/* * timeouts.c * * Created on: May 29, 2025 * Author: herli */ #include #include "timeouts.h" #include "tein_detection.h" #include "pre_injection.h" #include "can_port.h" #include "toothed_wheel.h" #if HAS_PREINJECTION #include "pre_injection.h" static uint16_t last_PI_tick = 0; #else static uint16_t last_CAN_msg_1_tick = 0; #endif #if defined(T06301) #include "ford_immo.h" #endif //#include "sync_pulse.c" uint32_t BitStatus = 0; uint32_t HiddenTimers = 0; static uint16_t last_CAN_msg_2_tick = 0; static uint16_t last_Idle_event_tick = 0; static uint16_t last_ICRPM_event_tick = 0; static uint16_t last_CaptorCorrect_event_tick = 0; static uint16_t last_BIP_event_tick = 0; static uint16_t last_TurnOff_event_tick = 0; static uint16_t last_CKPSignal_event_tick = 0; static uint16_t last_CKPSensor_event_tick = 0; static uint16_t last_SV_BIP_InsideTolerance_Timeout = 0; static uint16_t last_NOTIMPLEMENTED_event_tick = 0; static uint16_t last_BITZERO_event_tick = 0; static uint16_t last_CAN_msg_empf_1_tick = 0; static uint16_t last_CAN_msg_empf_2_tick = 0; static uint16_t last_CAN_msg_empf_4_tick = 0; static uint16_t last_CAN_msg_empf_3_boot_tick = 0; static uint16_t last_sync_pulse_boot_tick = 0; static uint8_t boot_em3_remaining = 0; // how many left to send after the first static uint16_t last_boot_em3_tick = 0; // last tick for this timeout static uint16_t last_startup_tick = 0; // last tick for this timeout #if HAS_PREINJECTION void Handle_PI_Timeout(void) { // Custom action on CAN timeout // e.g., trigger a CAN fault routine //si no hay sigo reseteandolo if(!active_PI){ Timeout_ResetByIndex(14, TIM16->CNT); // Reset turnoff timeout } //Timeout_ResetByIndexNoStatus(14, TIM16->CNT); //resetea sin poner a 0 el status } #else void Handle_Can_Timeout_1(void) { // Custom action on CAN timeout // e.g., trigger a CAN fault routine ME = 0.0f; } #endif void Handle_Can_Timeout_2(void) { // Custom action on CAN timeout // e.g., trigger a CAN fault routine ME = 0.0f; } void Handle_Idle_Timeout(void) { // Custom action on CAN timeout // e.g., trigger a CAN fault routine } uint8_t rpmoutCount = 0; extern volatile uint32_t prev_Difference; extern uint8_t hasCapturedTeeth; void Handle_IcRPM_Timeout(void) { // Handle RPM missing /*rpmoutCount++; //500 / 20ms = 25 if(rpmoutCount > 24){ RPM = 0; //estas son rpm pal can, pa que no de errores de COM. PHI_AD = 0; }else{ //Timeout_ResetByIndex(3, TIM16->CNT); // Reset rpm timeout Timeout_ResetByIndexNoStatus(3, TIM16->CNT); //resetea sin poner a 0 el status }*/ RPM = 0; //estas son rpm pal can, pa que no de errores de COM. PHI_AD = 0; hasCapturedTeeth = 0; prev_Difference = 0xFFFFFFFF; INJ_END(); Timeout_StopByIndex(3); // que sapague hasta que vuelva a turular Timeout_ResetByIndex(13, TIM16->CNT); // Reset CKP timeout Timeout_StopByIndex(13); // Reset CKP timeout Timeout_ResetByIndex(12, TIM16->CNT); // Reset CKP timeout Timeout_StopByIndex(12); // Reset CKP timeout Timeout_ResetByIndex(10, TIM16->CNT); // Reset CKP timeout Timeout_StopByIndex(10); // Reset CKP timeout FORCE_INJ_END(); } void Handle_CaptorDefect_Timeout(void) { TW_EVAL_MAX_TEETH(); Timeout_ResetByIndex(4, TIM16->CNT); // Reset turnoff timeout } void Handle_TurnOff_Timeout(void) { // Handle engine off event if(HAL_GPIO_ReadPin(SHUT_OFF_GPIO_Port, SHUT_OFF_Pin) != GPIO_PIN_RESET){ //si esta en alto OnEnd(); //SYNC_PULSE_TIM_STOP(); //Timeout_StopByIndex(11); //para los de ford se para el can en este msmo momento... }else{ Timeout_ResetByIndex(11, TIM16->CNT); // Reset turnoff timeout safetySHUTOFF = 0; //forceDC = 0; } } void Handle_BIP_Timeout(void) { // Handle not captured BIP TEIN_STATUS_ONFAULT(); } void Handle_CKP_NOSIGNAL_Timeout(void) { CKP_PULSE_AVAILABLE = 0; } void Handle_CKP_SENSOR_Timeout(void) { CKP_PULSE_AVAILABLE = 0; } void Handle_NOTIMPLEMENTED_Timeout(void) { // Handle not implemented //T_ein = 950; } void Handle_RPM_Low_Timeout(void) { if(RPM < CAN_RPM_SEND_ASYNC || safetySHUTOFF){ can_port_send_msg_def(&MSG_ID_EMPF1); } Timeout_ResetByIndex(16, TIM16->CNT); // Reset turnoff timeout } void Handle_EMPF2_TimeoutTick(void) { if(s_empf2_pending){ can_port_send_msg_def(&MSG_ID_EMPF2); s_empf2_pending = 0; } Timeout_ResetByIndex(17, TIM16->CNT); // Reset turnoff timeout } extern uint8_t startup_finished; extern uint8_t count; extern uint8_t startup_count; extern uint8_t startup_sent_count; extern uint8_t eps_fieona_override; extern void Fieona_SEND3_set_init(uint8_t u); void Handle_Boot_EMPF3_Timeout(void) { #if defined(T06301) if(!startup_finished) {//startup && Set_Timeout_Period_ByIndex(18, 400); /* FOR THE FORD CAN IMMO*/ if(!eps_fieona_override){ Fieona_SEND3_set_init(1); } can_port_send_msg_def(&MSG_ID_EMPF3); /* END FORD IMMO*/ if(startup_count){ Timeout_ResetByIndex(18, TIM16->CNT); // re-arm for another 40ms startup_count--; }else{ startup_finished = 1; } }else{ if(!eps_fieona_override){ Fieona_SEND3_set_init(0); } can_port_send_msg_def(&MSG_ID_EMPF3); Timeout_StopByIndex(18); // done } #else can_port_send_msg_def(&MSG_ID_EMPF3); if(!startup_finished) {//startup && Set_Timeout_Period_ByIndex(18, 150); startup_sent_count++; Timeout_ResetByIndex(18, TIM16->CNT); // re-arm for another 40ms }else{ Timeout_StopByIndex(18); // re-arm for another 40ms } #endif } void Handle_EMPF3_BootStart_Timeout(void){ #if defined(T06301) Timeout_ResetByIndex(18, TIM16->CNT); // re-arm for another 40ms #else Timeout_ResetByIndex(18, TIM16->CNT); // re-arm for another 40ms can_port_send_msg_def(&MSG_ID_EMPF1); Timeout_ResetByIndex(16, TIM16->CNT); // re-arm for another 40ms #endif Timeout_StopByIndex(21); // got to stop them because overflow } uint8_t s_empf4_due = 0; int counter = 0; #if defined(T06301) void Handle_EMPF4_TimeoutTick(void) { //s_empf4_due = 1; can_port_send_msg_def(&MSG_ID_EMPF4); uint16_t newtick = last_CAN_msg_empf_4_tick + 500; Timeout_ResetByIndex(20, newtick); // deberia mejorarlo bastante esto, en vez de FIEONA_advance(); } #endif void Handle_startup_Timeout(void){ startedEngine = 1; Timeout_ResetByIndex(0, TIM16->CNT); // Reset turnoff timeout Timeout_StopByIndex(0); Timeout_ResetByIndex(2, TIM16->CNT); // Reset turnoff timeout Timeout_StopByIndex(2); } void Handle_BITZERO_Timeout(void){ } #if defined(T06301) void Handle_SYNC_Pulse_BootStart_Timeout(void){ if(FORD_SYNC_PULSE_OUT){ SYNC_PULSE_TIM_START(); } Timeout_StartIfStopped(20, TIM16->CNT); // deberia mejorarlo bastante esto, en vez de Timeout_ResetByIndex(16, TIM16->CNT - 50); // Reset turnoff timeout Timeout_StopByIndex(22); // got to stop them because overflow } #endif void Handle_SV_BIP_OutOfTolerance_Timeout(void) { // Handle not implemented //T_ein = 950; } /*TimeoutEntry timeout_list[] = { { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 0), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 1), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_Idle_event_tick, 1000, &BitStatus, (1 << 2), Handle_Idle_Timeout, 1 }, // 100ms { &last_ICRPM_event_tick, 1200, &BitStatus, (1 << 3), Handle_IcRPM_Timeout, 1 }, // 20 ms //si en 20 no captura, abre can error, si en 500 sigue sin capturar, rpm = 0 { &last_CaptorCorrect_event_tick, 30000, &BitStatus, (1 << 4), Handle_CaptorDefect_Timeout, 0 }, // 3000ms { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 5), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 6), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 7), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 8), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 9), Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { &last_BIP_event_tick, 50000, &BitStatus, (1 << 10), Handle_BIP_Timeout, 0 }, // 5000 ms { &last_TurnOff_event_tick, 2500, &BitStatus, (1 << 11), Handle_TurnOff_Timeout, 0 }, // 250ms { &last_CKPSignal_event_tick, 5000, &BitStatus, (1 << 12), Handle_CKP_NOSIGNAL_Timeout, 0 }, // 10ms { &last_CKPSensor_event_tick, 3000, &BitStatus, (1 << 13), Handle_CKP_SENSOR_Timeout, 0 }, // 10ms, no tendrian que estar started... #if HAS_PREINJECTION { &last_PI_tick, 100, &BitStatus, (1 << 14), Handle_PI_Timeout, 1 }, // 500 ms #else { &last_CAN_msg_1_tick, 2500, &BitStatus, (1 << 14), Handle_Can_Timeout_1, 0 }, // 500 ms #endif { &last_CAN_msg_2_tick, 2500, &BitStatus, (1 << 15), Handle_Can_Timeout_2, 0 }, // 500 ms { &last_CAN_msg_empf_1_tick, 600, &HiddenTimers, (1 << 0), Handle_RPM_Low_Timeout, 1}, // 500 ms { &last_CAN_msg_empf_2_tick, CAN_EMPF2_INSTANT ? 10 : 600, &HiddenTimers, (1 << 1), Handle_EMPF2_TimeoutTick, 0}, // 500 ms { &last_boot_em3_tick, 400, &HiddenTimers, (1 << 2), Handle_Boot_EMPF3_Timeout, 0 }, { &last_startup_tick, 1000, &HiddenTimers, (1 << 3), Handle_startup_Timeout, 0 }, { &last_CAN_msg_empf_4_tick, 500, &HiddenTimers, (1 << 4), Handle_EMPF4_TimeoutTick, 1}, // 500 ms };*/ TimeoutEntry timeout_list[] = { #if defined(T06301) { 0, &last_BITZERO_event_tick, 10, &BitStatus, (1 << 0), 0, Handle_BITZERO_Timeout, 1 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 11), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_Idle_event_tick, 10, &BitStatus, (1 << 2), 0, Handle_Idle_Timeout, 1 }, // 100ms { 1, &last_ICRPM_event_tick, 1200, &HiddenTimers, (1 << 3), 0, Handle_IcRPM_Timeout, 1 }, // 20 ms //si en 20 no captura, abre can error, si en 500 sigue sin capturar, rpm = 0 { 1, &last_CaptorCorrect_event_tick, 30000, &HiddenTimers, (1 << 4), 0, Handle_CaptorDefect_Timeout, 0 }, // 3000ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 5), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 6), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 7), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 8), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 9), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 1, &last_BIP_event_tick, 50000, &HiddenTimers, (1 << 10), 0, Handle_BIP_Timeout, 0 }, // 5000 ms { 0, &last_TurnOff_event_tick, 2500, &BitStatus, (1 << 1), 0, Handle_TurnOff_Timeout, 1 }, // 250ms { 0, &last_CKPSignal_event_tick, 5000, &HiddenTimers, (1 << 12), 0, Handle_CKP_NOSIGNAL_Timeout, 0 }, // 10ms { 0, &last_CKPSensor_event_tick, 3000, &HiddenTimers, (1 << 13), 0, Handle_CKP_SENSOR_Timeout, 0 }, // 10ms, no tendrian que estar started... #if HAS_PREINJECTION { 1, &last_PI_tick, 100, &BitStatus, (1 << 14), 0, Handle_PI_Timeout, 1 }, // 500 ms #else { 0, &last_CAN_msg_1_tick, 2500, &HiddenTimers, (1 << 14), 0, Handle_Can_Timeout_1, 0 }, // 500 ms #endif { 1, &last_CAN_msg_2_tick, 50000, &HiddenTimers, (1 << 15), 0, Handle_Can_Timeout_2, 0 }, // 500 ms { 1, &last_CAN_msg_empf_1_tick, 600, &HiddenTimers, (1 << 0), 0, Handle_RPM_Low_Timeout, 0}, // 500 ms { 1, &last_CAN_msg_empf_2_tick, CAN_EMPF2_INSTANT ? 10 : 600, &HiddenTimers, (1 << 1), 0, Handle_EMPF2_TimeoutTick, 0}, // 500 ms { 1, &last_boot_em3_tick, 100, &HiddenTimers, (1 << 2), 0, Handle_Boot_EMPF3_Timeout, 0 }, { 1, &last_startup_tick, 1000, &HiddenTimers, (1 << 3), 0, Handle_startup_Timeout, 0 }, { 1, &last_CAN_msg_empf_4_tick, 500, &HiddenTimers, (1 << 4), 0, Handle_EMPF4_TimeoutTick, 0}, // 50 ms { 1, &last_CAN_msg_empf_3_boot_tick, 6200, &HiddenTimers, (1 << 5), 0, Handle_EMPF3_BootStart_Timeout, 1}, // 50 ms { 1, &last_sync_pulse_boot_tick, 950, &HiddenTimers, (1 << 6), 0, Handle_SYNC_Pulse_BootStart_Timeout, 1}, // 50 ms #else { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 0), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 1), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 1, &last_Idle_event_tick, 1000, &BitStatus, (1 << 2), 0, Handle_Idle_Timeout, 1 }, // 100ms { 1, &last_ICRPM_event_tick, 1200, &BitStatus, (1 << 3), 0, Handle_IcRPM_Timeout, 1 }, // 20 ms //si en 20 no captura, abre can error, si en 500 sigue sin capturar, rpm = 0 { 1, &last_CaptorCorrect_event_tick, 30000, &BitStatus, (1 << 4), 0, Handle_CaptorDefect_Timeout, 0 }, // 3000ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 5), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 6), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 7), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 1, &last_SV_BIP_InsideTolerance_Timeout, 65534, &BitStatus, (1 << 8), 0, Handle_SV_BIP_OutOfTolerance_Timeout, 0 }, // 10ms { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 9), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms { 1, &last_BIP_event_tick, 50000, &BitStatus, (1 << 10), 0, Handle_BIP_Timeout, 0 }, // 5000 ms { 1, &last_TurnOff_event_tick, 2500, &BitStatus, (1 << 11), 0, Handle_TurnOff_Timeout, 0 }, // 250ms { 1, &last_CKPSignal_event_tick, 5000, &BitStatus, (1 << 12), 0, Handle_CKP_NOSIGNAL_Timeout, 0 }, // 10ms { 1, &last_CKPSensor_event_tick, 3000, &BitStatus, (1 << 13), 0, Handle_CKP_SENSOR_Timeout, 0 }, // 10ms, no tendrian que estar started... #if HAS_PREINJECTION { 1, &last_PI_tick, 100, &BitStatus, (1 << 14), 0, Handle_PI_Timeout, 1 }, // 500 ms #else { 1, &last_CAN_msg_1_tick, 2500, &BitStatus, (1 << 14), 0, Handle_Can_Timeout_1, 0 }, // 500 ms #endif { 1, &last_CAN_msg_2_tick, 2500, &BitStatus, (1 << 15), 0, Handle_Can_Timeout_2, 0 }, // 500 ms { 1, &last_CAN_msg_empf_1_tick, 600, &HiddenTimers, (1 << 0), 0, Handle_RPM_Low_Timeout, 0}, // 500 ms { 1, &last_CAN_msg_empf_2_tick, CAN_EMPF2_INSTANT ? 10 : 600, &HiddenTimers, (1 << 1), 0, Handle_EMPF2_TimeoutTick, 0}, // 500 ms { 1, &last_boot_em3_tick, 100, &HiddenTimers, (1 << 2), 0, Handle_Boot_EMPF3_Timeout, 0 }, { 1, &last_startup_tick, 1000, &HiddenTimers, (1 << 3), 0, Handle_startup_Timeout, 0 }, { 0, &last_NOTIMPLEMENTED_event_tick, 100, &BitStatus, (1 << 4), 0, Handle_NOTIMPLEMENTED_Timeout, 0 }, // 10ms #if defined(T06211) { 1, &last_CAN_msg_empf_3_boot_tick, 3500, &HiddenTimers, (1 << 5), 0, Handle_EMPF3_BootStart_Timeout, 1}, // 50 ms #else { 1, &last_CAN_msg_empf_3_boot_tick, 75, &HiddenTimers, (1 << 5), 0, Handle_EMPF3_BootStart_Timeout, 1}, // 50 ms #endif #endif }; const size_t timeout_list_size = sizeof(timeout_list) / sizeof(timeout_list[0]); uint8_t has_timed_out(uint16_t start, uint16_t duration) { uint16_t now = TIM16->CNT; return ((uint16_t)(now - start)) > duration; } void CheckTimeouts(uint16_t current_time, TimeoutEntry* timeouts) { for (size_t i = 0; i < timeout_list_size; ++i) { if(!timeouts[i].enabled){continue;} if (timeouts[i].started && has_timed_out(*(timeouts[i].last_tick_ptr), timeouts[i].timeout_duration)) { *(timeouts[i].status_bit_ptr) |= timeouts[i].bit_mask; // Call the timeout handler if one is defined if (timeouts[i].on_timeout != NULL) { timeouts[i].on_timeout(); } } else { //*(timeouts[i].status_bit_ptr) &= ~(timeouts[i].bit_mask); } } } void Timeout_Reset(uint16_t* tick_ptr, uint16_t new_tick, uint16_t* status_ptr, uint16_t bit_mask) { if (tick_ptr) { *tick_ptr = new_tick; } if (status_ptr) { *status_ptr &= ~bit_mask; // Clear the sticky timeout bit //status |= BIT(n); for inverted } } void Timeout_ResetByIndex(uint8_t index, uint16_t new_tick) { if (index < timeout_list_size) { *timeout_list[index].last_tick_ptr = new_tick; *timeout_list[index].status_bit_ptr &= ~(timeout_list[index].bit_mask); if (!timeout_list[index].started){ timeout_list[index].started = 1; } } } /*void Timeout_ResetByIndex_Compliant(uint8_t index) { if (index < timeout_list_size) { uint16_t new_tick = timeout_list[index].last_tick_ptr + timeout_list[index].timeout_duration; *timeout_list[index].last_tick_ptr = new_tick; *timeout_list[index].status_bit_ptr &= ~(timeout_list[index].bit_mask); if (!timeout_list[index].started){ timeout_list[index].started = 1; } } }*/ void Timeout_ResetByIndexNoStatus(uint8_t index, uint16_t new_tick) { if (index < timeout_list_size) { *timeout_list[index].last_tick_ptr = new_tick; if (!timeout_list[index].started){ timeout_list[index].started = 1; } } } void Timeout_StopByIndex(uint8_t index){ if (index < timeout_list_size){ timeout_list[index].started = 0; } } void Set_Timeout_Period_ByIndex(uint8_t index, uint16_t period){ if (index < timeout_list_size){ timeout_list[index].timeout_duration = period; } } uint16_t* Timeout_GetCanTickPtr(void) { return &last_CAN_msg_2_tick; } uint16_t* Timeout_GetIcRPMTickPtr(void) { return &last_ICRPM_event_tick; } uint16_t* Timeout_GetTurnOffTickPtr(void) { return &last_TurnOff_event_tick; } void Timeout_CheckAll(uint16_t now) { CheckTimeouts(now, timeout_list); } bool Timeout_IsStarted(uint8_t index) { if (index >= timeout_list_size) return false; return timeout_list[index].started != 0; } void Timeout_StartIfStopped(uint8_t index, uint16_t now) { if (index >= timeout_list_size) return; if (!timeout_list[index].started) { *timeout_list[index].last_tick_ptr = now; timeout_list[index].started = 1; // do NOT touch status bit here } } bool Timeout_HasElapsed(uint8_t index, uint16_t now) { if (index >= timeout_list_size) return false; return has_timed_out(*timeout_list[index].last_tick_ptr, timeout_list[index].timeout_duration); } void Timeout_PollActions(void) { /*if (s_empf4_due) { s_empf4_due = 0; // Now safe: called from "normal" context can_port_send_msg_def(&MSG_ID_EMPF4); FIEONA_advance(); }*/ } /*void Timeout_Stop(uint8_t idx, uint16_t now) { if (idx >= timeout_list_size) return; timeout_list[idx].started = 0; *timeout_list[idx].last_tick_ptr = now; // optional, keeps a reference point }*/