From 194f1ca6c0fec73dfc49460c6427ec64f097fb11 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 8 Jan 2026 21:58:59 -0800 Subject: [PATCH 1/7] The beginnings of state machine implementation Co-authored-by: Ng0710 Co-authored-by: Thomas Xu --- ECU/Application/Inc/StateData.h | 19 +++++-- ECU/Application/Src/StateTicks.c | 92 ++++++++++++++++++++++---------- ECU/Application/Src/StateUtils.c | 3 ++ 3 files changed, 83 insertions(+), 31 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 5094af7e..e9c19473 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -19,11 +19,21 @@ * logic to access and modify the ECU's operational data. */ typedef struct ECU_StateData { - // DON'T TOUCH YET - GR_OLD_ECU_STATUS_1_MSG ecuStatus1; - GR_OLD_ECU_STATUS_2_MSG ecuStatus2; - GR_OLD_ECU_STATUS_3_MSG ecuStatus3; + // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs + // TODO: Remove unneeded states + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ + uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ + uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ + uint8_t glv_soc; /** GLV SoC, 20x/51=% */ + uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ + uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ + uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ + uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ + uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ + + GR_ECU_State ecu_state; int32_t dischargeStartMillis; uint32_t lastECUStatusMsgTick; uint32_t lastTSSIFlash; @@ -39,6 +49,7 @@ typedef struct ECU_StateData { uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; + uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index c45fab6c..eca3e110 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -16,11 +16,19 @@ */ ECU_StateData stateLump = {0}; +#define ECU_STATUS_MSG_PERIOD (100) +#define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time + void ECU_State_Tick(void) { - LOGOMATIC("ECU Current State: %d\n", stateLump.ecuStatus1.ecu_status); + if(stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD){ + LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); + stateLump.lastECUStatusMsgTick = 0; + } else{ + stateLump.lastECUStatusMsgTick++; + } - switch (stateLump.ecuStatus1.ecu_status) { + switch (stateLump.ecu_state) { case GR_GLV_OFF: ECU_GLV_Off(&stateLump); break; @@ -41,9 +49,9 @@ void ECU_State_Tick(void) break; default: LOGOMATIC("ECU Current State Unknown: %d\n", - stateLump.ecuStatus1.ecu_status); + stateLump.ecu_state); LOGOMATIC("ECU: Resetting to GLV On\n"); - stateLump.ecuStatus1.ecu_status = GR_GLV_ON; + stateLump.ecu_state = GR_GLV_ON; break; } } @@ -64,35 +72,30 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - UNUSED(stateData); - /* - if(stateData->TractiveSystemVoltage >= 60){ // should never happen but - has to be accounted for stateData->currentState = GR_TS_DISCHARGE; - emit an error - break; + if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; } - */ // TODO Implement functionality if (stateData->ts_active_button_engaged) { - stateData->ecuStatus1.ecu_status = GR_PRECHARGE_ENGAGED; + stateData->ecu_state = GR_PRECHARGE_ENGAGED; } } void ECU_Precharge_Engaged(ECU_StateData *stateData) { - UNUSED(stateData); - if (stateData->ecuStatus2.ts_voltage > 60) { - // Go to TS discharge - stateData->ecuStatus1.ecu_status = GR_TS_DISCHARGE; - // Emit an error + if (stateData->ts_voltage >= 60) { + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error return; } // TODO Implement functionality - /*if(not TS Active || Communication Error (CAN)){ - stateData->currentState = GR_TS_DISCHARGE - break; - }*/ + if(!stateData->ts_active_button_engaged || CommunicationError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } /*if(1 Isolation relay close && second isolation relay close){ --> CAN! stateData->currentState = GR_PRECHARGE_COMPLETE }*/ @@ -100,7 +103,6 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) void ECU_Precharge_Complete(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* On but idle @@ -112,7 +114,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (TS pressed or critical error) { stateData->currentState = GR_TS_DISCHARGE emit error - break; + return; } */ /* @@ -122,11 +124,19 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) */ // Pseudocode + if(stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; + } + + if(PressingBrake(stateData) && stateData->rtd_button_engaged){ + stateData->ecu_state = GR_DRIVE_ACTIVE; + } } void ECU_Drive_Active(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* If APPS/BSE Violation --> Don't drive until resolved (no state @@ -152,21 +162,49 @@ void ECU_Drive_Active(ECU_StateData *stateData) - calcPedalTravel func :p - make tuna-ble function */ + + if(!stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } + + if(!stateData->rtd_button_engaged){ + stateData->ecu_state = GR_PRECHARGE_COMPLETE; + // emit a warning if not moving + return; + } +} + +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { + stateData->ecu_state = GR_TS_DISCHARGE; + LOGOMATIC("tell the BCU to discharge TS"); + stateData->dischargeStartMillis = 0; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality of state itself /* Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ - if (stateData->ecuStatus2.ts_voltage < 60) { - stateData->ecuStatus1.ecu_status = GR_GLV_ON; + // TODO: Discharge TC through CAN + if (stateData->ts_voltage < 60) { + stateData->ecu_state = GR_GLV_ON; + stateData->dischargeStartMillis = 0; + return; } /* If TS fails to discharge over time then stay and emit a warning, see #129 */ + // TODO: Determine the maximum time to wait for TC to discharge. + if(stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME){ + // TODO: Research appropriate ways to buffer warning messages. + LOGOMATIC("Tractive System fails to discharge in time."); + } + + if(stateData->dischargeStartMillis < INT32_MAX){ + stateData->dischargeStartMillis++; + } } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 24c3b6e0..97e3c5ea 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -36,6 +36,9 @@ bool CriticalError(const ECU_StateData *stateData) if (stateData->ecuStatus2.ts_voltage > 600) { return true; } + if (stateData->bse_apps_violation) { + return true; + } return false; } From d3c93228d2d17c24c7460111608234ff0215315c Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 8 Jan 2026 21:58:59 -0800 Subject: [PATCH 2/7] The beginnings of state machine implementation Co-authored-by: Ng0710 Co-authored-by: Thomas Xu --- ECU/Application/Inc/StateData.h | 19 +++++-- ECU/Application/Src/StateTicks.c | 90 +++++++++++++++++++++++--------- ECU/Application/Src/StateUtils.c | 3 ++ 3 files changed, 82 insertions(+), 30 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index 5094af7e..e9c19473 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -19,11 +19,21 @@ * logic to access and modify the ECU's operational data. */ typedef struct ECU_StateData { - // DON'T TOUCH YET - GR_OLD_ECU_STATUS_1_MSG ecuStatus1; - GR_OLD_ECU_STATUS_2_MSG ecuStatus2; - GR_OLD_ECU_STATUS_3_MSG ecuStatus3; + // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs + // TODO: Remove unneeded states + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ + uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ + uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ + uint8_t glv_soc; /** GLV SoC, 20x/51=% */ + uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ + uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ + uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ + uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ + uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ + + GR_ECU_State ecu_state; int32_t dischargeStartMillis; uint32_t lastECUStatusMsgTick; uint32_t lastTSSIFlash; @@ -39,6 +49,7 @@ typedef struct ECU_StateData { uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; + uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index a8cf0738..1753a0fc 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -16,11 +16,19 @@ */ ECU_StateData stateLump = {0}; +#define ECU_STATUS_MSG_PERIOD (100) +#define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time + void ECU_State_Tick(void) { - LOGOMATIC("ECU Current State: %d\n", stateLump.ecuStatus1.ecu_status); + if(stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD){ + LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); + stateLump.lastECUStatusMsgTick = 0; + } else{ + stateLump.lastECUStatusMsgTick++; + } - switch (stateLump.ecuStatus1.ecu_status) { + switch (stateLump.ecu_state) { case GR_GLV_OFF: ECU_GLV_Off(&stateLump); break; @@ -42,7 +50,7 @@ void ECU_State_Tick(void) default: LOGOMATIC("ECU Current State Unknown: %d\n", stateLump.ecuStatus1.ecu_status); LOGOMATIC("ECU: Resetting to GLV On\n"); - stateLump.ecuStatus1.ecu_status = GR_GLV_ON; + stateLump.ecu_state = GR_GLV_ON; break; } } @@ -63,35 +71,30 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - UNUSED(stateData); - /* - if(stateData->TractiveSystemVoltage >= 60){ // should never happen but - has to be accounted for stateData->currentState = GR_TS_DISCHARGE; - emit an error - break; + if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; } - */ // TODO Implement functionality if (stateData->ts_active_button_engaged) { - stateData->ecuStatus1.ecu_status = GR_PRECHARGE_ENGAGED; + stateData->ecu_state = GR_PRECHARGE_ENGAGED; } } void ECU_Precharge_Engaged(ECU_StateData *stateData) { - UNUSED(stateData); - if (stateData->ecuStatus2.ts_voltage > 60) { - // Go to TS discharge - stateData->ecuStatus1.ecu_status = GR_TS_DISCHARGE; - // Emit an error + if (stateData->ts_voltage >= 60) { + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error return; } // TODO Implement functionality - /*if(not TS Active || Communication Error (CAN)){ - stateData->currentState = GR_TS_DISCHARGE - break; - }*/ + if(!stateData->ts_active_button_engaged || CommunicationError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } /*if(1 Isolation relay close && second isolation relay close){ --> CAN! stateData->currentState = GR_PRECHARGE_COMPLETE }*/ @@ -99,7 +102,6 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) void ECU_Precharge_Complete(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* On but idle @@ -111,7 +113,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) if (TS pressed or critical error) { stateData->currentState = GR_TS_DISCHARGE emit error - break; + return; } */ /* @@ -121,11 +123,19 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) */ // Pseudocode + if(stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + // emit an error + return; + } + + if(PressingBrake(stateData) && stateData->rtd_button_engaged){ + stateData->ecu_state = GR_DRIVE_ACTIVE; + } } void ECU_Drive_Active(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality /* If APPS/BSE Violation --> Don't drive until resolved (no state @@ -151,21 +161,49 @@ void ECU_Drive_Active(ECU_StateData *stateData) - calcPedalTravel func :p - make tuna-ble function */ + + if(!stateData->ts_active_button_engaged || CriticalError(stateData)){ + ECU_Tractive_System_Discharge_Start(stateData); + return; + } + + if(!stateData->rtd_button_engaged){ + stateData->ecu_state = GR_PRECHARGE_COMPLETE; + // emit a warning if not moving + return; + } +} + +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { + stateData->ecu_state = GR_TS_DISCHARGE; + LOGOMATIC("tell the BCU to discharge TS"); + stateData->dischargeStartMillis = 0; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) { - UNUSED(stateData); // TODO Implement functionality of state itself /* Discharge the tractive system to below 60 volts If TS voltage < 60 --> stateData->GLV_ON */ - if (stateData->ecuStatus2.ts_voltage < 60) { - stateData->ecuStatus1.ecu_status = GR_GLV_ON; + // TODO: Discharge TC through CAN + if (stateData->ts_voltage < 60) { + stateData->ecu_state = GR_GLV_ON; + stateData->dischargeStartMillis = 0; + return; } /* If TS fails to discharge over time then stay and emit a warning, see #129 */ + // TODO: Determine the maximum time to wait for TC to discharge. + if(stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME){ + // TODO: Research appropriate ways to buffer warning messages. + LOGOMATIC("Tractive System fails to discharge in time."); + } + + if(stateData->dischargeStartMillis < INT32_MAX){ + stateData->dischargeStartMillis++; + } } diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 6e8b4604..cecc65a6 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -36,6 +36,9 @@ bool CriticalError(const ECU_StateData *stateData) if (stateData->ecuStatus2.ts_voltage > 600) { return true; } + if (stateData->bse_apps_violation) { + return true; + } return false; } From c1ed33e6fb770b7d52779aca64f20a3c98bbc660 Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Thu, 8 Jan 2026 22:41:55 -0800 Subject: [PATCH 3/7] Added the function signature of ECU_Tractive_System_Discharge_Start in the header file. --- ECU/Application/Inc/StateTicks.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index 6844ceb8..42f633da 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -68,6 +68,18 @@ void ECU_Precharge_Complete(ECU_StateData *stateData); */ void ECU_Drive_Active(ECU_StateData *stateData); +/** + * @brief Init function for ECU_Tractive_System_Discharge_Start. + * + * Resets Tractive System discharge timer and switches on the Tractive System + * Discharge state. + * + * @param stateData Pointer to the ECU state data structure. + * + * @return void + */ +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); + /** * @brief State handler for the Tractive System Discharge state. * From 35bc726dd2c5fd1b8446adc7d673699c9b873216 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:30:22 +0000 Subject: [PATCH 4/7] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateData.h | 14 +++++++------- ECU/Application/Src/StateTicks.c | 29 +++++++++++++++-------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e9c19473..5562e8c0 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -22,16 +22,16 @@ typedef struct ECU_StateData { // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs // TODO: Remove unneeded states - int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ uint8_t glv_soc; /** GLV SoC, 20x/51=% */ - uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ - uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ - uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ - uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ - uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ + uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ + uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ + uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ + uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ + uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ GR_ECU_State ecu_state; int32_t dischargeStartMillis; @@ -49,7 +49,7 @@ typedef struct ECU_StateData { uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; - uint16_t ts_voltage; /** TS output voltage, 0.01V */ + uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 1753a0fc..85412660 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -21,10 +21,10 @@ ECU_StateData stateLump = {0}; void ECU_State_Tick(void) { - if(stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD){ + if (stateLump.lastECUStatusMsgTick >= ECU_STATUS_MSG_PERIOD) { LOGOMATIC("ECU Current State: %d\n", stateLump.ecu_state); stateLump.lastECUStatusMsgTick = 0; - } else{ + } else { stateLump.lastECUStatusMsgTick++; } @@ -71,7 +71,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; @@ -91,7 +91,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) return; } // TODO Implement functionality - if(!stateData->ts_active_button_engaged || CommunicationError(stateData)){ + if (!stateData->ts_active_button_engaged || CommunicationError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; } @@ -123,13 +123,13 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) */ // Pseudocode - if(stateData->ts_active_button_engaged || CriticalError(stateData)){ + if (stateData->ts_active_button_engaged || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; } - if(PressingBrake(stateData) && stateData->rtd_button_engaged){ + if (PressingBrake(stateData) && stateData->rtd_button_engaged) { stateData->ecu_state = GR_DRIVE_ACTIVE; } } @@ -162,22 +162,23 @@ void ECU_Drive_Active(ECU_StateData *stateData) - make tuna-ble function */ - if(!stateData->ts_active_button_engaged || CriticalError(stateData)){ + if (!stateData->ts_active_button_engaged || CriticalError(stateData)) { ECU_Tractive_System_Discharge_Start(stateData); return; } - if(!stateData->rtd_button_engaged){ + if (!stateData->rtd_button_engaged) { stateData->ecu_state = GR_PRECHARGE_COMPLETE; // emit a warning if not moving return; } } -void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) { - stateData->ecu_state = GR_TS_DISCHARGE; - LOGOMATIC("tell the BCU to discharge TS"); - stateData->dischargeStartMillis = 0; +void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) +{ + stateData->ecu_state = GR_TS_DISCHARGE; + LOGOMATIC("tell the BCU to discharge TS"); + stateData->dischargeStartMillis = 0; } void ECU_Tractive_System_Discharge(ECU_StateData *stateData) @@ -198,12 +199,12 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData) see #129 */ // TODO: Determine the maximum time to wait for TC to discharge. - if(stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME){ + if (stateData->dischargeStartMillis > TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME) { // TODO: Research appropriate ways to buffer warning messages. LOGOMATIC("Tractive System fails to discharge in time."); } - if(stateData->dischargeStartMillis < INT32_MAX){ + if (stateData->dischargeStartMillis < INT32_MAX) { stateData->dischargeStartMillis++; } } From 11142415a530db0daec011dbbe9eeadffe77b283 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Mon, 12 Jan 2026 21:47:43 -0800 Subject: [PATCH 5/7] cleaned up data, switched to floats, etc --- ECU/Application/Inc/StateData.h | 37 ++++++++++++++++++++------------ ECU/Application/Src/StateUtils.c | 4 ++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e9c19473..e7504412 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -20,37 +20,46 @@ */ typedef struct ECU_StateData { - // These states are copied from the GR_OLD_ECU_STATUS_#_MSG structs // TODO: Remove unneeded states - int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ - uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ - uint8_t max_cell_temp; /** Hottest cell temp, 0.25°C/bit */ - uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ - uint8_t glv_soc; /** GLV SoC, 20x/51=% */ - uint16_t vehicle_speed; /** Vehicle speed, 0.01 MPH */ - uint16_t fr_wheel_rpm; /** FR wheel, 0.1x-3276.8 RPM */ - uint16_t fl_wheel_rpm; /** FL wheel, 0.1x-3276.8 RPM */ - uint16_t rr_wheel_rpm; /** RR wheel, 0.1x-3276.8 RPM */ - uint16_t rl_wheel_rpm; /** RL wheel, 0.1x-3276.8 RPM */ - - GR_ECU_State ecu_state; int32_t dischargeStartMillis; uint32_t lastECUStatusMsgTick; uint32_t lastTSSIFlash; int32_t last_drive_active_control_ms; + float min_amk_heat_cap_throttle_percent; + float ts_voltage; + float max_cell_temp; /** Temperature of hottest cell, celsius */ + + float vehicle_speed; /** Vehicle speed, MPH */ + float fr_wheel_rpm; /** FR wheel, RPM */ + float fl_wheel_rpm; /** FL wheel, RPM */ + float rr_wheel_rpm; /** RRv wheel, RPM */ + float rl_wheel_rpm; /** RL wheel, RPM */ + + // 0.5V when things go to shit (X_OK low) + // 3V when things almost poggers (X_OK high but SDC not reset) + // 2.4V when things are actually poggers (X_OK high and SDC is not triggered) + float ams_sense; + float imd_sense; + float bspd_sense; + + float estop_sense; uint16_t driving_heat_capacity_1; uint16_t driving_heat_capacity_2; uint16_t APPS1_Signal; uint16_t APPS2_Signal; uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ + uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ + uint8_t glv_soc; /** GLV SoC, 20x/51=% */ uint8_t acu_error_warning_bits; uint8_t inverter_fault_map; bool bse_apps_violation; bool ts_active_button_engaged; - uint16_t ts_voltage; /** TS output voltage, 0.01V */ bool rtd_button_engaged; + GR_ECU_State ecu_state; } ECU_StateData; // FIXME Add comments to each data field with descriptions and // rules (eg -1 = invalid?, etc) // Will also need to add information from ADC into this struct diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index cecc65a6..116d94dc 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -30,10 +30,10 @@ void setSoftwareLatch(bool close) bool CriticalError(const ECU_StateData *stateData) { - if (stateData->ecuStatus1.max_cell_temp > 60) { + if (stateData->max_cell_temp > 60) { return true; } - if (stateData->ecuStatus2.ts_voltage > 600) { + if (stateData->ts_voltage > 600) { return true; } if (stateData->bse_apps_violation) { From 4008051b963d6ef48c4832977f106923a930afae Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 05:51:06 +0000 Subject: [PATCH 6/7] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Inc/StateData.h | 12 ++++++------ ECU/Application/Src/StateTicks.c | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index e7504412..fc4c49f6 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -28,13 +28,13 @@ typedef struct ECU_StateData { float min_amk_heat_cap_throttle_percent; float ts_voltage; - float max_cell_temp; /** Temperature of hottest cell, celsius */ + float max_cell_temp; /** Temperature of hottest cell, celsius */ float vehicle_speed; /** Vehicle speed, MPH */ - float fr_wheel_rpm; /** FR wheel, RPM */ - float fl_wheel_rpm; /** FL wheel, RPM */ - float rr_wheel_rpm; /** RRv wheel, RPM */ - float rl_wheel_rpm; /** RL wheel, RPM */ + float fr_wheel_rpm; /** FR wheel, RPM */ + float fl_wheel_rpm; /** FL wheel, RPM */ + float rr_wheel_rpm; /** RRv wheel, RPM */ + float rl_wheel_rpm; /** RL wheel, RPM */ // 0.5V when things go to shit (X_OK low) // 3V when things almost poggers (X_OK high but SDC not reset) @@ -50,7 +50,7 @@ typedef struct ECU_StateData { uint16_t APPS2_Signal; uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; - int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ + int8_t ping_block[3]; /** Node timeout status bits (1=OK, 0=Timeout) */ uint8_t powerlevel_torquemap; /** Power lvl (4b) & torque map (4b) */ uint8_t tractivebattery_soc; /** Accumulator SoC, 20x/51=% */ uint8_t glv_soc; /** GLV SoC, 20x/51=% */ diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index cc5aadd3..beccad86 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -48,8 +48,7 @@ void ECU_State_Tick(void) ECU_Tractive_System_Discharge(&stateLump); break; default: - LOGOMATIC("ECU Current State Unknown: %d\n", - stateLump.ecu_state); + LOGOMATIC("ECU Current State Unknown: %d\n", stateLump.ecu_state); LOGOMATIC("ECU: Resetting to GLV On\n"); stateLump.ecu_state = GR_GLV_ON; break; @@ -72,7 +71,7 @@ void ECU_GLV_Off(ECU_StateData *stateData) void ECU_GLV_On(ECU_StateData *stateData) { - if(stateData->ts_voltage >= 60){ // should never happen but has to be accounted for + if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for ECU_Tractive_System_Discharge_Start(stateData); // emit an error return; From a72a587ce2901530cf09333622a917009f2c0e7f Mon Sep 17 00:00:00 2001 From: Thomas Xu Date: Mon, 12 Jan 2026 21:54:31 -0800 Subject: [PATCH 7/7] add a placeholder --- ECU/Application/Src/StateTicks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index beccad86..95ef1e81 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -189,6 +189,7 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData) If TS voltage < 60 --> stateData->GLV_ON */ // TODO: Discharge TC through CAN + LOGOMATIC("CAN: please discharge the Tractive System"); if (stateData->ts_voltage < 60) { stateData->ecu_state = GR_GLV_ON; stateData->dischargeStartMillis = 0;