From 194f1ca6c0fec73dfc49460c6427ec64f097fb11 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 8 Jan 2026 21:58:59 -0800 Subject: [PATCH 01/21] 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 02/21] 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 03/21] 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 04/21] 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 05/21] 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 06/21] 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 07/21] 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; From f33172ead817903409d47ef25abbe73bb81d86e8 Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 15 Jan 2026 19:45:32 -0800 Subject: [PATCH 08/21] volatile state lump --- ECU/Application/Src/StateTicks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 95ef1e81..a39ad113 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -14,7 +14,7 @@ * * @remark Intentionally not a globally accessible variable */ -ECU_StateData stateLump = {0}; +volatile ECU_StateData stateLump = {0}; #define ECU_STATUS_MSG_PERIOD (100) #define TRACTIVE_SYSTEM_MAX_DISCHARGE_TIME (10000) // TODO: determine an appropriate wait time From 6a27ff107c0c8074c6275c3f7cd471c69c903bcf Mon Sep 17 00:00:00 2001 From: Casey Zwicker Date: Thu, 15 Jan 2026 19:51:19 -0800 Subject: [PATCH 09/21] scopes --- Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c index 22eeaf29..db2a98ce 100644 --- a/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c +++ b/Lib/FancyLayers-RENAME/ADC/Src/gr_adc.c @@ -140,10 +140,10 @@ void DMA_Init(DMA_TypeDef *DMA, DMA_Channel channel, uint32_t src_address, uint3 // NOTE: DMA init is still using NOINCREMENT // TODO: Add int n to consider last n values -int num = 0; -uint8_t filled = 0; void ADC_UpdateAnalogValues(uint16_t **adcDataValues, volatile uint16_t *new_values, int num_signals, int window_size, uint16_t *weighted_output) { + static int num = 0; + static uint8_t filled = 0; for (int i = 0; i < num_signals; ++i) { weighted_output[i] += (new_values[i] - (filled ? adcDataValues[i][num] : 0)) / window_size; // Update the average adcDataValues[i][num] = new_values[i]; From cec19d0dab9805b10a7b67fb2b5265f06cff2960 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 15 Jan 2026 23:21:38 -0800 Subject: [PATCH 10/21] adc basic functionality to ECU --- ECU/Application/Inc/StateData.h | 1 + ECU/Application/Src/StateTicks.c | 1 + ECU/Application/Src/StateUtils.c | 14 +++ ECU/Core/Src/main.c | 172 ++++++++++++++++++++++++++++++- 4 files changed, 187 insertions(+), 1 deletion(-) diff --git a/ECU/Application/Inc/StateData.h b/ECU/Application/Inc/StateData.h index fc4c49f6..0da61b53 100644 --- a/ECU/Application/Inc/StateData.h +++ b/ECU/Application/Inc/StateData.h @@ -50,6 +50,7 @@ typedef struct ECU_StateData { uint16_t APPS2_Signal; uint16_t Brake_R_Signal; uint16_t Brake_F_Signal; + uint16_t STEERING_ANGLE_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=% */ diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index a39ad113..6a0ac64e 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -6,6 +6,7 @@ #include "StateUtils.h" #include "Unused.h" + /** * @brief The ECU state data lump. * diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 116d94dc..95fa2639 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -6,6 +6,7 @@ #include "StateData.h" #include "Unused.h" +// use estop_sense to detect close(?) void setSoftwareLatch(bool close) { UNUSED(close); @@ -26,6 +27,19 @@ void setSoftwareLatch(bool close) SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } */ + + if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already + written too + { + HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); + } + else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin)) + { + HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } bool CriticalError(const ECU_StateData *stateData) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 1897c985..5157e9e0 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -18,7 +18,9 @@ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" - +#include "gr_adc.h" +#include "StateTicks.h" +#include "StateData.h" #include "adc.h" #include "dma.h" #include "fdcan.h" @@ -52,6 +54,60 @@ /* USER CODE END PV */ + + +/* +RELAVANT PORTS AND PINS + +-- ANALOG IN -- +ADC 1 (ADC_1 BUFFERS array is IN ORDER from top to bottom of this list) +BSE_SIGNAL (8): PC0 -> ADC12_IN6 (ADC 1 and ADC 2) +BSPD_SIGNAL (9): PC1 -> ADC12_IN7 +APPS1_SIGNAL (10): PC2 -> ADC12_IN8 +APPS2_SIGNAL (11): PC3 -> ADC12_IN9 +BRAKE_F_SIGNAL (24): PB0 -> ADC1_IN15 +BRAKE_R_SIGNAL (25): PB1 -> ADC1_IN12 +AUX_SIGNAL (36): PB14 -> ADC1_IN5 + + ADC 2 +STEERING_ANGLE_SIGNAL (37): PB15 -> ADC2_IN15 + +-- DIGITAL IN -- +BSPD_SENSE (19): PA5 +IMD_SENSE (20): PA6 +AMS_SENSE (21): PA7 +TS_ACTIVE_BTN_SENSE (54): PC12 +RTD_BTN_SENSE (53): PC11 +INERTIA_SW_SENSE (52): PC10 +ESTOP_SENSE (51): PA15 + +-- DIGITAL OUT -- +RTD_CONTROL (60): PB7 +TSSI_R_CONTROL (59): PB6 +TSSI_G_CONTROL (58): PB5 +BRAKE_CONTROL (57): PB4 +TS_ACTIVE_BTN_LED_CONTROL (43): PA9 +RTD_BTN_LED_CONTROL (42): PA8 +*/ + +// ADC 1/2 +#define WINDOW_SIZE 10 // weighted average for now can extend to other window functions +#define NUM_SIGNALS_ADC1 7 +#define NUM_SIGNALS_ADC2 1 +#define NUM_SIGNALS_DIGITAL 7 +// TODO: check which data size to use (floats...ints...etc) +volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values +volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values +uint16_t ADC1_outputs[NUM_SIGNALS_ADC1] = {0}; // Updated averages +uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages +uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array + +// DIGITAL +uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; + +// STATE DATA +extern ECU_StateData stateLump; + /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ @@ -74,6 +130,112 @@ static void ITM_Enable(void) } /* USER CODE END 0 */ +// TODO: state data stores stuff as either FLOATS or BOOLS...check +void read_digital(void) { + for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { + GPIO_PinState currRead; + switch(i) { + case 0: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_5); + break; + case 1: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_6); + break; + case 2: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_7); + break; + case 3: + currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_12); + break; + case 4: + currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_11); + break; + case 5: + currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_10); + break; + case 6: + currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_15); + break; + } + digital_data[i] = currRead + } +} + +void write_state_data() { + // analog + // TODO: bse signal idk what to do ADC1_outputs[0] + // TODO: bspd signal idk what to do ADC1_outputs[1] + stateLump.APPS1_SIGNAL = ADC1_outputs[2]; + stateLump.APPS2_SIGNAL = ADC1_outputs[3]; + stateLump.Brake_F_Signal = ADC1_outputs[4]; + stateLump.Brake_R_Signal = ADC1_outputs[5]; + // TODO: Aux signal idk what to do with it ADC1_outputs[6] + stateLump.STEERING_ANGLE_SIGNAL = ADC2_outputs[0]; + + // digital + stateLump.bspd_sense = digital_data[0]; + stateLump.imd_sense = digital_data[1]; + stateLump.ams_sense = digital_data[2]; + stateLump.ts_active_button_engaged = digital_data[3]; + stateLump.rtd_button_engaged = digital_data[4]; + stateLump.bspd_sense = digital_data[5]; + // TODO: inertia steering wheel sense? digital_data[6] + stateLump.estop_sense = digital_data[7]; +} + +void ADC_Configure(void) +{ + // Initialize which clock source to use + LL_RCC_SetADCClockSource(LL_RCC_ADC12_CLKSOURCE_SYSCLK); + /* Peripheral clock enable */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); + + // Initialize the ADC1 + ADC_Group_Init(ADC1, PS_8); // TODO: change prescalar l8r + ADC_Init(ADC1, RESOLUTION_12, RIGHT); + ADC_Regular_Group_Init(ADC1, NO_RANKS); + + // TODO: INITIALIZE PIN_PORTS BETTER!!! + // Initialize the pins and channels + Pin_Ports p1 = {0}; + p1.port = GPIOC; + p1.pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | LL_GPIO_PIN_3; + ADC_Init_Pins(&p1); + Pin_Ports p2 = {0}; + p2.port = GPIOB; + p2.pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_14; + ADC_Init_Pins(&p2); + ADC_Channel_Init(ADC1, RANK_1, ADC_CHANNEL_6, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_2, ADC_CHANNEL_7, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_3, ADC_CHANNEL_8, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_4, ADC_CHANNEL_9, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_5, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_6, ADC_CHANNEL_12, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + ADC_Channel_Init(ADC1, RANK_7, ADC_CHANNEL_5, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + + // Initialize ADC2 + ADC_Init(ADC2, RESOLUTION_12, RIGHT); + ADC_Regular_Group_Init(ADC2, NO_RANKS); + + // Initialize the pins and channels + Pin_Ports p3 = {0}; + p.port = GPIOA; + p.pin = LL_GPIO_PIN_15; + ADC_Init_Pins(&p3); + ADC_Channel_Init(ADC2, RANK_1, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); + + // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) + // DMA reads into buffer + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, ADC1, HIGH); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, ADC2, HIGH); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + + ADC_Enable_And_Calibrate(ADC1); + ADC_Enable_And_Calibrate(ADC2); +} + /** * @brief The application entry point. * @retval int @@ -112,6 +274,10 @@ int main(void) MX_ADC2_Init(); MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ + ADC_Configure(); + for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++){ + adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); + } /* USER CODE END 2 */ @@ -121,6 +287,10 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ + read_digital(); + write_state_data(); + ADC_UpdateAnalogValues(adcDataValues, ADC1_buffers, NUM_SIGNALS_ADC1, WINDOW_SIZE, ADC1_outputs); + ADC_UpdateAnalogValues(adcDataValues, ADC2_buffers, NUM_SIGNALS_ADC2, WINDOW_SIZE, ADC2_outputs); ECU_State_Tick(); LOGOMATIC("Main Loop Tick Complete. I like Pi %f\n", 3.14159265); LL_mDelay(250); // FIXME Reduce or remove delay From 6fa0832299fede26e30407d9389dbce9ea84fdcc Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 07:23:11 +0000 Subject: [PATCH 11/21] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateTicks.c | 1 - ECU/Application/Src/StateUtils.c | 97 +++++++++++++++----------------- ECU/Core/Src/main.c | 33 ++++++----- 3 files changed, 63 insertions(+), 68 deletions(-) diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index 6a0ac64e..a39ad113 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -6,7 +6,6 @@ #include "StateUtils.h" #include "Unused.h" - /** * @brief The ECU state data lump. * diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 95fa2639..34095aec 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -28,62 +28,55 @@ void setSoftwareLatch(bool close) } */ - if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already - written too - { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); - } - else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin)) - { - HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, - SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); -} - -bool CriticalError(const ECU_StateData *stateData) -{ - if (stateData->max_cell_temp > 60) { - return true; + if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + SOFTWARE_OK_CONTROL_Pin)) { // Avoid writing pins that are already + written too { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); } + } else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { + HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } - if (stateData->ts_voltage > 600) { - return true; - } - if (stateData->bse_apps_violation) { - return true; + + bool CriticalError(const ECU_StateData *stateData) + { + if (stateData->max_cell_temp > 60) { + return true; + } + if (stateData->ts_voltage > 600) { + return true; + } + if (stateData->bse_apps_violation) { + return true; + } + return false; } - return false; -} -bool CommunicationError(const ECU_StateData *stateData) -{ - UNUSED(stateData); - // TODO: implement COMMS errors - return false; -} + bool CommunicationError(const ECU_StateData *stateData) + { + UNUSED(stateData); + // TODO: implement COMMS errors + return false; + } -bool APPS_BSE_Violation(const ECU_StateData *stateData) -{ - // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the - // same time - return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || - (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); -} + bool APPS_BSE_Violation(const ECU_StateData *stateData) + { + // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the + // same time + return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || + (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); + } -bool PressingBrake(const ECU_StateData *stateData) -{ - return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); - // Ideally TCM receives values of 0 after this is no longer called xD. -} + bool PressingBrake(const ECU_StateData *stateData) + { + return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); + // Ideally TCM receives values of 0 after this is no longer called xD. + } -float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, - // PRESSURE SENSORS CAPTURE BRAKE TRAVEL -{ - return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); -} + float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, + // PRESSURE SENSORS CAPTURE BRAKE TRAVEL + { + return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); + } -float CalcPedalTravel(const ECU_StateData *stateData) -{ - return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); -} + float CalcPedalTravel(const ECU_StateData *stateData) + { + return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); + } diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 5157e9e0..8446863d 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -18,13 +18,14 @@ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" -#include "gr_adc.h" -#include "StateTicks.h" + #include "StateData.h" +#include "StateTicks.h" #include "adc.h" #include "dma.h" #include "fdcan.h" #include "gpio.h" +#include "gr_adc.h" #include "usart.h" /* Private includes ----------------------------------------------------------*/ @@ -54,8 +55,6 @@ /* USER CODE END PV */ - - /* RELAVANT PORTS AND PINS @@ -96,11 +95,11 @@ RTD_BTN_LED_CONTROL (42): PA8 #define NUM_SIGNALS_ADC2 1 #define NUM_SIGNALS_DIGITAL 7 // TODO: check which data size to use (floats...ints...etc) -volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values -volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values -uint16_t ADC1_outputs[NUM_SIGNALS_ADC1] = {0}; // Updated averages -uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages -uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array +volatile uint16_t ADC1_buffers[NUM_SIGNALS_ADC1] = {0}; // Contains new values +volatile uint16_t ADC2_buffers[NUM_SIGNALS_ADC2] = {0}; // Contains new values +uint16_t ADC1_outputs[NUM_SIGNALS_ADC1] = {0}; // Updated averages +uint16_t ADC2_outputs[NUM_SIGNALS_ADC2] = {0}; // Updated averages +uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Array // DIGITAL uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; @@ -131,10 +130,11 @@ static void ITM_Enable(void) /* USER CODE END 0 */ // TODO: state data stores stuff as either FLOATS or BOOLS...check -void read_digital(void) { +void read_digital(void) +{ for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { GPIO_PinState currRead; - switch(i) { + switch (i) { case 0: currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_5); break; @@ -161,7 +161,8 @@ void read_digital(void) { } } -void write_state_data() { +void write_state_data() +{ // analog // TODO: bse signal idk what to do ADC1_outputs[0] // TODO: bspd signal idk what to do ADC1_outputs[1] @@ -227,9 +228,11 @@ void ADC_Configure(void) // Initialize DMA (ADC1 = CHANNEL 1, ADC2 = CHANNEL 2) // DMA reads into buffer - DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, ADC1, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC1_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC1, + ADC1, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); - DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, ADC2, HIGH); + DMA_Init(DMA1, LL_DMA_CHANNEL_2, LL_ADC_DMA_GetRegAddr(ADC2, LL_ADC_DMA_REG_REGULAR_DATA), (uint16_t)&ADC2_buffers, LL_DMA_PDATAALIGN_HALFWORD, LL_DMA_MDATAALIGN_HALFWORD, NUM_SIGNALS_ADC2, + ADC2, HIGH); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); ADC_Enable_And_Calibrate(ADC1); @@ -275,7 +278,7 @@ int main(void) MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ ADC_Configure(); - for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++){ + for (int i = 0; i < (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2); i++) { adcDataValues[i] = malloc(sizeof(uint16_t) * WINDOW_SIZE); } From beb3a2f8cbd5439caf1f065a1ed237d98581ef19 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Thu, 15 Jan 2026 23:34:29 -0800 Subject: [PATCH 12/21] fixed LL stuff --- ECU/Application/Src/StateUtils.c | 13 +++++++------ ECU/CMakeLists.txt | 1 + ECU/Core/Src/main.c | 26 ++++++++++++++------------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 95fa2639..756589db 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -13,33 +13,34 @@ void setSoftwareLatch(bool close) // TODO Implement functionality // LOGOMATIC("Setting software latch to %d\n", close); /* - if (close && !HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + if (close && !HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already written too { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); } - else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + else if (!close && HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); } - */ - - if (close && !LL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + */ + /* + if (close && !LL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) // Avoid writing pins that are already written too { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_SET); } - else if (!close && HAL_GPIO_ReadPin(SOFTWARE_OK_CONTROL_GPIO_Port, + else if (!close && HAL_GPIO_IsInputPinSet(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin)) { HAL_GPIO_WritePin(SOFTWARE_OK_CONTROL_GPIO_Port, SOFTWARE_OK_CONTROL_Pin, GPIO_PIN_RESET); + */ } bool CriticalError(const ECU_StateData *stateData) diff --git a/ECU/CMakeLists.txt b/ECU/CMakeLists.txt index bf16105f..7c17f935 100644 --- a/ECU/CMakeLists.txt +++ b/ECU/CMakeLists.txt @@ -77,6 +77,7 @@ target_link_libraries( ${GR_PROJECT_NAME}_USER_CODE INTERFACE GR_OLD_CAN_MESSAGES + ADC ) target_include_directories( diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 5157e9e0..3b45d458 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -25,6 +25,8 @@ #include "dma.h" #include "fdcan.h" #include "gpio.h" +#include "gr_adc.h" +#include "malloc.h" #include "usart.h" /* Private includes ----------------------------------------------------------*/ @@ -136,28 +138,28 @@ void read_digital(void) { GPIO_PinState currRead; switch(i) { case 0: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_5); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); break; case 1: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_6); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); break; case 2: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_7); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); break; case 3: - currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_12); + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); break; case 4: - currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_11); + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); break; case 5: - currRead = LL_GPIO_ReadPin(GPIOC, LL_GPIO_PIN_10); + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); break; case 6: - currRead = LL_GPIO_ReadPin(GPIOA, LL_GPIO_PIN_15); + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); break; } - digital_data[i] = currRead + digital_data[i] = currRead; } } @@ -165,8 +167,8 @@ void write_state_data() { // analog // TODO: bse signal idk what to do ADC1_outputs[0] // TODO: bspd signal idk what to do ADC1_outputs[1] - stateLump.APPS1_SIGNAL = ADC1_outputs[2]; - stateLump.APPS2_SIGNAL = ADC1_outputs[3]; + stateLump.APPS1_Signal = ADC1_outputs[2]; + stateLump.APPS2_Signal = ADC1_outputs[3]; stateLump.Brake_F_Signal = ADC1_outputs[4]; stateLump.Brake_R_Signal = ADC1_outputs[5]; // TODO: Aux signal idk what to do with it ADC1_outputs[6] @@ -220,8 +222,8 @@ void ADC_Configure(void) // Initialize the pins and channels Pin_Ports p3 = {0}; - p.port = GPIOA; - p.pin = LL_GPIO_PIN_15; + p3.port = GPIOA; + p3.pin = LL_GPIO_PIN_15; ADC_Init_Pins(&p3); ADC_Channel_Init(ADC2, RANK_1, ADC_CHANNEL_15, SINGLE_ENDED, SAMPLINGTIME_247CYCLES_5); From 7921f1b696fb451a922dd46a35ef45bdf6c643bf Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 07:37:52 +0000 Subject: [PATCH 13/21] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateUtils.c | 79 ++++++++++++++++---------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 8613e978..1ef3faef 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -44,49 +44,48 @@ void setSoftwareLatch(bool close) */ } - bool CriticalError(const ECU_StateData *stateData) - { - if (stateData->max_cell_temp > 60) { - return true; - } - if (stateData->ts_voltage > 600) { - return true; - } - if (stateData->bse_apps_violation) { - return true; - } - return false; +bool CriticalError(const ECU_StateData *stateData) +{ + if (stateData->max_cell_temp > 60) { + return true; } - - bool CommunicationError(const ECU_StateData *stateData) - { - UNUSED(stateData); - // TODO: implement COMMS errors - return false; + if (stateData->ts_voltage > 600) { + return true; } - - bool APPS_BSE_Violation(const ECU_StateData *stateData) - { - // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the - // same time - return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || - (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); + if (stateData->bse_apps_violation) { + return true; } + return false; +} - bool PressingBrake(const ECU_StateData *stateData) - { - return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); - // Ideally TCM receives values of 0 after this is no longer called xD. - } +bool CommunicationError(const ECU_StateData *stateData) +{ + UNUSED(stateData); + // TODO: implement COMMS errors + return false; +} - float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, - // PRESSURE SENSORS CAPTURE BRAKE TRAVEL - { - return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); - } +bool APPS_BSE_Violation(const ECU_StateData *stateData) +{ + // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the + // same time + return fabs(stateData->APPS2_Signal - stateData->APPS1_Signal * APPS_PROPORTION - APPS_OFFSET) > stateData->APPS2_Signal * 0.1f || + (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); +} - float CalcPedalTravel(const ECU_StateData *stateData) - { - return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); - } - +bool PressingBrake(const ECU_StateData *stateData) +{ + return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); + // Ideally TCM receives values of 0 after this is no longer called xD. +} + +float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, + // PRESSURE SENSORS CAPTURE BRAKE TRAVEL +{ + return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); +} + +float CalcPedalTravel(const ECU_StateData *stateData) +{ + return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); +} From 7434de743a40e2c144bfdf28a1314a1ce351a706 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Fri, 16 Jan 2026 00:11:19 -0800 Subject: [PATCH 14/21] fixed free() stuff --- ECU/Core/Src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 621cf790..208c9bb5 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -27,6 +27,7 @@ #include "gpio.h" #include "gr_adc.h" #include "usart.h" +#include "malloc.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ @@ -299,6 +300,9 @@ int main(void) LL_mDelay(250); // FIXME Reduce or remove delay } /* USER CODE END 3 */ + for (int i = (NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2) - 1; i >= 0; i--) { + free(adcDataValues[i]); + } } /** From bfa3f4a17cabe6646fd1d1286c33676119527f6a Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 08:13:58 +0000 Subject: [PATCH 15/21] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 208c9bb5..eb5483d0 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -26,8 +26,8 @@ #include "fdcan.h" #include "gpio.h" #include "gr_adc.h" -#include "usart.h" #include "malloc.h" +#include "usart.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ From 8bef2c1da817acb4a64bbf7c871de6a597ee8dcd Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Fri, 16 Jan 2026 01:27:41 -0800 Subject: [PATCH 16/21] Spread volatility over the state data lump for things to do better --- ECU/Application/Inc/StateTicks.h | 14 +++++++------- ECU/Application/Src/StateTicks.c | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ECU/Application/Inc/StateTicks.h b/ECU/Application/Inc/StateTicks.h index 42f633da..f2f5161b 100644 --- a/ECU/Application/Inc/StateTicks.h +++ b/ECU/Application/Inc/StateTicks.h @@ -22,7 +22,7 @@ void ECU_State_Tick(void); * * @return void */ -void ECU_GLV_Off(ECU_StateData *stateData); +void ECU_GLV_Off(volatile ECU_StateData *stateData); /** * @brief State handler for the GLV On state. @@ -33,7 +33,7 @@ void ECU_GLV_Off(ECU_StateData *stateData); * * @return void */ -void ECU_GLV_On(ECU_StateData *stateData); +void ECU_GLV_On(volatile ECU_StateData *stateData); /** * @brief State handler for the Precharge Engaged state. @@ -44,7 +44,7 @@ void ECU_GLV_On(ECU_StateData *stateData); * * @return void */ -void ECU_Precharge_Engaged(ECU_StateData *stateData); +void ECU_Precharge_Engaged(volatile ECU_StateData *stateData); /** * @brief State handler for the Precharge Complete state. @@ -55,7 +55,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData); * * @return void */ -void ECU_Precharge_Complete(ECU_StateData *stateData); +void ECU_Precharge_Complete(volatile ECU_StateData *stateData); /** * @brief State handler for the Precharge Fault state. @@ -66,7 +66,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData); * * @return void */ -void ECU_Drive_Active(ECU_StateData *stateData); +void ECU_Drive_Active(volatile ECU_StateData *stateData); /** * @brief Init function for ECU_Tractive_System_Discharge_Start. @@ -78,7 +78,7 @@ void ECU_Drive_Active(ECU_StateData *stateData); * * @return void */ -void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); +void ECU_Tractive_System_Discharge_Start(volatile ECU_StateData *stateData); /** * @brief State handler for the Tractive System Discharge state. @@ -90,6 +90,6 @@ void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData); * * @return void */ -void ECU_Tractive_System_Discharge(ECU_StateData *stateData); +void ECU_Tractive_System_Discharge(volatile ECU_StateData *stateData); #endif diff --git a/ECU/Application/Src/StateTicks.c b/ECU/Application/Src/StateTicks.c index a39ad113..c075b17a 100644 --- a/ECU/Application/Src/StateTicks.c +++ b/ECU/Application/Src/StateTicks.c @@ -62,14 +62,14 @@ transitioning state */ -void ECU_GLV_Off(ECU_StateData *stateData) +void ECU_GLV_Off(volatile ECU_StateData *stateData) { UNUSED(stateData); // TODO Implement functionality // ERROR --> GLV_OFF should never be reached } -void ECU_GLV_On(ECU_StateData *stateData) +void ECU_GLV_On(volatile ECU_StateData *stateData) { if (stateData->ts_voltage >= 60) { // should never happen but has to be accounted for ECU_Tractive_System_Discharge_Start(stateData); @@ -83,7 +83,7 @@ void ECU_GLV_On(ECU_StateData *stateData) } } -void ECU_Precharge_Engaged(ECU_StateData *stateData) +void ECU_Precharge_Engaged(volatile ECU_StateData *stateData) { if (stateData->ts_voltage >= 60) { ECU_Tractive_System_Discharge_Start(stateData); @@ -100,7 +100,7 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData) }*/ } -void ECU_Precharge_Complete(ECU_StateData *stateData) +void ECU_Precharge_Complete(volatile ECU_StateData *stateData) { // TODO Implement functionality /* @@ -134,7 +134,7 @@ void ECU_Precharge_Complete(ECU_StateData *stateData) } } -void ECU_Drive_Active(ECU_StateData *stateData) +void ECU_Drive_Active(volatile ECU_StateData *stateData) { // TODO Implement functionality /* @@ -174,14 +174,14 @@ void ECU_Drive_Active(ECU_StateData *stateData) } } -void ECU_Tractive_System_Discharge_Start(ECU_StateData *stateData) +void ECU_Tractive_System_Discharge_Start(volatile 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) +void ECU_Tractive_System_Discharge(volatile ECU_StateData *stateData) { // TODO Implement functionality of state itself /* From 787876ca84e38165a6b91d0dee6a3bfaf2de780f Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Fri, 16 Jan 2026 14:11:20 -0800 Subject: [PATCH 17/21] removed switch-case for if-else, fixed function order in main --- ECU/Core/Src/main.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index eb5483d0..a346b89c 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -135,28 +135,26 @@ void read_digital(void) { for (int i = 0; i < NUM_SIGNALS_DIGITAL; i++) { GPIO_PinState currRead; - switch (i) { - case 0: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - break; - case 1: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - break; - case 2: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - break; - case 3: - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - break; - case 4: - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - break; - case 5: - currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); - break; - case 6: - currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); - break; + if (i == 0) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); + } + else if (i == 1) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); + } + else if (i == 2) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); + } + else if (i == 3) { + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); + } + else if (i == 4) { + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); + } + else if (i == 5) { + currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); + } + else if (i == 6) { + currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } digital_data[i] = currRead; } @@ -292,9 +290,9 @@ int main(void) /* USER CODE BEGIN 3 */ read_digital(); - write_state_data(); ADC_UpdateAnalogValues(adcDataValues, ADC1_buffers, NUM_SIGNALS_ADC1, WINDOW_SIZE, ADC1_outputs); ADC_UpdateAnalogValues(adcDataValues, ADC2_buffers, NUM_SIGNALS_ADC2, WINDOW_SIZE, ADC2_outputs); + write_state_data(); ECU_State_Tick(); LOGOMATIC("Main Loop Tick Complete. I like Pi %f\n", 3.14159265); LL_mDelay(250); // FIXME Reduce or remove delay From d5ccf94254e7b66527e2949eb6be78d470904edf Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 22:12:23 +0000 Subject: [PATCH 18/21] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index a346b89c..7ef141e8 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -137,23 +137,17 @@ void read_digital(void) GPIO_PinState currRead; if (i == 0) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5); - } - else if (i == 1) { + } else if (i == 1) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_6); - } - else if (i == 2) { + } else if (i == 2) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_7); - } - else if (i == 3) { + } else if (i == 3) { currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_12); - } - else if (i == 4) { + } else if (i == 4) { currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_11); - } - else if (i == 5) { + } else if (i == 5) { currRead = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_10); - } - else if (i == 6) { + } else if (i == 6) { currRead = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15); } digital_data[i] = currRead; From f0d0633a46ca5396e9e1aa976f4815333a0c4484 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Fri, 16 Jan 2026 14:33:39 -0800 Subject: [PATCH 19/21] Use `const volatile` for `ECU_StateData` pointers that you should not change in a function but should expect to be changed/modified in interrupt contexts --- ECU/Application/Inc/StateUtils.h | 12 ++++++------ ECU/Application/Src/StateUtils.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ECU/Application/Inc/StateUtils.h b/ECU/Application/Inc/StateUtils.h index 7dcfeedf..b509a9a3 100644 --- a/ECU/Application/Inc/StateUtils.h +++ b/ECU/Application/Inc/StateUtils.h @@ -20,11 +20,11 @@ #define APPS_OFFSET 250.0f // TODO: Need to be experimentally determined // Checks stateData for critical errors -bool CriticalError(const ECU_StateData *stateData); -bool CommunicationError(const ECU_StateData *stateData); -bool APPS_BSE_Violation(const ECU_StateData *stateData); -bool PressingBrake(const ECU_StateData *stateData); -float CalcBrakePercent(const ECU_StateData *stateData); -float CalcPedalTravel(const ECU_StateData *stateData); +bool CriticalError(volatile const ECU_StateData *stateData); +bool CommunicationError(volatile const ECU_StateData *stateData); +bool APPS_BSE_Violation(volatile const ECU_StateData *stateData); +bool PressingBrake(volatile const ECU_StateData *stateData); +float CalcBrakePercent(volatile const ECU_StateData *stateData); +float CalcPedalTravel(volatile const ECU_StateData *stateData); #endif diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 1ef3faef..5e7c9be4 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -44,7 +44,7 @@ void setSoftwareLatch(bool close) */ } -bool CriticalError(const ECU_StateData *stateData) +bool CriticalError(volatile const ECU_StateData *stateData) { if (stateData->max_cell_temp > 60) { return true; @@ -58,14 +58,14 @@ bool CriticalError(const ECU_StateData *stateData) return false; } -bool CommunicationError(const ECU_StateData *stateData) +bool CommunicationError(volatile const ECU_StateData *stateData) { UNUSED(stateData); // TODO: implement COMMS errors return false; } -bool APPS_BSE_Violation(const ECU_StateData *stateData) +bool APPS_BSE_Violation(volatile const ECU_StateData *stateData) { // Checks 2 * APPS_1 is within 10% of APPS_2 and break + throttle at the // same time @@ -73,19 +73,19 @@ bool APPS_BSE_Violation(const ECU_StateData *stateData) (PressingBrake(stateData) && CalcPedalTravel(stateData) >= 0.25f); } -bool PressingBrake(const ECU_StateData *stateData) +bool PressingBrake(volatile const ECU_StateData *stateData) { return (stateData->Brake_F_Signal - BRAKE_F_MIN > BSE_DEADZONE * (BRAKE_F_MAX - BRAKE_F_MIN)) && (stateData->Brake_R_Signal - BRAKE_R_MIN > BSE_DEADZONE * (BRAKE_R_MAX - BRAKE_R_MIN)); // Ideally TCM receives values of 0 after this is no longer called xD. } -float CalcBrakePercent(const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, +float CalcBrakePercent(volatile const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, // PRESSURE SENSORS CAPTURE BRAKE TRAVEL { return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); } -float CalcPedalTravel(const ECU_StateData *stateData) +float CalcPedalTravel(volatile const ECU_StateData *stateData) { return (float)(stateData->APPS1_Signal + stateData->APPS2_Signal - THROTTLE_MIN_2 - THROTTLE_MIN_1) / (THROTTLE_MAX_1 + THROTTLE_MAX_2 - THROTTLE_MIN_1 - THROTTLE_MIN_2); } From 9187de1b48756df3a9f985c0be9bb84c313acfab Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 22:34:41 +0000 Subject: [PATCH 20/21] Automatic Clang-Format: Standardized formatting automatically --- ECU/Application/Src/StateUtils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Application/Src/StateUtils.c b/ECU/Application/Src/StateUtils.c index 5e7c9be4..a9dbd990 100644 --- a/ECU/Application/Src/StateUtils.c +++ b/ECU/Application/Src/StateUtils.c @@ -80,7 +80,7 @@ bool PressingBrake(volatile const ECU_StateData *stateData) } float CalcBrakePercent(volatile const ECU_StateData *stateData) // THIS IS NOT ACTUALLY BRAKE TRAVEL, - // PRESSURE SENSORS CAPTURE BRAKE TRAVEL + // PRESSURE SENSORS CAPTURE BRAKE TRAVEL { return (float)(stateData->Brake_F_Signal + stateData->Brake_R_Signal - BRAKE_R_MIN - BRAKE_F_MIN) / (BRAKE_F_MAX - BRAKE_F_MIN + BRAKE_R_MAX - BRAKE_R_MIN); } From 10e55ccc326cfd3a26f7915530a73fa1bc11fe17 Mon Sep 17 00:00:00 2001 From: khoulihan27 Date: Fri, 16 Jan 2026 14:43:27 -0800 Subject: [PATCH 21/21] fixed stateLump not being declared volatile --- ECU/Core/Src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 7ef141e8..15b48cf7 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -106,7 +106,7 @@ uint16_t *adcDataValues[(NUM_SIGNALS_ADC1 + NUM_SIGNALS_ADC2)] = {0}; // 2D Arra uint8_t digital_data[NUM_SIGNALS_DIGITAL] = {0}; // STATE DATA -extern ECU_StateData stateLump; +extern volatile ECU_StateData stateLump; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void);