From d0e0c7dbba0473dfe393a05af97330bb4bb7e06c Mon Sep 17 00:00:00 2001 From: Akshay Date: Fri, 20 Mar 2026 15:38:58 -0500 Subject: [PATCH 01/27] fixed canbus test, rewrote faults --- Firmware/Drivers/Inc/FaultBits.h | 268 +++++++++++--- Firmware/Drivers/Inc/MotorSafeBits.h | 28 +- Firmware/Drivers/Inc/StatusLEDs.h | 15 +- Firmware/Drivers/Inc/Watchdogs.h | 116 ++++++ Firmware/Drivers/Src/ADC_Sense.c | 26 +- Firmware/Drivers/Src/CANbus.c | 210 +++++------ Firmware/Drivers/Src/Contactors.c | 67 ++-- Firmware/Drivers/Src/FaultBits.c | 152 +++++--- Firmware/Drivers/Src/MotorSafeBits.c | 69 ++-- Firmware/Drivers/Src/StatusLEDs.c | 66 ++-- Firmware/Drivers/Src/UART_Init.c | 42 +-- Firmware/Drivers/Src/Watchdogs.c | 80 ++++ Firmware/Tasks/Inc/FaultHandlerTask.h | 17 - Firmware/Tasks/Src/CanTxTelemetryTask.c | 54 +-- Firmware/Tasks/Src/FaultHandlerTask.c | 348 ++++++++++++------ Firmware/Tasks/Src/InitTask.c | 5 +- Firmware/Tasks/Src/PrechargeTask.c | 127 +++---- Firmware/config/Inc/pinDefs.h | 96 ++--- .../tests/{CANBus_test.c => canbus_test.c} | 56 +-- .../{Printf_Init_test.c => printf_test.c} | 31 +- 20 files changed, 1131 insertions(+), 742 deletions(-) create mode 100644 Firmware/Drivers/Inc/Watchdogs.h create mode 100644 Firmware/Drivers/Src/Watchdogs.c rename Firmware/tests/{CANBus_test.c => canbus_test.c} (52%) rename Firmware/tests/{Printf_Init_test.c => printf_test.c} (53%) diff --git a/Firmware/Drivers/Inc/FaultBits.h b/Firmware/Drivers/Inc/FaultBits.h index 22fc628f..6431b6b7 100644 --- a/Firmware/Drivers/Inc/FaultBits.h +++ b/Firmware/Drivers/Inc/FaultBits.h @@ -1,77 +1,237 @@ +// #pragma once + +// #include "inits.h" +// #include +// #include + +// #define ALL_FAULT_BITS ((1UL << NUM_FAULTS) - 1UL) + +// // The max number of fault bits is dependent on the configUSE_16_BIT_TICKS defined in FreeRTOS.h +// #if (configUSE_16_BIT_TICKS == 0) +// #define MAX_FAULT_BITS 24U +// #else +// #define MAX_FAULT_BITS 8U +// #endif + +// typedef enum +// { +// MOTOR_GREATER_THAN_BATTERY_FAULT, // Motor voltage is greater than battery voltage +// BATTERY_OVERVOLTAGE_FAULT, // Battery voltage is greater than OVERVOLTAGE_THRESHOLD_MV +// BATTERY_UNDERVOLTAGE_FAULT, // Battery voltage is less than UNDERVOLTAGE_THRESHOLD_MV +// MOTOR_SENSE_TIMEOUT_FAULT, // Motor contactor didn't close within expected time +// PRECHARGE_SENSE_TIMEOUT_FAULT, // Precharge contactor didn't close within expected time +// PRECHARGE_TIMEOUT_FAULT, // Precharge sequence took too long +// CALLBACK_FAULT, // Contactor state did not match expected state after being set +// MOTOR_SENSE_MISMATCH_FAULT, // Motor contactor sense pin reading does not match contactor state +// PRECHARGE_SENSE_MISMATCH_FAULT, // Precharge contactor sense pin reading does not match contactor state +// NUM_FAULTS +// } fault_bit_t; + +// /* Convert enum to bitmask */ +// #define FAULT_BIT(fault) (1UL << (fault)) + +// /* Mask containing only the actual fault bits (exclude precharge state bits) +// Precharge state enum values are the first entries, so keep bits from +// MOTOR_GREATER_THAN_BATTERY_FAULT upwards. */ +// #define FAULTS_ONLY_MASK ((EventBits_t)(ALL_FAULT_BITS & ~((1UL << (MOTOR_GREATER_THAN_BATTERY_FAULT)) - 1UL))) + +// /* Legacy name kept for callers that expect a mask of fault bits */ +// #define FAULT_BITMASK (FAULTS_ONLY_MASK) + +// _Static_assert(NUM_FAULTS <= MAX_FAULT_BITS, "Too many fault bits for EventGroup"); + +// /** +// * @brief Initializes fault bitmap +// * +// * @param none +// * @return 0 on failure, 1 on success +// */ +// uint8_t faultBits_init(void); + +// /** +// * @brief Set a fault in the fault bitmap +// * +// * @param bit which fault is being set +// * @return none +// */ +// void set_faultBit(fault_bit_t bit); + +// /** +// * @brief Wait for a fault to be set +// * +// * @param bit which fault to wait for, pass NUM_FAULTS if waiting for any fault +// * @param xTicksToWait delay when waiting +// * @return the event bit that was set +// */ +// EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait); + +// /** +// * @brief Set a fault in the fault bitmap from an ISR +// * +// * @param bit which fault is being set +// * @return none +// */ +// void set_faultBitFromISR(fault_bit_t bit); + #pragma once -#include "inits.h" -#include +#include "FreeRTOS.h" +#include "event_groups.h" #include +#include + +#define FAULT_ID_LIST(X) \ + /* ============= MOTOR CONTROLLER ============ */ \ + X(MOTOR_HARDWARE_OVERCURRENT) \ + X(MOTOR_SOFTWARE_OVERCURRENT) \ + X(MOTOR_DC_BUS_OVERVOLTAGE) \ + X(MOTOR_BAD_HALL_SEQUENCE) \ + X(MOTOR_WD_RESET) \ + X(MOTOR_CONFIG_READ) \ + X(MOTOR_15V_UNDERVOLTAGE) \ + X(MOTOR_DESATURATION) \ + X(MOTOR_OVERSPEED) \ + \ + /* ================ PRECHARGE ================ */ \ + X(PRECHARGE_TIMEOUT) /* Prech sequence took too long */ \ + X(PRECHARGE_SENSE_TIMEOUT) /* Prech contactor didn't close within expected time */ \ + X(PRECHARGE_SENSE_MISMATCH) /* Prech contactor sense reading doesnt match contactor state */ \ + X(MOTOR_SENSE_TIMEOUT) /* Motor contactor didn't close within expected time */ \ + X(MOTOR_SENSE_MISMATCH) /* Motor contactor sense reading doesnt match contactor state */ \ + X(BATTERY_OVERVOLTAGE) /* Battery voltage is greater than OVERVOLTAGE_THRESHOLD_MV */ \ + X(BATTERY_UNDERVOLTAGE) /* Battery voltage is less than UNDERVOLTAGE_THRESHOLD_MV */ \ + X(MOTOR_GT_BATTERY) /* Motor voltage is greater than battery voltage */ \ + X(CONTACTOR_CALLBACK) /* Contactor state didnt match expected state after being set */ \ + \ + /* ============== OTHER BOARDS =============== */ \ + X(STEERING_SENSOR_FAULT) /* Sensor not OK or data invalid */ \ + X(PEDAL_BOARD_FAULT) /* Pedal board fault or data invalid */ \ + X(CONTROLS_FAULT) /* Fault in controls status */ \ + X(BPS_FAULT) /* Fault in BPS status */ \ + X(GENERIC_WATCHDOG_FAULT) /* A generic fault triggereed by all dogs */ -#define ALL_FAULT_BITS ((1UL << NUM_FAULTS) - 1UL) +typedef enum { +#define X(name) FAULT_ID_##name, + FAULT_ID_LIST(X) +#undef X + FAULT_ID_COUNT +} FaultID_e; -// The max number of fault bits is dependent on the configUSE_16_BIT_TICKS defined in FreeRTOS.h #if (configUSE_16_BIT_TICKS == 0) #define MAX_FAULT_BITS 24U #else #define MAX_FAULT_BITS 8U #endif -typedef enum -{ - PRECHARGE_INITIAL_STATE, // Indiciates we are in the inital state when set - PRECHARGE_PRECHARGING_STATE, // Indicates we are in the precharging state when set - PRECHARGE_RUN_STATE, // Indicates we are in the run state when set - MOTOR_GREATER_THAN_BATTERY_FAULT, // Motor voltage is greater than battery voltage - BATTERY_OVERVOLTAGE_FAULT, // Battery voltage is greater than OVERVOLTAGE_THRESHOLD_MV - BATTERY_UNDERVOLTAGE_FAULT, // Battery voltage is less than UNDERVOLTAGE_THRESHOLD_MV - MOTOR_SENSE_TIMEOUT_FAULT, // Motor contactor didn't close within expected time - PRECHARGE_SENSE_TIMEOUT_FAULT, // Precharge contactor didn't close within expected time - PRECHARGE_TIMEOUT_FAULT, // Precharge sequence took too long - CALLBACK_FAULT, // Contactor state did not match expected state after being set - MOTOR_SENSE_MISMATCH_FAULT, // Motor contactor sense pin reading does not match contactor state - PRECHARGE_SENSE_MISMATCH_FAULT, // Precharge contactor sense pin reading does not match contactor state - NUM_FAULTS -} fault_bit_t; - -/* Convert enum to bitmask */ -#define FAULT_BIT(fault) (1UL << (fault)) - -/* Mask containing only the actual fault bits (exclude precharge state bits) - Precharge state enum values are the first entries, so keep bits from - MOTOR_GREATER_THAN_BATTERY_FAULT upwards. */ -#define FAULTS_ONLY_MASK ((EventBits_t)(ALL_FAULT_BITS & ~((1UL << (MOTOR_GREATER_THAN_BATTERY_FAULT)) - 1UL))) - -/* Legacy name kept for callers that expect a mask of fault bits */ -#define FAULT_BITMASK (FAULTS_ONLY_MASK) - -_Static_assert(NUM_FAULTS <= MAX_FAULT_BITS, "Too many fault bits for EventGroup"); +_Static_assert(FAULT_ID_COUNT <= MAX_FAULT_BITS, + "Too many fault bits for EventGroup"); + +// Names for faults for printing/debugging purposes. Indexed by FaultID_e values +extern const char *fault_names[]; + + +#define FAULT_BIT(id) (1UL << (id)) +#define FAULT_MASK_ALL ((1UL << FAULT_ID_COUNT) - 1) + + +#define FAULT_MASK_MOTOR_ALL ( \ + FAULT_BIT(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT) | \ + FAULT_BIT(FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT) | \ + FAULT_BIT(FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE) | \ + FAULT_BIT(FAULT_ID_MOTOR_BAD_HALL_SEQUENCE) | \ + FAULT_BIT(FAULT_ID_MOTOR_WD_RESET) | \ + FAULT_BIT(FAULT_ID_MOTOR_CONFIG_READ) | \ + FAULT_BIT(FAULT_ID_MOTOR_15V_UNDERVOLTAGE) | \ + FAULT_BIT(FAULT_ID_MOTOR_DESATURATION) | \ + FAULT_BIT(FAULT_ID_MOTOR_OVERSPEED) \ +) + +#define FAULT_MASK_PRECHARGE_ALL ( \ + FAULT_BIT(FAULT_ID_PRECHARGE_TIMEOUT) | \ + FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_TIMEOUT) | \ + FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_MISMATCH) | \ + FAULT_BIT(FAULT_ID_MOTOR_SENSE_TIMEOUT) | \ + FAULT_BIT(FAULT_ID_MOTOR_SENSE_MISMATCH) | \ + FAULT_BIT(FAULT_ID_BATTERY_OVERVOLTAGE) | \ + FAULT_BIT(FAULT_ID_BATTERY_UNDERVOLTAGE) | \ + FAULT_BIT(FAULT_ID_MOTOR_GT_BATTERY) | \ + FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK) \ +) + +/** + * @brief Initializes fault bitmap and associated data structures. Must be + * called before using any other functions in this module. + * + * @return true if initialization succeeded, false if it failed + */ +bool faults_init(void); + +/** + * @brief Sets a fault bit. + * + * @param id The fault ID to set. + */ +void faults_set(FaultID_e id); + +/** + * @brief Sets a fault bit from an ISR context. + * + * This is a separate function from the non-ISR version because it needs to use + * FromISR FreeRTOS APIs and handle the pxHigherPriorityTaskWoken parameter. + * + * @param id The fault ID to set. + */ +void faults_set_from_isr(FaultID_e id); + +/** + * @brief Sets multiple fault bits at once using a mask. This is useful for + * cases where multiple faults need to be set simultaneously. + * + * @param mask A bitmask of fault bits to set. Only bits corresponding to valid + * fault IDs will be set; other bits will be ignored. + */ +void faults_set_mask(EventBits_t mask); /** - * @brief Initializes fault bitmap - * - * @param none - * @return 0 on failure, 1 on success + * @brief Clears a fault bit. + * + * @param id The fault ID to clear. */ -uint8_t faultBits_init(void); +void faults_clear(FaultID_e id); /** - * @brief Set a fault in the fault bitmap - * - * @param bit which fault is being set - * @return none + * @brief Checks if a specific fault bit is active. + * + * @param id The fault ID to check. + * @return true if the specified fault bit is active, false otherwise. */ -void set_faultBit(fault_bit_t bit); +bool faults_is_active(FaultID_e id); /** - * @brief Wait for a fault to be set - * - * @param bit which fault to wait for, pass NUM_FAULTS if waiting for any fault - * @param xTicksToWait delay when waiting - * @return the event bit that was set + * @brief Checks if any fault bits are active. + * + * @return true if any fault bits are active, false if no fault bits are active. */ -EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait); +bool faults_any_active(void); + +/** + * @brief Gets the current active fault bits as a bitmask. + * + * @return A bitmask where each bit corresponds to an active fault. Only bits + * corresponding to valid fault IDs will be set; other bits will be 0. + */ +EventBits_t faults_get(void); + /** - * @brief Set a fault in the fault bitmap from an ISR - * - * @param bit which fault is being set - * @return none + * @brief Waits for specific fault bits to become active. + * + * @param id The fault ID to wait for, or NUM_FAULTS to wait for any fault. + * @param ticks The maximum time to wait in ticks. Use portMAX_DELAY to wait + * indefinitely + * @return A bitmask of the fault bits that are currently active. If waiting for + * a specific fault ID, the returned bitmask will have that bit set if it became + * active. If waiting for any fault, the returned bitmask will have all active + * fault bits set. */ -void set_faultBitFromISR(fault_bit_t bit); \ No newline at end of file +EventBits_t faults_wait(FaultID_e id, TickType_t ticks); diff --git a/Firmware/Drivers/Inc/MotorSafeBits.h b/Firmware/Drivers/Inc/MotorSafeBits.h index a493716a..1dd1480c 100644 --- a/Firmware/Drivers/Inc/MotorSafeBits.h +++ b/Firmware/Drivers/Inc/MotorSafeBits.h @@ -1,33 +1,33 @@ #pragma once #include "FreeRTOS.h" -#include "stm32xx_hal.h" #include "inits.h" +#include "stm32xx_hal.h" #include #include // The max number of fault bits is dependent on the configUSE_16_BIT_TICKS defined in FreeRTOS.h -#if ( configUSE_16_BIT_TICKS == 0 ) - #define MAX_MOTOR_SAFE_BITS 24U +#if (configUSE_16_BIT_TICKS == 0) +#define MAX_MOTOR_SAFE_BITS 24U #else - #define MAX_MOTOR_SAFE_BITS 8U +#define MAX_MOTOR_SAFE_BITS 8U #endif -typedef enum -{ - BPS_SAFE = 0, // BPS is clear and high voltage is on - PEDALS_READING_ACCELERATOR = 1, // We're getting correct accelerator pedal messages - PEDALS_READING_BRAKE = 2, // We're getting correct brake pedal messages - MOTOR_CONTACTOR_ENABLED = 3, // The Motor contactor is enabled - MOTOR_PRECHARGE_CONTACTOR_ENABLED = 4, // The Motor precharge Contactor is enabled - DASHBOARD_IGNITION_MOTOR = 5, // Ignition switch is set to motor +typedef enum { + BPS_SAFE = 0, // BPS is clear and high voltage is on + PEDALS_READING_ACCELERATOR = 1, // We're getting correct accelerator pedal messages + PEDALS_READING_BRAKE = 2, // We're getting correct brake pedal messages + MOTOR_CONTACTOR_ENABLED = 3, // The Motor contactor is enabled + MOTOR_PRECHARGE_CONTACTOR_ENABLED = 4, // The Motor precharge Contactor is enabled + DASHBOARD_IGNITION_MOTOR = 5, // Ignition switch is set to motor NUM_MOTOR_STATUS_BITS = 6 } motor_status_bit_t; -_Static_assert(NUM_MOTOR_STATUS_BITS <= MAX_MOTOR_SAFE_BITS, "Too many motor safe bits for EventGroup"); +_Static_assert(NUM_MOTOR_STATUS_BITS <= MAX_MOTOR_SAFE_BITS, + "Too many motor safe bits for EventGroup"); /* Convert enum to bitmask */ -#define MOTOR_STATUS_BIT(motorBit) (1UL << (motorBit)) +#define MOTOR_STATUS_BIT(motorBit) (1UL << (motorBit)) BaseType_t MotorSafeBits_Init(); diff --git a/Firmware/Drivers/Inc/StatusLEDs.h b/Firmware/Drivers/Inc/StatusLEDs.h index 56b04e07..1ee10a87 100644 --- a/Firmware/Drivers/Inc/StatusLEDs.h +++ b/Firmware/Drivers/Inc/StatusLEDs.h @@ -1,22 +1,21 @@ #pragma once -#include #include "inits.h" +#include #define num_LEDs 15 -/** * @brief LED States */ -typedef enum -{ +/** @brief LED States */ +typedef enum { LED_OFF = GPIO_PIN_SET, // Negative logic - LED_ON = GPIO_PIN_RESET + LED_ON = GPIO_PIN_RESET } LED_state_t; -/** * @brief Logic-to-Hardware mapping for diagnostic LEDs. +/** + * @brief Logic-to-Hardware mapping for diagnostic LEDs. * @note Values correspond to specific shift register positions. */ -typedef enum -{ +typedef enum { PRECHARGE_COMPLETE, // precharge voltage threshold reached PRECHARGE_TIMEOUT, // precharge voltage did not meet threshold in time PRECHARGE_SENSE_TIMEOUT, // precharge contactor sense did not return in time diff --git a/Firmware/Drivers/Inc/Watchdogs.h b/Firmware/Drivers/Inc/Watchdogs.h new file mode 100644 index 00000000..e73dfa55 --- /dev/null +++ b/Firmware/Drivers/Inc/Watchdogs.h @@ -0,0 +1,116 @@ +/** + * @file Watchdogs.h + * @brief CAN message watchdog monitoring + * @copyright Copyright (c) 2026 UT Longhorn Racing Solar + */ + +#pragma once + +#include "FreeRTOS.h" +#include "timers.h" +#include "FaultBits.h" +#include +#include + +#define MAX_WD_TIMERS 10 + +/** + * @brief List of watchdogs to create, along with their timeouts and fault IDs + * Format: X(name, string_name, timeout_ms, fault_id) + * - name: enum name for the watchdog index (e.g. WD_IDX_DRIVER_INPUT) + * - string_name: name to show in printf when the dog times out (e.g. "wd_driver_input") + * - timeout_ms: how long the watchdog should wait before timing out in milliseconds (e.g. 150) + * - fault_id: which fault to throw when the watchdog times out + * + * Currently all watchdogs throw the same generic fault, but you can specify different + * faults for each one if you want to get more specific information about which signal + * caused the fault. Just make sure to add the new fault IDs to FaultBits.h as well. + */ +#define WATCHDOG_LIST(X) \ + X(DRIVER_INPUT, "wd_driver_input", 150U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(ACCEL_BRAKE, "wd_accel_brake", 150U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(STEERING_ANGLE, "wd_steering_angle", 300U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(CONTROLS_STATUS, "wd_controls_status", 300U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(BPS_STATUS, "wd_bps_status", 300U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(MOCO_STATUS, "wd_moco_status", 500U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(MOCO_VELOCITY, "wd_moco_velocity", 500U, FAULT_ID_GENERIC_WATCHDOG_FAULT) + +typedef enum { +#define X(name, str, timeout, fault) WD_IDX_##name, + WATCHDOG_LIST(X) +#undef X + WD_IDX_COUNT +} WatchdogIndex_e; + +_Static_assert(WD_IDX_COUNT <= MAX_WD_TIMERS, "Too many watchdogs; keep under the max"); + +#define X(name, str, timeout, fault) enum { WD_TIMEOUT_##name##_MS = timeout }; +WATCHDOG_LIST(X) +#undef X + + +/** + * @brief Initialize the watchdog system. This must be called before creating + * any watchdog timers. + */ +void watchdog_init(void); + +/** + * @brief Create a watchdog timer for a given index. The timer will be created + * in a stopped state, so you need to call watchdog_start_all to start it after + * creating all the timers. + */ +void watchdog_create(const char *name, uint8_t idx, uint32_t timeout_ms, FaultID_e fault_id); + +/** + * @brief Start all watchdog timers. Should be called after creating all timers + * with watchdog_create, and also after handling a fault to restart the timers + * once the fault condition has been resolved. + * + * Note that if you call this function while a timer is already running, it will + * reset the timer back to its full timeout. + */ +void watchdog_start_all(void); + +/** + * @brief Stop all watchdog timers. Should be called when entering a fault state + * to prevent any watchdog timeouts from triggering additional faults while + * we're already handling a fault. + */ +void watchdog_stop_all(void); + +/** + * @brief Pet the watchdog for a given index. Should be called from the task + * context when a CAN message is received. + */ +void watchdog_received_can_message(uint8_t idx); + +/** + * @brief Pet the watchdog from an ISR context. This is a separate function from + * the non-ISR version because it needs to use FromISR FreeRTOS APIs and handle + * the pxHigherPriorityTaskWoken parameter. + */ +void watchdog_received_can_message_ISR(uint8_t idx, BaseType_t *pxHigherPriorityTaskWoken); + +/** + * @brief Check if the watchdog for a given index is alive (i.e. has been petted + * recently enough that it hasn't timed out). + */ +bool watchdog_is_alive(int idx); + +/** + * @brief Get the number of watchdog timers that have been created. Useful for + * iterating over all timers or for debugging. + */ +uint8_t watchdog_count(void); + +/** + * @brief Helper macro to initialize all watchdogs defined in WATCHDOG_LIST with one call + */ +#define WATCHDOG_INIT_ALL_FSM_SIGNALS() \ + do { \ + WATCHDOG_LIST(WATCHDOG_CREATE_ONE_); \ + } while (0); + +#define WATCHDOG_CREATE_ONE_(name, str, timeout, fault) \ + watchdog_create(str, WD_IDX_##name, timeout, fault); diff --git a/Firmware/Drivers/Src/ADC_Sense.c b/Firmware/Drivers/Src/ADC_Sense.c index b18ccabe..7a93d122 100644 --- a/Firmware/Drivers/Src/ADC_Sense.c +++ b/Firmware/Drivers/Src/ADC_Sense.c @@ -19,7 +19,8 @@ static ADC_ChannelConfTypeDef sConfig1 = { .SamplingTime = ADC_SAMPLING_TIME, .SingleDiff = ADC_SINGLE_ENDED, .OffsetNumber = ADC_OFFSET_NONE, - .Offset = 0}; + .Offset = 0 +}; static ADC_ChannelConfTypeDef sConfig2 = { .Channel = ADC2_CHANNEL, @@ -27,7 +28,8 @@ static ADC_ChannelConfTypeDef sConfig2 = { .SamplingTime = ADC_SAMPLING_TIME, .SingleDiff = ADC_SINGLE_ENDED, .OffsetNumber = ADC_OFFSET_NONE, - .Offset = 0}; + .Offset = 0 +}; static uint32_t HAL_RCC_ADC12_CLK_ENABLED = 0; @@ -118,7 +120,7 @@ ADC_Sense_Status_t ADC_1_Init() if (adc_init(&adc_init_1, hadc1) != ADC_OK) { // ADC1 initialization failed - set_faultBit(ADC_1_INIT_ERR); + faults_set(ADC_1_INIT_ERR); return ADC_1_INIT_ERR; } @@ -157,7 +159,7 @@ ADC_Sense_Status_t ADC_2_Init() if (adc_init(&adc_init_2, hadc2) != ADC_OK) { // ADC2 initialization failed - set_faultBit(ADC_2_INIT_ERR); + faults_set(ADC_2_INIT_ERR); return ADC_2_INIT_ERR; } @@ -179,14 +181,14 @@ ADC_Sense_Status_t ADC_Sense_Init(void) // Initialize ADCs and queues if (Motor_ADC_Queue == NULL || Battery_ADC_Queue == NULL) { // Queue creation failed - set_faultBit(ADC_QUEUE_ERR); + faults_set(ADC_QUEUE_ERR); return ADC_QUEUE_ERR; } if (ADC_1_Init() != ADC_SENSE_OK || ADC_2_Init() != ADC_SENSE_OK) { // One or both ADC initializations failed - set_faultBit(ADC_SENSE_INIT_ERR); + faults_set(ADC_SENSE_INIT_ERR); return ADC_SENSE_INIT_ERR; } @@ -199,14 +201,14 @@ ADC_Sense_Status_t Read_ADC(uint32_t Timeout_MS, ADC_Sense_Result *Result) // Re if (!Is_Initialized) { // ADC_Sense_Init has not been called or failed - set_faultBit(ADC_SENSE_INIT_ERR); + faults_set(ADC_SENSE_INIT_ERR); return ADC_SENSE_INIT_ERR; } if (Result == NULL) { // Invalid result pointer - set_faultBit(READ_ADC_BAD_PARAM_ERR); + faults_set(READ_ADC_BAD_PARAM_ERR); return READ_ADC_BAD_PARAM_ERR; } @@ -220,13 +222,13 @@ ADC_Sense_Status_t Read_ADC(uint32_t Timeout_MS, ADC_Sense_Result *Result) // Re if (adc_read(hadc1, &sConfig1, Motor_ADC_Queue) != ADC_OK) { // Motor ADC read failed - set_faultBit(ADC_1_READ_ERR); + faults_set(ADC_1_READ_ERR); return ADC_1_READ_ERR; } if (adc_read(hadc2, &sConfig2, Battery_ADC_Queue) != ADC_OK) { // Battery ADC read failed - set_faultBit(ADC_2_READ_ERR); + faults_set(ADC_2_READ_ERR); return ADC_2_READ_ERR; } @@ -237,7 +239,7 @@ ADC_Sense_Status_t Read_ADC(uint32_t Timeout_MS, ADC_Sense_Result *Result) // Re else { // Queue receive failed for motor ADC - set_faultBit(MOTOR_QUEUE_RECEIVE_ERR); + faults_set(MOTOR_QUEUE_RECEIVE_ERR); return MOTOR_QUEUE_RECEIVE_ERR; } @@ -248,7 +250,7 @@ ADC_Sense_Status_t Read_ADC(uint32_t Timeout_MS, ADC_Sense_Result *Result) // Re else { // Queue receive failed for battery ADC - set_faultBit(BATTERY_QUEUE_RECEIVE_ERR); + faults_set(BATTERY_QUEUE_RECEIVE_ERR); return BATTERY_QUEUE_RECEIVE_ERR; } diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 88322f7a..0f3d3676 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -2,15 +2,13 @@ #define FDCAN_NVIC_PRIO configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 5 -FDCAN_HandleTypeDef* motorfdcan; -FDCAN_HandleTypeDef* carfdcan; +FDCAN_HandleTypeDef *motorfdcan; +FDCAN_HandleTypeDef *carfdcan; -can_status_t Motor_CANBus_Init(void){ - +can_status_t Motor_CANBus_Init(void) { motorfdcan = hfdcan1; motorfdcan->Instance = FDCAN1; - motorfdcan->Init.ClockDivider = FDCAN_CLOCK_DIV1; motorfdcan->Init.FrameFormat = FDCAN_FRAME_CLASSIC; motorfdcan->Init.Mode = FDCAN_MODE_NORMAL; @@ -29,7 +27,7 @@ can_status_t Motor_CANBus_Init(void){ motorfdcan->Init.ExtFiltersNbr = 0; motorfdcan->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; - // accepts all CAN IDs + // accepts all CAN IDs FDCAN_FilterTypeDef sFilterConfig1; sFilterConfig1.IdType = FDCAN_STANDARD_ID; sFilterConfig1.FilterIndex = 0; @@ -40,36 +38,33 @@ can_status_t Motor_CANBus_Init(void){ sFilterConfig1.FilterID1 = 0x000; sFilterConfig1.FilterID2 = 0x000; - if(can_fd_init(motorfdcan, &sFilterConfig1) != CAN_OK){ - return CAN_ERR; + if (can_fd_init(motorfdcan, &sFilterConfig1) != CAN_OK) { + return CAN_ERR; } - if(can_fd_start(motorfdcan) != CAN_OK){ - return CAN_ERR; + if (can_fd_start(motorfdcan) != CAN_OK) { + return CAN_ERR; } return CAN_OK; - } -can_status_t Motor_CANBus_Send(FDCAN_TxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks){ - - return can_fd_send(motorfdcan, header, data, delay_ticks); +can_status_t Motor_CANBus_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks) { + return can_fd_send(motorfdcan, header, data, delay_ticks); } -can_status_t Motor_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks){ - - return can_fd_recv(motorfdcan, id, header, data, delay_ticks); +can_status_t Motor_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef *header, + uint8_t data[], TickType_t delay_ticks) { + return can_fd_recv(motorfdcan, id, header, data, delay_ticks); } -can_status_t Car_CANBus_Init(void){ - +can_status_t Car_CANBus_Init(void) { carfdcan = hfdcan3; carfdcan->Instance = FDCAN3; - carfdcan->Init.ClockDivider = FDCAN_CLOCK_DIV1; carfdcan->Init.FrameFormat = FDCAN_FRAME_CLASSIC; carfdcan->Init.Mode = FDCAN_MODE_NORMAL; @@ -88,7 +83,7 @@ can_status_t Car_CANBus_Init(void){ carfdcan->Init.ExtFiltersNbr = 0; carfdcan->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; - // accepts all CAN IDs from + // accepts all CAN IDs from // FDCAN1 Filter Config FDCAN_FilterTypeDef CarCANFilterConfig; CarCANFilterConfig.IdType = FDCAN_STANDARD_ID; @@ -98,145 +93,132 @@ can_status_t Car_CANBus_Init(void){ CarCANFilterConfig.FilterID1 = 0x000; CarCANFilterConfig.FilterID2 = 0x000; - if(can_fd_init(carfdcan, &CarCANFilterConfig) != CAN_OK){ - return CAN_ERR; + if (can_fd_init(carfdcan, &CarCANFilterConfig) != CAN_OK) { + return CAN_ERR; } - if(can_fd_start(carfdcan) != CAN_OK){ - return CAN_ERR; + if (can_fd_start(carfdcan) != CAN_OK) { + return CAN_ERR; } return CAN_OK; - } -can_status_t Car_CANBus_Send(FDCAN_TxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks){ - - return can_fd_send(carfdcan, header, data, delay_ticks); +can_status_t Car_CANBus_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks) { + return can_fd_send(carfdcan, header, data, delay_ticks); } -can_status_t Car_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks){ +can_status_t Car_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef *header, + uint8_t data[], TickType_t delay_ticks) { return can_fd_recv(carfdcan, id, header, data, delay_ticks); - } +static uint32_t HAL_RCC_FDCAN_CLK_ENABLED = 0; -static uint32_t HAL_RCC_FDCAN_CLK_ENABLED=0; +void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *fdcanHandle) { -void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle) -{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - GPIO_InitTypeDef GPIO_InitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + if (fdcanHandle->Instance == FDCAN1) { + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; + PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + Error_Handler(); + } - if(fdcanHandle->Instance==FDCAN1) - { - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; - PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) - { - Error_Handler(); - } + /* FDCAN1 clock enable */ + HAL_RCC_FDCAN_CLK_ENABLED++; + if (HAL_RCC_FDCAN_CLK_ENABLED == 1) { + __HAL_RCC_FDCAN_CLK_ENABLE(); + } - /* FDCAN1 clock enable */ - HAL_RCC_FDCAN_CLK_ENABLED++; - if(HAL_RCC_FDCAN_CLK_ENABLED==1){ - __HAL_RCC_FDCAN_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**FDCAN1 GPIO Configuration + PA11 ------> FDCAN1_RX + PA12 ------> FDCAN1_TX + */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* FDCAN1 interrupt Init */ + HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, FDCAN_NVIC_PRIO, 0); + HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); + HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, FDCAN_NVIC_PRIO, 0); + HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn); } + else if (fdcanHandle->Instance == FDCAN3) { + /** Initializes the peripherals clocks + */ + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; + PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + Error_Handler(); + } - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**FDCAN1 GPIO Configuration - PA11 ------> FDCAN1_RX - PA12 ------> FDCAN1_TX - */ - GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* FDCAN1 interrupt Init */ - HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, FDCAN_NVIC_PRIO, 0); - HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); - HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, FDCAN_NVIC_PRIO, 0); - HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn); - } - - else if(fdcanHandle->Instance==FDCAN3) - { - /** Initializes the peripherals clocks - */ - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; - PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) - { - Error_Handler(); - } + /* FDCAN3 clock enable */ + HAL_RCC_FDCAN_CLK_ENABLED++; + if (HAL_RCC_FDCAN_CLK_ENABLED == 1) { + __HAL_RCC_FDCAN_CLK_ENABLE(); + } - /* FDCAN3 clock enable */ - HAL_RCC_FDCAN_CLK_ENABLED++; - if(HAL_RCC_FDCAN_CLK_ENABLED==1){ - __HAL_RCC_FDCAN_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**FDCAN3 GPIO Configuration + PA8 ------> FDCAN3_RX + PA15 ------> FDCAN3_TX + */ + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF11_FDCAN3; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* FDCAN3 interrupt Init */ + HAL_NVIC_SetPriority(FDCAN3_IT0_IRQn, FDCAN_NVIC_PRIO, 0); + HAL_NVIC_EnableIRQ(FDCAN3_IT0_IRQn); + HAL_NVIC_SetPriority(FDCAN3_IT1_IRQn, FDCAN_NVIC_PRIO, 0); + HAL_NVIC_EnableIRQ(FDCAN3_IT1_IRQn); } - - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**FDCAN3 GPIO Configuration - PA8 ------> FDCAN3_RX - PA15 ------> FDCAN3_TX - */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF11_FDCAN3; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* FDCAN3 interrupt Init */ - HAL_NVIC_SetPriority(FDCAN3_IT0_IRQn, FDCAN_NVIC_PRIO, 0); - HAL_NVIC_EnableIRQ(FDCAN3_IT0_IRQn); - HAL_NVIC_SetPriority(FDCAN3_IT1_IRQn, FDCAN_NVIC_PRIO, 0); - HAL_NVIC_EnableIRQ(FDCAN3_IT1_IRQn); - - } } -void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* fdcanHandle) -{ - if(fdcanHandle->Instance==FDCAN1) - { +void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *fdcanHandle) { + if (fdcanHandle->Instance == FDCAN1) { /* Peripheral clock disable */ HAL_RCC_FDCAN_CLK_ENABLED--; - if(HAL_RCC_FDCAN_CLK_ENABLED==0){ - __HAL_RCC_FDCAN_CLK_DISABLE(); + if (HAL_RCC_FDCAN_CLK_ENABLED == 0) { + __HAL_RCC_FDCAN_CLK_DISABLE(); } /**FDCAN1 GPIO Configuration PA11 ------> FDCAN1_RX PA12 ------> FDCAN1_TX */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11 | GPIO_PIN_12); /* FDCAN1 interrupt Deinit */ HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn); } - - else if(fdcanHandle->Instance==FDCAN3) - { + else if (fdcanHandle->Instance == FDCAN3) { /* Peripheral clock disable */ HAL_RCC_FDCAN_CLK_ENABLED--; - if(HAL_RCC_FDCAN_CLK_ENABLED==0){ - __HAL_RCC_FDCAN_CLK_DISABLE(); + if (HAL_RCC_FDCAN_CLK_ENABLED == 0) { + __HAL_RCC_FDCAN_CLK_DISABLE(); } /**FDCAN3 GPIO Configuration PA8 ------> FDCAN3_RX PA15 ------> FDCAN3_TX */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8|GPIO_PIN_15); + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8 | GPIO_PIN_15); /* FDCAN3 interrupt Deinit */ HAL_NVIC_DisableIRQ(FDCAN3_IT0_IRQn); diff --git a/Firmware/Drivers/Src/Contactors.c b/Firmware/Drivers/Src/Contactors.c index 5b4db6dd..b720b40d 100644 --- a/Firmware/Drivers/Src/Contactors.c +++ b/Firmware/Drivers/Src/Contactors.c @@ -4,20 +4,14 @@ static SemaphoreHandle_t contactorsMutex = NULL; static StaticSemaphore_t contactorsMutexBuffer; -static const char *CONTACTOR_NAMES[NUM_CONTACTORS] = { - "Motor Contactor", - "Motor Pre Contactor"}; +static const char *CONTACTOR_NAMES[NUM_CONTACTORS] = {"Motor Contactor", "Motor Pre Contactor"}; // array to hold the contactor structs static contactor_t contactors[NUM_CONTACTORS]; -// get -contactor_state_t contactor_get_sense(contactor_num_t contactor_num) -{ - +contactor_state_t contactor_get_sense(contactor_num_t contactor_num) { // check that contactor exists - if ((contactor_num < 0) || (contactor_num >= NUM_CONTACTORS)) - { + if ((contactor_num < 0) || (contactor_num >= NUM_CONTACTORS)) { Error_Handler(); } @@ -25,56 +19,48 @@ contactor_state_t contactor_get_sense(contactor_num_t contactor_num) return HAL_GPIO_ReadPin(contactor->sense_pin.port, contactor->sense_pin.pin); } -contactor_state_t contactor_get_commanded_state(contactor_num_t contactor_num) -{ +contactor_state_t contactor_get_commanded_state(contactor_num_t contactor_num) { // check that contactor exists - if ((contactor_num < 0) || (contactor_num >= NUM_CONTACTORS)) - { + if ((contactor_num < 0) || (contactor_num >= NUM_CONTACTORS)) { Error_Handler(); } return contactors[contactor_num].state; } -static void vContactorCallback(TimerHandle_t senseTimer) -{ - +static void vContactorCallback(TimerHandle_t senseTimer) { contactor_num_t contactor_num = (contactor_num_t)pvTimerGetTimerID(senseTimer); contactor_t *contactor = &contactors[contactor_num]; - if (contactor->state != contactor_get_sense(contactor_num)) - { - set_faultBit(CALLBACK_FAULT); + if (contactor->state != contactor_get_sense(contactor_num)) { + faults_set(FAULT_ID_CONTACTOR_CALLBACK); } } -/* sets contactor, updates state value, then starts timer to check expected state matches actual state. -An error means semaphore was busy, or that I set a contactor that didn't exist. */ -ErrorStatus contactor_set(contactor_num_t contactor_num, contactor_state_t state, uint32_t wait_ms, fault_state_t emergency) -{ - +/* sets contactor, updates state value, then starts timer to check expected state matches actual +state. An error means semaphore was busy, or that I set a contactor that didn't exist. */ +ErrorStatus contactor_set(contactor_num_t contactor_num, contactor_state_t state, uint32_t wait_ms, + fault_state_t emergency) { // check that contactor exists - if ((contactor_num < 0) || (contactor_num >= NUM_CONTACTORS)) - { + if ((contactor_num < 0) || (contactor_num >= NUM_CONTACTORS)) { return ERROR; } contactor_t *contactor = &contactors[contactor_num]; // if its emergency, dont bother with semaphore - if (!emergency && xSemaphoreTake(contactorsMutex, wait_ms) == pdFALSE) - { + if (!emergency && xSemaphoreTake(contactorsMutex, wait_ms) == pdFALSE) { return ERROR; - }; + } // critical section: HAL_GPIO_WritePin(contactor->control_pin.port, contactor->control_pin.pin, state); contactor->state = state; - /* start timer to check if the state of the contactor makes expected state, the exit critical section. Timer resets - when the contactor is set to another value, so no possible error with expected value changing from when timer is called*/ - if (!emergency) - { + /* start timer to check if the state of the contactor makes expected state, the exit critical + section. Timer resets when the contactor is set to another value, so no possible error with + expected value changing from when timer is called*/ + if (!emergency) { xTimerStart(contactor->senseTimer, 0); xSemaphoreGive(contactorsMutex); } @@ -82,9 +68,7 @@ ErrorStatus contactor_set(contactor_num_t contactor_num, contactor_state_t state return SUCCESS; } -void contactor_init() -{ - +void contactor_init() { // Enable clock for GPIO A/B/C __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); @@ -106,11 +90,8 @@ void contactor_init() contactors[MOTOR_PRE_CONTACTOR].control_pin = Precharge_Contactor_Enable; GPIO_InitTypeDef GPIO_InitStruct = {0}; - // loop to intialize contactor GPIO and timers - for (uint32_t contactor_num = 0; contactor_num < NUM_CONTACTORS; contactor_num++) - { - + for (uint32_t contactor_num = 0; contactor_num < NUM_CONTACTORS; contactor_num++) { contactor_t *contactor = &contactors[contactor_num]; // init contactor control pins @@ -141,10 +122,8 @@ void contactor_init() } } -void contactor_emergency_open_all() -{ - for (uint32_t contactor_num = 0; contactor_num < NUM_CONTACTORS; contactor_num++) - { +void contactor_emergency_open_all() { + for (uint32_t contactor_num = 0; contactor_num < NUM_CONTACTORS; contactor_num++) { contactor_set(contactor_num, OPEN, portMAX_DELAY, EMERGENCY); } } \ No newline at end of file diff --git a/Firmware/Drivers/Src/FaultBits.c b/Firmware/Drivers/Src/FaultBits.c index 05d1fa62..f0faf095 100644 --- a/Firmware/Drivers/Src/FaultBits.c +++ b/Firmware/Drivers/Src/FaultBits.c @@ -1,64 +1,126 @@ +// #include "FaultBits.h" + +// // Event group handle to store fault state bits +// EventGroupHandle_t faultStateBits; + +// // Static buffer to store the event handle +// StaticEventGroup_t faultStateBitsBuffer; + +// uint8_t faultBits_init(void) { +// faultStateBits = xEventGroupCreateStatic(&faultStateBitsBuffer); +// if (faultStateBits == NULL) { +// return 0; +// } +// return 1; +// } + +// void set_faultBit(fault_bit_t bit) { +// // not a valid fault +// if (bit >= NUM_FAULTS) { +// return; +// } + +// // chat we're cooked +// xEventGroupSetBits(faultStateBits, FAULT_BIT(bit)); +// // should never return from here +// taskYIELD(); +// } + +// void set_faultBitFromISR(fault_bit_t bit) { +// BaseType_t xHigherPriorityTaskWoken = pdFALSE; + +// if (bit >= NUM_FAULTS) { +// return; +// } + +// xEventGroupSetBitsFromISR(faultStateBits, FAULT_BIT(bit), &xHigherPriorityTaskWoken); + +// portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +// } + +// EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait) { +// // NUM_FAULTS indiciates you want to wait for all bits +// if (bit > NUM_FAULTS) { +// return 0; +// } + +// // if NUM +// // EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? ALL_FAULT_BITS : (FAULT_BIT(bit)); +// EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? FAULT_BITMASK : (FAULT_BIT(bit)); + +// EventBits_t pending = xEventGroupWaitBits(faultStateBits, +// uxBitsToWaitFor, // wait for any defined fault +// pdFALSE, // fault bits are not reset +// pdFALSE, // wait for ANY bit to be set +// xTicksToWait); +// return pending; +// } + + #include "FaultBits.h" +#include -// Event group handle to store fault state bits -EventGroupHandle_t faultStateBits; +static StaticEventGroup_t faultBuffer; +static EventGroupHandle_t faultGroup; -// Static buffer to store the event handle -StaticEventGroup_t faultStateBitsBuffer; +const char *fault_names[FAULT_ID_COUNT] = { +#define X(name) [FAULT_ID_##name] = #name, + FAULT_ID_LIST(X) +#undef X +}; -uint8_t faultBits_init(void){ - faultStateBits = xEventGroupCreateStatic( &faultStateBitsBuffer ); - if(faultStateBits == NULL){ - return 0; +bool faults_init(void) { + faultGroup = xEventGroupCreateStatic(&faultBuffer); + if (faultGroup == NULL) { + return false; } - return 1; + xEventGroupClearBits(faultGroup, FAULT_MASK_ALL); + return true; } -void set_faultBit(fault_bit_t bit){ - // not a valid fault - if(bit >= NUM_FAULTS){ - return; - } - - // chat we're cooked - xEventGroupSetBits(faultStateBits, FAULT_BIT(bit)); - // should never return from here - taskYIELD(); +void faults_set(FaultID_e id) { + configASSERT(id < FAULT_ID_COUNT); + xEventGroupSetBits(faultGroup, FAULT_BIT(id)); } -void set_faultBitFromISR(fault_bit_t bit){ - BaseType_t xHigherPriorityTaskWoken = pdFALSE; +void faults_set_from_isr(FaultID_e id) { + BaseType_t hpw = pdFALSE; + configASSERT(id < FAULT_ID_COUNT); - if(bit >= NUM_FAULTS){ - return; - } + xEventGroupSetBitsFromISR(faultGroup, FAULT_BIT(id), &hpw); + portYIELD_FROM_ISR(hpw); +} - xEventGroupSetBitsFromISR( - faultStateBits, - FAULT_BIT(bit), - &xHigherPriorityTaskWoken - ); +void faults_set_mask(EventBits_t mask) { + xEventGroupSetBits(faultGroup, mask & FAULT_MASK_ALL); +} - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +void faults_clear(FaultID_e id) { + configASSERT(id < FAULT_ID_COUNT); + xEventGroupClearBits(faultGroup, FAULT_BIT(id)); } -EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait){ +bool faults_any_active(void) { + return (xEventGroupGetBits(faultGroup) & FAULT_MASK_ALL) != 0; +} - // NUM_FAULTS indiciates you want to wait for all bits - if(bit > NUM_FAULTS){ - return 0; - } +bool faults_is_active(FaultID_e id) { + configASSERT(id < FAULT_ID_COUNT); + return (xEventGroupGetBits(faultGroup) & FAULT_BIT(id)) != 0; +} + +EventBits_t faults_get(void) { + return xEventGroupGetBits(faultGroup) & FAULT_MASK_ALL; +} - // if NUM - // EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? ALL_FAULT_BITS : (FAULT_BIT(bit)); - EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? FAULT_BITMASK : (FAULT_BIT(bit)); +EventBits_t faults_wait(FaultID_e id, TickType_t ticks) { + EventBits_t mask = (id == FAULT_ID_COUNT) ? FAULT_MASK_ALL : FAULT_BIT(id); - EventBits_t pending = xEventGroupWaitBits( - faultStateBits, - uxBitsToWaitFor, // wait for any defined fault - pdFALSE, // fault bits are not reset - pdFALSE, // wait for ANY bit to be set - xTicksToWait + return xEventGroupWaitBits( + faultGroup, + mask, + pdFALSE, // don't clear + pdFALSE, // wait for any + ticks ); - return pending; } \ No newline at end of file diff --git a/Firmware/Drivers/Src/MotorSafeBits.c b/Firmware/Drivers/Src/MotorSafeBits.c index 1e1cbf0c..8ce543ec 100644 --- a/Firmware/Drivers/Src/MotorSafeBits.c +++ b/Firmware/Drivers/Src/MotorSafeBits.c @@ -6,73 +6,58 @@ EventGroupHandle_t motorSafeBits; // Static buffer to store the event handle StaticEventGroup_t motorSafeBitsBuffer; - -BaseType_t MotorSafeBits_Init(){ - - motorSafeBits = xEventGroupCreateStatic( &motorSafeBitsBuffer ); - if(motorSafeBits == NULL){ +BaseType_t MotorSafeBits_Init() { + motorSafeBits = xEventGroupCreateStatic(&motorSafeBitsBuffer); + if (motorSafeBits == NULL) { return pdFALSE; } return pdTRUE; } -void set_MotorSafeBit(motor_status_bit_t bit){ +void set_MotorSafeBit(motor_status_bit_t bit) { // not a valid fault - if(bit >= NUM_MOTOR_STATUS_BITS){ - return; - } - if(motorSafeBits == NULL){ + if (bit >= NUM_MOTOR_STATUS_BITS || motorSafeBits == NULL) { return; } - + // set the bit xEventGroupSetBits(motorSafeBits, MOTOR_STATUS_BIT(bit)); } -void clear_MotorSafeBit(motor_status_bit_t bit){ - +void clear_MotorSafeBit(motor_status_bit_t bit) { + // not a valid fault - if(bit >= NUM_MOTOR_STATUS_BITS){ - return; - } - if(motorSafeBits == NULL){ + if (bit >= NUM_MOTOR_STATUS_BITS || motorSafeBits == NULL) { return; } - + // set the bit xEventGroupClearBits(motorSafeBits, MOTOR_STATUS_BIT(bit)); } -EventBits_t MotorSafeBits_WaitMask(EventBits_t bitsToWait, TickType_t delay_ticks){ - - if(motorSafeBits == NULL){ +EventBits_t MotorSafeBits_WaitMask(EventBits_t bitsToWait, TickType_t delay_ticks) { + if (motorSafeBits == NULL) { return 0; } - EventBits_t pending = xEventGroupWaitBits( - motorSafeBits, - bitsToWait, // wait for the given bits to be set - pdFALSE, // fault bits are not reset - pdTRUE, // wait for all bits to be set - delay_ticks - ); - + EventBits_t pending = xEventGroupWaitBits(motorSafeBits, + bitsToWait, // wait for the given bits to be set + pdFALSE, // fault bits are not reset + pdTRUE, // wait for all bits to be set + delay_ticks); + return pending; } -EventBits_t MotorSafeBits_Wait(motor_status_bit_t motor_status_bit, TickType_t delay_ticks){ - - EventBits_t bitsToWaitFor = MOTOR_STATUS_BIT(motor_status_bit); - - if(motorSafeBits == NULL){ +EventBits_t MotorSafeBits_Wait(motor_status_bit_t motor_status_bit, TickType_t delay_ticks) { + if (motorSafeBits == NULL) { return 0; } - EventBits_t pending = xEventGroupWaitBits( - motorSafeBits, - bitsToWaitFor, // wait for the given bits to be set - pdFALSE, // fault bits are not reset - pdTRUE, // wait for all bits to be set - delay_ticks - ); - + EventBits_t bitsToWaitFor = MOTOR_STATUS_BIT(motor_status_bit); + EventBits_t pending = xEventGroupWaitBits(motorSafeBits, + bitsToWaitFor, // wait for the given bits to be set + pdFALSE, // fault bits are not reset + pdTRUE, // wait for all bits to be set + delay_ticks); + return pending; } \ No newline at end of file diff --git a/Firmware/Drivers/Src/StatusLEDs.c b/Firmware/Drivers/Src/StatusLEDs.c index 3f1c39b1..9d2239e8 100644 --- a/Firmware/Drivers/Src/StatusLEDs.c +++ b/Firmware/Drivers/Src/StatusLEDs.c @@ -1,72 +1,64 @@ -// NOTE: LEDs are negative logic, however ON and OFF are defined such that they reflect the actual state of the LED +// NOTE: LEDs are negative logic, however ON and OFF are defined such that they reflect the actual +// state of the LED #include "StatusLEDs.h" static uint16_t LEDbitmap; -static const GpioPin_t DebugLEDs[num_LEDs] = {{PRECHARGE_COMPLETE_LED_PORT, PRECHARGE_COMPLETE_LED_PIN}, - {PRECHARGE_TO_LED_PORT, PRECHARGE_TO_LED_PIN}, - {PRECHARGE_SENSE_TO_LED_PORT, PRECHARGE_SENSE_TO_LED_PIN}, - {MOTOR_SENSE_TO_LED_PORT, MOTOR_SENSE_TO_LED_PIN}, - {DRIVABLE_LED_PORT, DRIVABLE_LED_PIN}, - {DRIVING_LED_PORT, DRIVING_LED_PIN}, - {CRUISE_LED_PORT, CRUISE_LED_PIN}, - {REGEN_LED_PORT, REGEN_LED_PIN}, - {BPS_FAULT_LED_PORT, BPS_FAULT_LED_PIN}, - {CAR_HB_LED_PORT, CAR_HB_LED_PIN}, - {HALL_EFFECT_LED_PORT, HALL_EFFECT_LED_PIN}, - {DAWG_LED_PORT, DAWG_LED_PIN}, - {SWOC_LED_PORT, SWOC_LED_PIN}, - {FAULT_LED_PORT, FAULT_LED_PIN}, - {HB_LED_PORT, HB_LED_PIN}}; +static const GpioPin_t DebugLEDs[num_LEDs] = { + {PRECHARGE_COMPLETE_LED_PORT, PRECHARGE_COMPLETE_LED_PIN}, + {PRECHARGE_TO_LED_PORT, PRECHARGE_TO_LED_PIN}, + {PRECHARGE_SENSE_TO_LED_PORT, PRECHARGE_SENSE_TO_LED_PIN}, + {MOTOR_SENSE_TO_LED_PORT, MOTOR_SENSE_TO_LED_PIN}, + {DRIVABLE_LED_PORT, DRIVABLE_LED_PIN}, + {DRIVING_LED_PORT, DRIVING_LED_PIN}, + {CRUISE_LED_PORT, CRUISE_LED_PIN}, + {REGEN_LED_PORT, REGEN_LED_PIN}, + {BPS_FAULT_LED_PORT, BPS_FAULT_LED_PIN}, + {CAR_HB_LED_PORT, CAR_HB_LED_PIN}, + {HALL_EFFECT_LED_PORT, HALL_EFFECT_LED_PIN}, + {DAWG_LED_PORT, DAWG_LED_PIN}, + {SWOC_LED_PORT, SWOC_LED_PIN}, + {FAULT_LED_PORT, FAULT_LED_PIN}, + {HB_LED_PORT, HB_LED_PIN} +}; -void Toggle_LED(Status_Mapping_t LED) -{ +void Toggle_LED(Status_Mapping_t LED) { if (LED < 0 || LED >= num_LEDs) { return; } HAL_GPIO_TogglePin(DebugLEDs[LED].port, DebugLEDs[LED].pin); } -void LED_set(Status_Mapping_t LED, LED_state_t state) -{ +void LED_set(Status_Mapping_t LED, LED_state_t state) { // make sure LED is within bound - if(LED > num_LEDs || LED < 0){ + if (LED > num_LEDs || LED < 0) { return; } - if(LED == HB){ + if (LED == HB) { // the heartbeat LED is the only positive logic LED HAL_GPIO_WritePin(DebugLEDs[LED].port, DebugLEDs[LED].pin, !state); - } - else{ + } else { HAL_GPIO_WritePin(DebugLEDs[LED].port, DebugLEDs[LED].pin, state); } } -void LEDs_clear() -{ +void LEDs_clear() { LEDbitmap = 0; - for (int i = 0; i < num_LEDs; i++) - { + for (int i = 0; i < num_LEDs; i++) { LED_set(i, LED_OFF); } } - -void LEDs_init() -{ - +void LEDs_init() { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); - for (size_t i = 0; i < num_LEDs; ++i) - { + for (size_t i = 0; i < num_LEDs; ++i) { GPIO_InitTypeDef led_config = { - .Mode = GPIO_MODE_OUTPUT_PP, - .Pull = GPIO_NOPULL, - .Pin = DebugLEDs[i].pin}; + .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_NOPULL, .Pin = DebugLEDs[i].pin}; HAL_GPIO_Init(DebugLEDs[i].port, &led_config); LED_set(i, LED_OFF); diff --git a/Firmware/Drivers/Src/UART_Init.c b/Firmware/Drivers/Src/UART_Init.c index c7ab7da5..fd1c2d84 100644 --- a/Firmware/Drivers/Src/UART_Init.c +++ b/Firmware/Drivers/Src/UART_Init.c @@ -1,7 +1,6 @@ #include "UART_Init.h" -void Init_UART_Printf() -{ +void Init_UART_Printf() { husart3->Instance = USART3; husart3->Init.BaudRate = 115200; husart3->Init.WordLength = UART_WORDLENGTH_8B; @@ -17,18 +16,17 @@ void Init_UART_Printf() printf_init(husart3); } -void HAL_UART_MspGPIOInit(UART_HandleTypeDef* huart){ +void HAL_UART_MspGPIOInit(UART_HandleTypeDef *huart) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitTypeDef GPIO_InitStruct = {0}; - - // for the ESP32 - if(huart->Instance == LPUART1){ + // for the ESP32 + if (huart->Instance == LPUART1) { __HAL_RCC_GPIOB_CLK_ENABLE(); /**LPUART1 GPIO Configuration PB10 ------> LPUART1_RX PB11 ------> LPUART1_TX */ - GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; + GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; @@ -37,20 +35,18 @@ void HAL_UART_MspGPIOInit(UART_HandleTypeDef* huart){ } // for printf - if(huart->Instance == USART3){ - - __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART3 GPIO Configuration - PC10 ------> USART3_TX - PC11 ------> USART3_RX - */ - GPIO_InitStruct.Pin = USART3_TX_PIN | USART3_RX_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF7_USART3; - HAL_GPIO_Init(USART3_PORT, &GPIO_InitStruct); - - } + if (huart->Instance == USART3) { + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**USART3 GPIO Configuration + PC10 ------> USART3_TX + PC11 ------> USART3_RX + */ + GPIO_InitStruct.Pin = USART3_TX_PIN | USART3_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF7_USART3; + HAL_GPIO_Init(USART3_PORT, &GPIO_InitStruct); + } } \ No newline at end of file diff --git a/Firmware/Drivers/Src/Watchdogs.c b/Firmware/Drivers/Src/Watchdogs.c new file mode 100644 index 00000000..fd2c91b2 --- /dev/null +++ b/Firmware/Drivers/Src/Watchdogs.c @@ -0,0 +1,80 @@ +/** + * @file Watchdogs.c + * @brief CAN message watchdog implementation + * @copyright Copyright (c) 2018-2026 UT Longhorn Racing Solar + */ + +#include "Watchdogs.h" +#include "FaultBits.h" +#include +#include + +static StaticTimer_t wd_buffers[MAX_WD_TIMERS]; +static TimerHandle_t wd_timers[MAX_WD_TIMERS]; +static bool wd_alive[MAX_WD_TIMERS]; +static FaultID_e wd_fault_ids[MAX_WD_TIMERS]; +static uint8_t wd_count = 0; + +// Callback function for when a watchdog timer expires +static void wd_callback(TimerHandle_t xTimer) { + uint8_t idx = (uint8_t)(uintptr_t)pvTimerGetTimerID(xTimer); + wd_alive[idx] = false; + printf("WD timeout: signal %d\n", idx); + faults_set(wd_fault_ids[idx]); +} + +void watchdog_init(void) { + memset(wd_timers, 0, sizeof(wd_timers)); + memset(wd_alive, 0, sizeof(wd_alive)); + wd_count = 0; +} + +void watchdog_create(const char *name, uint8_t idx, uint32_t timeout_ms, FaultID_e fault_id) { + configASSERT(wd_count < MAX_WD_TIMERS); + configASSERT(idx < MAX_WD_TIMERS); + + TimerHandle_t t = xTimerCreateStatic( + name, + pdMS_TO_TICKS(timeout_ms), + pdFALSE, // one-shot + (void *)(uintptr_t)idx, + wd_callback, + &wd_buffers[wd_count] + ); + configASSERT(t != NULL); + wd_timers[wd_count] = t; + wd_alive[idx] = true; + wd_fault_ids[idx] = fault_id; + wd_count++; +} + +void watchdog_start_all(void) { + for (uint8_t i = 0; i < wd_count; i++) { + configASSERT(xTimerStart(wd_timers[i], portMAX_DELAY) == pdPASS); + } +} + +void watchdog_stop_all(void) { + for (uint8_t i = 0; i < wd_count; i++) { + xTimerStop(wd_timers[i], portMAX_DELAY); + } +} + +void watchdog_received_can_message(uint8_t idx) { + configASSERT(idx < MAX_WD_TIMERS && wd_timers[idx] != NULL); + wd_alive[idx] = true; + xTimerReset(wd_timers[idx], 0); +} + +void watchdog_received_can_message_ISR(uint8_t idx, BaseType_t *pxHigherPriorityTaskWoken) { + configASSERT(idx < MAX_WD_TIMERS && wd_timers[idx] != NULL); + wd_alive[idx] = true; + xTimerResetFromISR(wd_timers[idx], pxHigherPriorityTaskWoken); +} + +bool watchdog_is_alive(int idx) { + if (idx < 0 || idx >= MAX_WD_TIMERS) return false; + return wd_alive[idx]; +} + +uint8_t watchdog_count(void) { return wd_count; } diff --git a/Firmware/Tasks/Inc/FaultHandlerTask.h b/Firmware/Tasks/Inc/FaultHandlerTask.h index b9bc0dea..d928a2b0 100644 --- a/Firmware/Tasks/Inc/FaultHandlerTask.h +++ b/Firmware/Tasks/Inc/FaultHandlerTask.h @@ -7,23 +7,6 @@ #include "InitTask.h" #include "MotorSafeBits.h" -#define MAX_FAULT_STRING_CHARS 20 - -typedef struct{ - const char fault_string[MAX_FAULT_STRING_CHARS]; - uint8_t faultStringSize; -}fault_string_t; - - -/** @brief Initialize the fault handler task. */ -void Init_FaultHandlerTask(); /** @brief Run the fault handler task. */ void Task_FaultHandler(); - -/** @brief Kill the precharge task. */ -void Kill_Precharge_Task(); - -void Fault_Loop(); - -void Set_Fault_LED(); \ No newline at end of file diff --git a/Firmware/Tasks/Src/CanTxTelemetryTask.c b/Firmware/Tasks/Src/CanTxTelemetryTask.c index 0e8fc41f..2806a633 100644 --- a/Firmware/Tasks/Src/CanTxTelemetryTask.c +++ b/Firmware/Tasks/Src/CanTxTelemetryTask.c @@ -1,80 +1,64 @@ #include "CanTxTelemetryTask.h" -#define CAN_TX_TELEMETRY_QUEUE_SIZE 10 +#define CAN_TX_TELEMETRY_QUEUE_SIZE 10 static StaticQueue_t canTxTelemetryQueueBuffer; static uint8_t canTxTelemetryQueueStorage[CAN_TX_TELEMETRY_QUEUE_SIZE * sizeof(can_tx_payload_t)]; static QueueHandle_t canTxTelemetryQueue; +void can_tx_print_slcan(const can_tx_payload_t payload) { -void can_tx_print_slcan(const can_tx_payload_t payload) -{ - - uint32_t id = payload.header.Identifier; - uint8_t len = (payload.header.DataLength); + uint32_t id = payload.header.Identifier; + uint8_t len = (payload.header.DataLength); /* SLCAN supports max 8 bytes */ - if (len > 8) - len = 8; + if (len > 8) len = 8; - if (payload.header.IdType == FDCAN_STANDARD_ID) - { + if (payload.header.IdType == FDCAN_STANDARD_ID) { /* tIII DLC DATA... */ printf("t%03lX%1X", id & 0x7FF, len); - } - else - { + } else { /* TIIIIIIII DLC DATA... */ printf("T%08lX%1X", id & 0x1FFFFFFF, len); } - for (uint8_t i = 0; i < len; i++) - { + for (uint8_t i = 0; i < len; i++) { printf("%02X", payload.data[i]); } printf("\r\n"); } -void CanTxTelemetryTask_Init(void){ - canTxTelemetryQueue = xQueueCreateStatic( - CAN_TX_TELEMETRY_QUEUE_SIZE, - sizeof(can_tx_payload_t), - canTxTelemetryQueueStorage, - &canTxTelemetryQueueBuffer - ); +void CanTxTelemetryTask_Init(void) { + canTxTelemetryQueue = + xQueueCreateStatic(CAN_TX_TELEMETRY_QUEUE_SIZE, sizeof(can_tx_payload_t), + canTxTelemetryQueueStorage, &canTxTelemetryQueueBuffer); - if(canTxTelemetryQueue == NULL){ + if (canTxTelemetryQueue == NULL) { return; } } -void can_fd_tx_callback_hook(FDCAN_HandleTypeDef* hfdcan, const can_tx_payload_t* payload){ +void can_fd_tx_callback_hook(FDCAN_HandleTypeDef *hfdcan, const can_tx_payload_t *payload) { BaseType_t higherPriorityTaskWoken = pdFALSE; - if(canTxTelemetryQueue != NULL){ - xQueueSendFromISR( - canTxTelemetryQueue, - payload, - &higherPriorityTaskWoken - ); - + if (canTxTelemetryQueue != NULL) { + xQueueSendFromISR(canTxTelemetryQueue, payload, &higherPriorityTaskWoken); } // don't yield at the end of this since the rest of the ISR needs to run } - -void Task_CanTxTelemetry(){ +void Task_CanTxTelemetry() { // car canbus MUST be initialized by now CanTxTelemetryTask_Init(); can_tx_payload_t payload; - while(1){ + while (1) { // forward all transmitted can messages to USB - if (xQueueReceive(canTxTelemetryQueue, &payload, portMAX_DELAY) == pdTRUE){ + if (xQueueReceive(canTxTelemetryQueue, &payload, portMAX_DELAY) == pdTRUE) { // TODO: use the embedded-sharepoint slcan formatter can_tx_print_slcan(payload); // TODO: should also forward data to ESP32 diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index d28c8200..ad11c638 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -1,143 +1,249 @@ +// #include "FaultHandlerTask.h" +// #include "PrechargeTask.h" // for hprecharge_task handle + +// #define FAULT_LOOP_PRINTF_DELAY_MS 10000 + +// #define FAULT_PRINTF_COUNTER (FAULT_LOOP_PRINTF_DELAY_MS / FAULT_LOOP_PERIOD_MS) + +// EventBits_t fault_bits = 0; + +// void Init_FaultHandlerTask() { +// if (!faults_init()) { +// // Fault bit initialization failed +// Error_Handler(); +// } +// } + +// void Kill_Precharge_Task() { +// if (hprecharge_task != NULL) { +// vTaskDelete(hprecharge_task); +// } +// } + +// static void print_fault() { +// switch (fault_bits) // compare against individual bitmasks +// { +// case FAULT_BIT(FAULT_ID_MOTOR_GT_BATTERY): +// printf("Fault: Motor Voltage Greater Than Battery Voltage\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_BATTERY_OVERVOLTAGE): +// printf("Fault: Battery Overvoltage\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_BATTERY_UNDERVOLTAGE): +// printf("Fault: Battery Undervoltage\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_TIMEOUT): +// printf("Fault: Motor Sense Timeout\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_TIMEOUT): +// printf("Fault: Precharge Sense Timeout\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_PRECHARGE_TIMEOUT): +// printf("Fault: Precharge Sequence Timeout\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK): +// printf("Fault: Contactor Sense Fault\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_MISMATCH): +// printf("Fault: Motor Sense Mismatch\r\n"); +// break; +// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_MISMATCH): +// printf("Fault: Precharge Sense Mismatch\r\n"); +// break; +// default: +// printf("Fault: Unknown\r\n"); +// break; +// } +// } + +// void Fault_Loop() { +// uint32_t fault_printf_debug_counter = 0; +// while (1) { +// fault_printf_debug_counter++; + +// if (fault_printf_debug_counter >= FAULT_PRINTF_COUNTER) { +// print_fault(); +// fault_printf_debug_counter = 0; +// } + +// Toggle_LED(HB); +// vTaskDelay(FAULT_LOOP_PERIOD_MS); +// } +// } + +// void Set_Fault_LED() { +// switch (fault_bits) // compare against individual bitmasks +// { +// case FAULT_BIT(FAULT_ID_MOTOR_GT_BATTERY): +// LED_set(CAR_BPSFAULT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_BATTERY_OVERVOLTAGE): +// LED_set(CAR_BPSFAULT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_BATTERY_UNDERVOLTAGE): +// LED_set(CAR_BPSFAULT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_TIMEOUT): +// LED_set(MOTOR_SENSE_TIMEOUT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_TIMEOUT): +// LED_set(PRECHARGE_SENSE_TIMEOUT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_PRECHARGE_TIMEOUT): +// LED_set(PRECHARGE_TIMEOUT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK): +// LED_set(CAR_BPSFAULT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_MISMATCH): +// LED_set(CAR_BPSFAULT, LED_ON); +// break; +// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_MISMATCH): +// LED_set(CAR_BPSFAULT, LED_ON); +// break; +// default: +// break; +// } +// } + +// void Task_FaultHandler() { +// Init_FaultHandlerTask(); + +// while (true) { +// fault_bits = faults_wait(FAULT_ID_COUNT, portMAX_DELAY); + +// if (fault_bits != 0) { +// Kill_Precharge_Task(); +// contactor_emergency_open_all(); + +// // prevents the motor from running +// clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); +// clear_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); + +// printf("Fault Handler triggered with bitmask: 0x%02lX\r\n", fault_bits); + +// Set_Fault_LED(); +// Fault_Loop(); +// } + +// vTaskDelay(1000); +// } +// } + #include "FaultHandlerTask.h" -#include "PrechargeTask.h" // for hprecharge_task handle +#include "PrechargeTask.h" // for hprecharge_task handle +#include "Watchdogs.h" #define FAULT_LOOP_PRINTF_DELAY_MS 10000 +#define FAULT_PRINTF_COUNTER (FAULT_LOOP_PRINTF_DELAY_MS / FAULT_LOOP_PERIOD_MS) -#define FAULT_PRINTF_COUNTER (FAULT_LOOP_PRINTF_DELAY_MS/FAULT_LOOP_PERIOD_MS) - -EventBits_t fault_bits = 0; - -void Init_FaultHandlerTask() -{ - if (faultBits_init() != 1) - { - // Fault bit initialization failed - Error_Handler(); - } -} -void Kill_Precharge_Task() -{ - if (hprecharge_task != NULL) - { +static void FHT_kill_precharge_task(void) { + if (hprecharge_task != NULL) { vTaskDelete(hprecharge_task); + hprecharge_task = NULL; } } -static void print_fault(){ - switch (fault_bits) // compare against individual bitmasks - { - case FAULT_BIT(MOTOR_GREATER_THAN_BATTERY_FAULT): - printf("Fault: Motor Voltage Greater Than Battery Voltage\r\n"); - break; - case FAULT_BIT(BATTERY_OVERVOLTAGE_FAULT): - printf("Fault: Battery Overvoltage\r\n"); - break; - case FAULT_BIT(BATTERY_UNDERVOLTAGE_FAULT): - printf("Fault: Battery Undervoltage\r\n"); - break; - case FAULT_BIT(MOTOR_SENSE_TIMEOUT_FAULT): - printf("Fault: Motor Sense Timeout\r\n"); - break; - case FAULT_BIT(PRECHARGE_SENSE_TIMEOUT_FAULT): - printf("Fault: Precharge Sense Timeout\r\n"); - break; - case FAULT_BIT(PRECHARGE_TIMEOUT_FAULT): - printf("Fault: Precharge Sequence Timeout\r\n"); - break; - case FAULT_BIT(CALLBACK_FAULT): - printf("Fault: Contactor Sense Fault\r\n"); - break; - case FAULT_BIT(MOTOR_SENSE_MISMATCH_FAULT): - printf("Fault: Motor Sense Mismatch\r\n"); - break; - case FAULT_BIT(PRECHARGE_SENSE_MISMATCH_FAULT): - printf("Fault: Precharge Sense Mismatch\r\n"); - break; - default: - printf("Fault: Unknown\r\n"); - break; - } -} - -void Fault_Loop() -{ - uint32_t fault_printf_debug_counter = 0; - while (1) - { - fault_printf_debug_counter++; - - if(fault_printf_debug_counter >= FAULT_PRINTF_COUNTER){ - print_fault(); - fault_printf_debug_counter = 0; +// Sets fault LEDs based on which faults are active. Multiple faults may be +// active at once, so multiple LEDs may be set. +static void FHT_set_fault_leds(EventBits_t bits) { + // TODO add a generic fault LED + //LED_set(FAULT_LED, LED_ON); + for (FaultID_e i = 0; i < FAULT_ID_COUNT; i++) { + if (bits & FAULT_BIT(i)) { + switch (i) { + /* ============= MOTOR CONTROLLER ============ */ + case FAULT_ID_MOTOR_HARDWARE_OVERCURRENT: + case FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE: + case FAULT_ID_MOTOR_WD_RESET: + case FAULT_ID_MOTOR_CONFIG_READ: + case FAULT_ID_MOTOR_15V_UNDERVOLTAGE: + case FAULT_ID_MOTOR_DESATURATION: + case FAULT_ID_MOTOR_OVERSPEED: + LED_set(MOTOR_FAULT, LED_ON); + break; + case FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT: + LED_set(SWOC, LED_ON); + break; + case FAULT_ID_MOTOR_BAD_HALL_SEQUENCE: + LED_set(HALL_EFFECT, LED_ON); + break; + + /* ================ PRECHARGE ================ */ + case FAULT_ID_PRECHARGE_TIMEOUT: + case FAULT_ID_PRECHARGE_SENSE_TIMEOUT: + case FAULT_ID_PRECHARGE_SENSE_MISMATCH: + case FAULT_ID_MOTOR_SENSE_TIMEOUT: + case FAULT_ID_MOTOR_SENSE_MISMATCH: + case FAULT_ID_BATTERY_OVERVOLTAGE: + case FAULT_ID_BATTERY_UNDERVOLTAGE: + case FAULT_ID_MOTOR_GT_BATTERY: + case FAULT_ID_CONTACTOR_CALLBACK: + // TODO add a precharge fault led + break; + + /* ============== OTHER BOARDS =============== */ + case FAULT_ID_STEERING_SENSOR_FAULT: + case FAULT_ID_PEDAL_BOARD_FAULT: + case FAULT_ID_CONTROLS_FAULT: + // TODO add other leds + break; + case FAULT_ID_BPS_FAULT: + LED_set(CAR_BPSFAULT, LED_ON); + break; + case FAULT_ID_GENERIC_WATCHDOG_FAULT: + LED_set(WATCHDOG, LED_ON); + break; + + default: + // TODO unknown fault, turn on generic fault LED + //LED_set(FAULT_LED, LED_ON); + break; + } } - - Toggle_LED(HB); - vTaskDelay(FAULT_LOOP_PERIOD_MS); - } } -void Set_Fault_LED() -{ - switch (fault_bits) // compare against individual bitmasks - { - case FAULT_BIT(MOTOR_GREATER_THAN_BATTERY_FAULT): - LED_set(CAR_BPSFAULT, LED_ON); - break; - case FAULT_BIT(BATTERY_OVERVOLTAGE_FAULT): - LED_set(CAR_BPSFAULT, LED_ON); - break; - case FAULT_BIT(BATTERY_UNDERVOLTAGE_FAULT): - LED_set(CAR_BPSFAULT, LED_ON); - break; - case FAULT_BIT(MOTOR_SENSE_TIMEOUT_FAULT): - LED_set(MOTOR_SENSE_TIMEOUT, LED_ON); - break; - case FAULT_BIT(PRECHARGE_SENSE_TIMEOUT_FAULT): - LED_set(PRECHARGE_SENSE_TIMEOUT, LED_ON); - break; - case FAULT_BIT(PRECHARGE_TIMEOUT_FAULT): - LED_set(PRECHARGE_TIMEOUT, LED_ON); - break; - case FAULT_BIT(CALLBACK_FAULT): - LED_set(CAR_BPSFAULT, LED_ON); - break; - case FAULT_BIT(MOTOR_SENSE_MISMATCH_FAULT): - LED_set(CAR_BPSFAULT, LED_ON); - break; - case FAULT_BIT(PRECHARGE_SENSE_MISMATCH_FAULT): - LED_set(CAR_BPSFAULT, LED_ON); - break; - default: - break; +void Task_FaultHandler(void *args __attribute__((unused))) { + if (!faults_init()) { + // Fault bit initialization failed, cannot proceed safely + Error_Handler(); } -} - -void Task_FaultHandler() -{ - Init_FaultHandlerTask(); - while (1) - { - fault_bits = faultBit_wait(NUM_FAULTS, portMAX_DELAY); + while (true) { + EventBits_t bits = faults_wait(FAULT_ID_COUNT, portMAX_DELAY); - if (fault_bits != 0) - { - Kill_Precharge_Task(); + if (bits != 0) { + FHT_kill_precharge_task(); contactor_emergency_open_all(); - - // prevents the motor from running clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); clear_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); - - printf("Fault Handler triggered with bitmask: 0x%02lX\r\n", fault_bits); - - Set_Fault_LED(); - Fault_Loop(); + // fsm_disable(); + watchdog_stop_all(); + + printf("Fault Handler triggered: 0x%02lX\r\n", bits); + + // Loop to display/handle fault until system reset + uint32_t print_counter = 0; + while (true) { + print_counter++; + if (print_counter >= FAULT_PRINTF_COUNTER) { + for (int i = 0; i < FAULT_ID_COUNT; i++) { + if (bits & FAULT_BIT(i)) { + printf("Fault: %s\r\n", fault_names[i]); + } + } + print_counter = 0; + } + + FHT_set_fault_leds(bits); + Toggle_LED(HB); + vTaskDelay(pdMS_TO_TICKS(FAULT_LOOP_PERIOD_MS)); + } } - - vTaskDelay(1000); + + vTaskDelay(pdMS_TO_TICKS(1000)); } -} \ No newline at end of file +} diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 37e4b8d1..31f94951 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -9,7 +9,6 @@ StackType_t Precharge_Task_Stack[PRECHARGE_TASK_STACK_SIZE]; StaticTask_t Init_Task_Buffer; StackType_t Init_Task_Stack[INIT_TASK_STACK_SIZE]; - StaticTask_t Motor_Control_Task_Buffer; StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; @@ -19,8 +18,7 @@ StackType_t Motor_Telemetry_Task_Stack[MOTOR_TELEMETRY_TASK_STACK_SIZE]; StaticTask_t Can_Tx_Telemetry_Task_Buffer; StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; -void Task_Init() -{ +void Task_Init() { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); @@ -81,6 +79,5 @@ void Task_Init() &Can_Tx_Telemetry_Task_Buffer // Static task buffer (optional) ); - vTaskDelete(NULL); } \ No newline at end of file diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index 86ce4ceb..f42a4e67 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -1,7 +1,7 @@ #include "PrechargeTask.h" #define PRECHARGE_PRINTF_DEBUG_PERIOD_MS 10000 -#define PRECHARGE_PRINTF_DEBUG_COUNTER (PRECHARGE_PRINTF_DEBUG_PERIOD_MS/PRECHARGE_TASK_DELAY_MS) +#define PRECHARGE_PRINTF_DEBUG_COUNTER (PRECHARGE_PRINTF_DEBUG_PERIOD_MS / PRECHARGE_TASK_DELAY_MS) /* handle for the Precharge task, defined here */ TaskHandle_t hprecharge_task = NULL; @@ -9,8 +9,7 @@ TaskHandle_t hprecharge_task = NULL; StaticEventGroup_t xPrechargeEventGroup; EventGroupHandle_t xPrechargeEventGroup_handle; -void Init_PrechargeTask() -{ +void Init_PrechargeTask() { // Event Group init xPrechargeEventGroup_handle = xEventGroupCreateStatic(&xPrechargeEventGroup); configASSERT(xPrechargeEventGroup_handle); // check if handle is set @@ -22,44 +21,39 @@ void Init_PrechargeTask() contactor_init(); } -void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage) -{ - if (Motor_Voltage > (Battery_Voltage * VOLTAGE_TOLERANCE_NUMERATOR / VOLTAGE_TOLERANCE_DENOMINATOR)) - { +void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage) { + if (Motor_Voltage > + (Battery_Voltage * VOLTAGE_TOLERANCE_NUMERATOR / VOLTAGE_TOLERANCE_DENOMINATOR)) { // Fault handler - set_faultBit(MOTOR_GREATER_THAN_BATTERY_FAULT); + faults_set(FAULT_ID_MOTOR_GT_BATTERY); } - if (Battery_Voltage > OVERVOLTAGE_THRESHOLD_MV) - { + if (Battery_Voltage > OVERVOLTAGE_THRESHOLD_MV) { /* BATTERY ABOUT TO GO BOOM */ // Fault handler - set_faultBit(BATTERY_OVERVOLTAGE_FAULT); + faults_set(FAULT_ID_BATTERY_OVERVOLTAGE); } - if (Battery_Voltage < UNDERVOLTAGE_THRESHOLD_MV) - { + if (Battery_Voltage < UNDERVOLTAGE_THRESHOLD_MV) { /* Battery voltage is too low or battery is disconnected, treat as fault */ // Fault handler - set_faultBit(BATTERY_UNDERVOLTAGE_FAULT); + faults_set(FAULT_ID_BATTERY_UNDERVOLTAGE); } - if (contactor_get_sense(MOTOR_CONTACTOR) != contactor_get_commanded_state(MOTOR_CONTACTOR)) - { + if (contactor_get_sense(MOTOR_CONTACTOR) != contactor_get_commanded_state(MOTOR_CONTACTOR)) { // Fault handler - set_faultBit(MOTOR_SENSE_MISMATCH_FAULT); + faults_set(FAULT_ID_MOTOR_SENSE_MISMATCH); } - if (contactor_get_sense(MOTOR_PRE_CONTACTOR) != contactor_get_commanded_state(MOTOR_PRE_CONTACTOR)) - { + if (contactor_get_sense(MOTOR_PRE_CONTACTOR) != + contactor_get_commanded_state(MOTOR_PRE_CONTACTOR)) { // Fault handler - set_faultBit(PRECHARGE_SENSE_MISMATCH_FAULT); + faults_set(FAULT_ID_PRECHARGE_SENSE_MISMATCH); } } -static void print_Precharge_State(Precharge_State_t State){ - switch (State) - { +static void print_Precharge_State(Precharge_State_t State) { + switch (State) { case PRECHARGE_STATE_INITIAL: printf("Precharge State: Initial\r\n"); break; @@ -75,8 +69,7 @@ static void print_Precharge_State(Precharge_State_t State){ } } -void Task_Precharge() -{ +void Task_Precharge() { Init_PrechargeTask(); static Precharge_State_t State = PRECHARGE_STATE_INITIAL; @@ -84,12 +77,9 @@ void Task_Precharge() uint8_t printDebugCounter = 0; - while (1) - { - + while (1) { ADC_Sense_Result ADC_Result = {0}; - if (Read_ADC(ADC_TIMEOUT_MS, &ADC_Result) != ADC_SENSE_OK) - { + if (Read_ADC(ADC_TIMEOUT_MS, &ADC_Result) != ADC_SENSE_OK) { Error_Handler(); } @@ -98,82 +88,79 @@ void Task_Precharge() printDebugCounter++; - switch (State) - { - case PRECHARGE_STATE_INITIAL: // Startup state: Closes main contactor and moves to precharging state - if (contactor_set(MOTOR_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) - { - set_faultBit(MOTOR_SENSE_TIMEOUT_FAULT); + switch (State) { + case PRECHARGE_STATE_INITIAL: // Startup state: Closes main contactor and moves to + // precharging state + if (contactor_set(MOTOR_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) { + faults_set(FAULT_ID_MOTOR_SENSE_TIMEOUT); } State = PRECHARGE_STATE_PRECHARGING; // Start a timer for precharging Start_Tick = xTaskGetTickCount(); break; - case PRECHARGE_STATE_PRECHARGING: // Precharging state: Waits for battery voltage to reach 90% of motor voltage, then closes precharge contactor and moves to run state - - Fault_Checker(Motor_Voltage, Battery_Voltage); // Check for faults while precharging, if any fault conditions are met, will call fault handler and not proceed with precharge sequence - - const TickType_t Current_Tick = xTaskGetTickCount(); // Check how long we've been precharging for, fault if not precharged after PRECHARGE_TIMEOUT_MS - if ((Current_Tick - Start_Tick) > pdMS_TO_TICKS(PRECHARGE_TIMEOUT_MS)) // Faults if precharging takes too long - { + case PRECHARGE_STATE_PRECHARGING: // Precharging state: Waits for battery voltage to + // reach 90% of motor voltage, then closes precharge + // contactor and moves to run state + + // Check for faults while precharging, if any fault conditions are met, will call + // fault handler and not proceed with precharge sequence + Fault_Checker(Motor_Voltage, Battery_Voltage); + + // Check how long we've been precharging for. + // Fault if not precharged after PRECHARGE_TIMEOUT_MS + const TickType_t Current_Tick = xTaskGetTickCount(); + if ((Current_Tick - Start_Tick) > pdMS_TO_TICKS(PRECHARGE_TIMEOUT_MS)) { // Check if motor voltage is within 90% of battery voltage (precharge complete) - if (Motor_Voltage * RATIO_SCALE >= Battery_Voltage * PRECHARGE_THRESHOLD_90) - { - if (contactor_set(MOTOR_PRE_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, false) != SUCCESS) - { - set_faultBit(PRECHARGE_SENSE_TIMEOUT_FAULT); + if (Motor_Voltage * RATIO_SCALE >= Battery_Voltage * PRECHARGE_THRESHOLD_90) { + if (contactor_set(MOTOR_PRE_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, + false) != SUCCESS) { + faults_set(FAULT_ID_PRECHARGE_SENSE_TIMEOUT); } State = PRECHARGE_STATE_RUN; - } - else - { + } else { // Precharging took too long - set_faultBit(PRECHARGE_TIMEOUT_FAULT); + faults_set(FAULT_ID_PRECHARGE_TIMEOUT); } } break; - case PRECHARGE_STATE_RUN: // Run state: Continuously checks that motor voltage stays within 80% of battery voltage + case PRECHARGE_STATE_RUN: // Run state: Continuously checks that motor voltage stays + // within 80% of battery voltage - Fault_Checker(Motor_Voltage, Battery_Voltage); // Check for faults while precharging, if any fault conditions are met, will call fault handler and not proceed with precharge sequence + // Check for faults while precharging, if any fault conditions are met, will call + // fault handler and not proceed with precharge sequence + Fault_Checker(Motor_Voltage, Battery_Voltage); // Use 80% threshold for hysteresis - if (Motor_Voltage * RATIO_SCALE < Battery_Voltage * PRECHARGE_THRESHOLD_80) - { - + if (Motor_Voltage * RATIO_SCALE < Battery_Voltage * PRECHARGE_THRESHOLD_80) { } break; default: break; } - if(printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER){ - + if (printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER) { // prints battery and motor voltage - printf("Motor: %ld mV | Battery: %ld mV\r\n", - Motor_Voltage, - Battery_Voltage); + printf("Motor: %ld mV | Battery: %ld mV\r\n", Motor_Voltage, Battery_Voltage); // prints current precharge state print_Precharge_State(State); printDebugCounter = 0; } - // set the Precharge Complete LED + // set the Precharge Complete LED LED_set(PRECHARGE_COMPLETE, State == PRECHARGE_STATE_RUN ? LED_ON : LED_OFF); - // update the motor safe bits with Contactor state - if(contactor_get_sense(MOTOR_PRE_CONTACTOR) == CLOSED){ + // update the motor safe bits with Contactor state + if (contactor_get_sense(MOTOR_PRE_CONTACTOR) == CLOSED) { set_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); - } - else{ + } else { clear_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); } - if(contactor_get_sense(MOTOR_CONTACTOR) == CLOSED){ + if (contactor_get_sense(MOTOR_CONTACTOR) == CLOSED) { set_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); - } - else{ + } else { clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); } diff --git a/Firmware/config/Inc/pinDefs.h b/Firmware/config/Inc/pinDefs.h index eee24cb4..a782a096 100644 --- a/Firmware/config/Inc/pinDefs.h +++ b/Firmware/config/Inc/pinDefs.h @@ -2,89 +2,89 @@ #include "stm32xx_hal.h" -#define HB_LED_PORT GPIOC -#define HB_LED_PIN GPIO_PIN_3 +#define HB_LED_PORT GPIOC +#define HB_LED_PIN GPIO_PIN_3 // Car State LEDs -#define DRIVABLE_LED_PORT GPIOC -#define DRIVABLE_LED_PIN GPIO_PIN_6 +#define DRIVABLE_LED_PORT GPIOC +#define DRIVABLE_LED_PIN GPIO_PIN_6 -#define DRIVING_LED_PORT GPIOC -#define DRIVING_LED_PIN GPIO_PIN_9 +#define DRIVING_LED_PORT GPIOC +#define DRIVING_LED_PIN GPIO_PIN_9 -#define CRUISE_LED_PORT GPIOB -#define CRUISE_LED_PIN GPIO_PIN_13 +#define CRUISE_LED_PORT GPIOB +#define CRUISE_LED_PIN GPIO_PIN_13 -#define REGEN_LED_PORT GPIOB -#define REGEN_LED_PIN GPIO_PIN_15 +#define REGEN_LED_PORT GPIOB +#define REGEN_LED_PIN GPIO_PIN_15 -#define BPS_FAULT_LED_PORT GPIOB -#define BPS_FAULT_LED_PIN GPIO_PIN_9 +#define BPS_FAULT_LED_PORT GPIOB +#define BPS_FAULT_LED_PIN GPIO_PIN_9 -#define CAR_HB_LED_PORT GPIOB -#define CAR_HB_LED_PIN GPIO_PIN_14 +#define CAR_HB_LED_PORT GPIOB +#define CAR_HB_LED_PIN GPIO_PIN_14 // Motor Contactor -#define MOTOR_SENSE_TO_LED_PORT GPIOC -#define MOTOR_SENSE_TO_LED_PIN GPIO_PIN_7 +#define MOTOR_SENSE_TO_LED_PORT GPIOC +#define MOTOR_SENSE_TO_LED_PIN GPIO_PIN_7 -#define MOTOR_ENABLE_LED_PORT GPIOC -#define MOTOR_ENABLE_LED_PIN GPIO_PIN_0 +#define MOTOR_ENABLE_LED_PORT GPIOC +#define MOTOR_ENABLE_LED_PIN GPIO_PIN_0 -#define MOTOR_SENSE_LED_PORT GPIOC -#define MOTOR_SENSE_LED_PIN GPIO_PIN_2 +#define MOTOR_SENSE_LED_PORT GPIOC +#define MOTOR_SENSE_LED_PIN GPIO_PIN_2 // Precharge Contactor #define PRECHARGE_COMPLETE_LED_PORT GPIOC -#define PRECHARGE_COMPLETE_LED_PIN GPIO_PIN_8 +#define PRECHARGE_COMPLETE_LED_PIN GPIO_PIN_8 -#define PRECHARGE_TO_LED_PORT GPIOD -#define PRECHARGE_TO_LED_PIN GPIO_PIN_2 +#define PRECHARGE_TO_LED_PORT GPIOD +#define PRECHARGE_TO_LED_PIN GPIO_PIN_2 #define PRECHARGE_SENSE_TO_LED_PORT GPIOC -#define PRECHARGE_SENSE_TO_LED_PIN GPIO_PIN_12 +#define PRECHARGE_SENSE_TO_LED_PIN GPIO_PIN_12 -#define PRECHARGE_ENABLE_LED_PORT GPIOC -#define PRECHARGE_ENABLE_LED_PIN GPIO_PIN_4 +#define PRECHARGE_ENABLE_LED_PORT GPIOC +#define PRECHARGE_ENABLE_LED_PIN GPIO_PIN_4 -#define PRECHARGE_SENSE_LED_PORT GPIOC -#define PRECHARGE_SENSE_LED_PIN GPIO_PIN_5 +#define PRECHARGE_SENSE_LED_PORT GPIOC +#define PRECHARGE_SENSE_LED_PIN GPIO_PIN_5 // Motor Faults -#define HALL_EFFECT_LED_PORT GPIOB -#define HALL_EFFECT_LED_PIN GPIO_PIN_3 +#define HALL_EFFECT_LED_PORT GPIOB +#define HALL_EFFECT_LED_PIN GPIO_PIN_3 -#define DAWG_LED_PORT GPIOB -#define DAWG_LED_PIN GPIO_PIN_5 +#define DAWG_LED_PORT GPIOB +#define DAWG_LED_PIN GPIO_PIN_5 -#define SWOC_LED_PORT GPIOA -#define SWOC_LED_PIN GPIO_PIN_10 +#define SWOC_LED_PORT GPIOA +#define SWOC_LED_PIN GPIO_PIN_10 -#define FAULT_LED_PORT GPIOB -#define FAULT_LED_PIN GPIO_PIN_4 +#define FAULT_LED_PORT GPIOB +#define FAULT_LED_PIN GPIO_PIN_4 // Other pins -#define USART3_PORT GPIOC -#define USART3_TX_PIN GPIO_PIN_10 -#define USART3_RX_PIN GPIO_PIN_11 +#define USART3_PORT GPIOC +#define USART3_TX_PIN GPIO_PIN_10 +#define USART3_RX_PIN GPIO_PIN_11 -#define GPIO_INIT_PORT GPIOC -#define GPIO_ONE_PIN GPIO_PIN_8 -#define GPIO_TWO_PIN GPIO_PIN_12 +#define GPIO_INIT_PORT GPIOC +#define GPIO_ONE_PIN GPIO_PIN_8 +#define GPIO_TWO_PIN GPIO_PIN_12 -#define ADC_PORT GPIOB -#define ADC1_PIN GPIO_PIN_12 -#define ADC2_PIN GPIO_PIN_2 +#define ADC_PORT GPIOB +#define ADC1_PIN GPIO_PIN_12 +#define ADC2_PIN GPIO_PIN_2 /** * @brief object that holds pin num and port of a GPIO pin */ typedef struct { - GPIO_TypeDef* port; // e.g., GPIOA - uint16_t pin; // e.g., GPIO_PIN_3 + GPIO_TypeDef *port; // e.g., GPIOA + uint16_t pin; // e.g., GPIO_PIN_3 } GpioPin_t; typedef enum { NORMAL = 0, // We good - EMERGENCY = 1 // We bad + EMERGENCY = 1 // We bad } fault_state_t; \ No newline at end of file diff --git a/Firmware/tests/CANBus_test.c b/Firmware/tests/canbus_test.c similarity index 52% rename from Firmware/tests/CANBus_test.c rename to Firmware/tests/canbus_test.c index b94c8b0a..1c1fa8e5 100644 --- a/Firmware/tests/CANBus_test.c +++ b/Firmware/tests/canbus_test.c @@ -1,17 +1,19 @@ #include "CANbus.h" -#include "stm32xx_hal.h" -#include "inits.h" #include "StatusLEDs.h" +#include "inits.h" #include "pinDefs.h" +#include "stm32xx_hal.h" StaticTask_t task_buffer; StackType_t task_stack[512]; -static void task(void *pvParameters){ +#define TEST_CAN_ID 0x321 +#define TEST_CAN_DATA {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF} +#define TEST_CAN_DATA_LENGTH 8 - int test_id = 0x321; - FDCAN_TxHeaderTypeDef tx_header = {0}; - tx_header.Identifier = test_id; +static void task(void *pvParameters) { + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = TEST_CAN_ID; tx_header.IdType = FDCAN_STANDARD_ID; tx_header.TxFrameType = FDCAN_DATA_FRAME; tx_header.DataLength = FDCAN_DLC_BYTES_8; @@ -21,36 +23,24 @@ static void task(void *pvParameters){ tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; tx_header.MessageMarker = 0; - // send x1234 to 0x11 - uint8_t tx_data[8] = {0}; - tx_data[0] = 0x12; - tx_data[1] = 0x34; - tx_data[2] = 0x56; - tx_data[3] = 0x78; - tx_data[4] = 0x9A; - tx_data[5] = 0xBC; - tx_data[6] = 0xDE; - tx_data[7] = 0xFF; - - while(1){ - - if (can_fd_send(hfdcan3, &tx_header, tx_data, portMAX_DELAY) == CAN_ERR){ + uint8_t tx_data[TEST_CAN_DATA_LENGTH] = TEST_CAN_DATA; + while (1) { + if (Motor_CANBus_Send(&tx_header, tx_data, portMAX_DELAY) != CAN_OK) { Error_Handler(); } - - // TODO: add status LED + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); vTaskDelay(pdMS_TO_TICKS(1000)); } } -void can_error_handler(){ - while(1){ +void can_error_handler() { + while (1) { LED_set(MOTOR_FAULT, LED_ON); } } -int main(){ +int main() { HAL_Init(); SystemClock_Config(); @@ -59,24 +49,14 @@ int main(){ LEDs_init(); - - if(Motor_CANBus_Init() != CAN_OK){ + if (Motor_CANBus_Init() != CAN_OK) { can_error_handler(); } - xTaskCreateStatic( - task, - "task", - 512, - NULL, - tskIDLE_PRIORITY + 2, - task_stack, - &task_buffer); + xTaskCreateStatic(task, "task", 512, NULL, tskIDLE_PRIORITY + 2, task_stack, &task_buffer); - vTaskStartScheduler(); - while(1){ - + while (1) { } } \ No newline at end of file diff --git a/Firmware/tests/Printf_Init_test.c b/Firmware/tests/printf_test.c similarity index 53% rename from Firmware/tests/Printf_Init_test.c rename to Firmware/tests/printf_test.c index d6f7b2e5..d6536c1d 100644 --- a/Firmware/tests/Printf_Init_test.c +++ b/Firmware/tests/printf_test.c @@ -1,37 +1,36 @@ +#include "FreeRTOS.h" +#include "stm32xx_hal.h" #include "StatusLEDs.h" -#include "pinDefs.h" -#include "inits.h" #include "UART.h" -#include "projdefs.h" -#include "stm32xx_hal.h" -#include "printf.h" #include "UART_Init.h" +#include + StaticTask_t txTaskBuffer; StackType_t txTaskStack[configMINIMAL_STACK_SIZE]; -void TxTask(void *argument){ - - while(1){ +void TxTask(void *argument) { + while (true) { printf("Hello World! %s %d %f\n\r", "Test String", 5, 4.4); vTaskDelay(pdMS_TO_TICKS(1000)); } } int main(void) { - HAL_Init(); SystemClock_Config(); Init_UART_Printf(); - xTaskCreateStatic(TxTask, - "TX", - configMINIMAL_STACK_SIZE, - NULL, - tskIDLE_PRIORITY + 2, - txTaskStack, - &txTaskBuffer); + xTaskCreateStatic( + TxTask, + "TX", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + txTaskStack, + &txTaskBuffer + ); vTaskStartScheduler(); From 91309a642f757fb3f8acbe3bda1691a828524f00 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 28 Mar 2026 12:36:43 -0500 Subject: [PATCH 02/27] some shit --- .vscode/launch.json | 15 - Firmware/Drivers/Inc/ADC_Sense.h | 55 +- Firmware/Drivers/Inc/CANbus.h | 20 +- Firmware/Drivers/Inc/Contactors.h | 43 +- Firmware/Drivers/Inc/MotorSafeBits.h | 1 + Firmware/Drivers/Inc/StatusLEDs.h | 11 +- Firmware/Drivers/Src/CANbus.c | 131 ++++- Firmware/Drivers/Src/FaultBits.c | 59 -- Firmware/Drivers/Src/MotorSafeBits.c | 4 - Firmware/Drivers/Src/StatusLEDs.c | 26 +- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSM.h | 85 +++ Firmware/Tasks/Inc/fsm_table.h | 544 ++++++++++++++++++ Firmware/Tasks/Inc/fsm_table_dnr.h | 544 ++++++++++++++++++ Firmware/Tasks/Inc/rollover_speed_table.h | 111 ++++ Firmware/Tasks/Src/FSM.c | 246 ++++++++ Firmware/Tasks/Src/FaultHandlerTask.c | 4 +- Firmware/Tasks/Src/InitTask.c | 4 +- Firmware/Tasks/Src/MotorControlTask.c | 6 +- Firmware/Tasks/Src/MotorTelemetryTask.c | 60 +- Firmware/Tasks/Src/PrechargeTask.c | 2 +- Firmware/Tasks/Src/ReadMotorCAN.c | 2 +- Firmware/config/Inc/BPSCAN_can_msgs.h | 163 ++++++ Firmware/config/Inc/CarCAN_can_msgs.h | 470 +++++++++++++++ Firmware/config/Inc/ControlsCAN_can_msgs.h | 224 ++++++++ Firmware/config/Inc/MotorCAN_can_msgs.h | 20 + Firmware/core/Src/main.c | 2 +- Firmware/scripts/fsm_generator.py | 181 ++++++ .../scripts/steering_angle_lut_generator.py | 49 ++ Firmware/tests/CanTxTelemetry_test.c | 57 +- Firmware/tests/Contactors_test.c | 2 +- Firmware/tests/FaultHandler_test.c | 4 +- Firmware/tests/MotorController_test.c | 4 +- Firmware/tests/MotorSafe_test.c | 4 +- Firmware/tests/MotorTelemetryTask_test.c | 4 +- Firmware/tests/Precharge_test.c | 2 +- Firmware/tests/blinky_test.c | 10 +- Firmware/tests/canbus_test.c | 6 +- Firmware/tests/motorControlTask_test.c | 4 +- 39 files changed, 2902 insertions(+), 279 deletions(-) delete mode 100644 .vscode/launch.json create mode 100644 Firmware/Tasks/Inc/FSM.h create mode 100644 Firmware/Tasks/Inc/fsm_table.h create mode 100644 Firmware/Tasks/Inc/fsm_table_dnr.h create mode 100644 Firmware/Tasks/Inc/rollover_speed_table.h create mode 100644 Firmware/Tasks/Src/FSM.c create mode 100644 Firmware/config/Inc/BPSCAN_can_msgs.h create mode 100644 Firmware/config/Inc/CarCAN_can_msgs.h create mode 100644 Firmware/config/Inc/ControlsCAN_can_msgs.h create mode 100644 Firmware/scripts/fsm_generator.py create mode 100644 Firmware/scripts/steering_angle_lut_generator.py diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 2ba986f6..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "chrome", - "request": "launch", - "name": "Launch Chrome against localhost", - "url": "http://localhost:8080", - "webRoot": "${workspaceFolder}" - } - ] -} \ No newline at end of file diff --git a/Firmware/Drivers/Inc/ADC_Sense.h b/Firmware/Drivers/Inc/ADC_Sense.h index 3c2010b4..3598cffc 100644 --- a/Firmware/Drivers/Inc/ADC_Sense.h +++ b/Firmware/Drivers/Inc/ADC_Sense.h @@ -1,24 +1,23 @@ #pragma once #include "inits.h" -#include "queue.h" -#include "UART.h" #include "ADC.h" #include "ADC_Battery_LUT.h" #include "ADC_Motor_LUT.h" #include "FaultBits.h" +#include "UART.h" +#include "queue.h" // ADC Channel 11 (Motor Voltage) and 12 (Battery Voltage) are GPIOB 12 and 2 -#define ADC1_CHANNEL ADC_CHANNEL_11 -#define ADC2_CHANNEL ADC_CHANNEL_12 -#define ADC_QUEUE_LENGTH 4 +#define ADC1_CHANNEL ADC_CHANNEL_11 +#define ADC2_CHANNEL ADC_CHANNEL_12 +#define ADC_QUEUE_LENGTH 4 #define ADC_QUEUE_ITEM_SIZE sizeof(uint16_t) -#define ADC_SAMPLING_TIME ADC_SAMPLETIME_2CYCLES_5 +#define ADC_SAMPLING_TIME ADC_SAMPLETIME_2CYCLES_5 /** * @brief ADC Initialization Function * @param adcHandle Pointer to ADC handle struct - * @retval None */ void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle); @@ -27,40 +26,36 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle); * * Contains scaled motor and battery voltages in millivolts. */ -typedef struct -{ - uint32_t Motor_Voltage; - uint32_t Battery_Voltage; +typedef struct { + uint32_t Motor_Voltage; + uint32_t Battery_Voltage; } ADC_Sense_Result; /** * @brief ADC sense function return status */ -typedef enum -{ - ADC_SENSE_OK = 0, // Operation successful - ADC_QUEUE_ERR, // Queue creation failed - ADC_1_INIT_ERR, // ADC1 initialization failed - ADC_2_INIT_ERR, // ADC2 initialization failed - ADC_1_READ_ERR, // ADC1 read failed - ADC_2_READ_ERR, // ADC2 read failed - ADC_SENSE_INIT_ERR, // Initialization not called or failed - READ_ADC_BAD_PARAM_ERR, // Bad result parameter - MOTOR_QUEUE_RECEIVE_ERR, // ADC values not received from motor ADC queue - BATTERY_QUEUE_RECEIVE_ERR // ADC values not received from battery ADC queue +typedef enum { + ADC_SENSE_OK = 0, // Operation successful + ADC_QUEUE_ERR, // Queue creation failed + ADC_1_INIT_ERR, // ADC1 initialization failed + ADC_2_INIT_ERR, // ADC2 initialization failed + ADC_1_READ_ERR, // ADC1 read failed + ADC_2_READ_ERR, // ADC2 read failed + ADC_SENSE_INIT_ERR, // Initialization not called or failed + READ_ADC_BAD_PARAM_ERR, // Bad result parameter + MOTOR_QUEUE_RECEIVE_ERR, // ADC values not received from motor ADC queue + BATTERY_QUEUE_RECEIVE_ERR // ADC values not received from battery ADC queue } ADC_Sense_Status_t; /** - * @brief Initialize ADC1 struct and calls the wrapper adc_init function to initialize ADC1 peripheral - * @param None - * @retval None + * @brief Initialize ADC1 struct and calls the wrapper adc_init function to initialize ADC1 + * peripheral */ ADC_Sense_Status_t ADC_1_Init(void); /** - * @brief Initialize ADC2 struct and calls the wrapper adc_init function to initialize ADC2 peripheral - * @param None - * @retval None + * @brief Initialize ADC2 struct and calls the wrapper adc_init function to initialize ADC2 + * peripheral */ ADC_Sense_Status_t ADC_2_Init(void); @@ -89,13 +84,11 @@ ADC_Sense_Status_t Read_ADC(uint32_t Timeout_MS, ADC_Sense_Result *Result); /** * @brief ADC1 Initialization Function * @param None - * @retval None */ void MX_ADC1_Init(void); /** * @brief ADC2 Initialization Function * @param None - * @retval None */ void MX_ADC2_Init(void); diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index c18e782f..6b251bf0 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -1,19 +1,21 @@ #pragma once -#include "stm32xx_hal.h" #include "CAN_FD.h" +#include "stm32xx_hal.h" -extern FDCAN_HandleTypeDef* motorfdcan; -extern FDCAN_HandleTypeDef* carfdcan; +extern FDCAN_HandleTypeDef *motorfdcan; +extern FDCAN_HandleTypeDef *carfdcan; -can_status_t Motor_CANBus_Init(void); +can_status_t MotorCAN_Init(void); -can_status_t Motor_CANBus_Send(FDCAN_TxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks); +can_status_t MotorCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); -can_status_t Motor_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks); +can_status_t MotorCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks); -can_status_t Car_CANBus_Init(void); +can_status_t CarCAN_Init(void); -can_status_t Car_CANBus_Send(FDCAN_TxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks); +can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); -can_status_t Car_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef* header, uint8_t data[], TickType_t delay_ticks); \ No newline at end of file +can_status_t CarCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks); \ No newline at end of file diff --git a/Firmware/Drivers/Inc/Contactors.h b/Firmware/Drivers/Inc/Contactors.h index fb3a0b83..ce155af9 100644 --- a/Firmware/Drivers/Inc/Contactors.h +++ b/Firmware/Drivers/Inc/Contactors.h @@ -4,15 +4,14 @@ /* Timing Definitions */ /** Time to wait for the physical contactor to settle before reading feedback */ -#define CONTACTOR_SENSE_DELAY pdMS_TO_TICKS(250) +#define CONTACTOR_SENSE_DELAY pdMS_TO_TICKS(250) /** Maximum time allowed for callback execution to prevent task starvation */ #define CALLBACK_BLOCKING_TIME pdMS_TO_TICKS(20) /** * @brief Represents the logical and physical state of a contactor. */ -typedef enum -{ +typedef enum { OPEN = 0, /**< Circuit is disconnected */ CLOSED = 1 /**< Circuit is connected */ } contactor_state_t; @@ -20,46 +19,50 @@ typedef enum /** * @brief Identification for specific contactors within the HV system. */ -typedef enum -{ - MOTOR_CONTACTOR, /**< Battery to Motor Contactor */ - MOTOR_PRE_CONTACTOR, /**< Post-Precharge Bypass Contactor */ - NUM_CONTACTORS /**< Total count helper */ +typedef enum { + MOTOR_CONTACTOR, /* Battery to Motor Contactor */ + MOTOR_PRE_CONTACTOR, /* Post-Precharge Bypass Contactor */ + NUM_CONTACTORS /* Total count helper */ } contactor_num_t; /** * @brief Contactor hardware abstraction object. */ -typedef struct -{ - contactor_state_t state; /**< Current state */ - GpioPin_t sense_pin; /**< Digital input for auxiliary feedback loop */ - GpioPin_t control_pin; /**< Digital output to coil driver/relay */ +typedef struct { + contactor_state_t state; /* Current state */ + GpioPin_t sense_pin; /* Digital input for auxiliary feedback loop */ + GpioPin_t control_pin; /* Digital output to coil driver/relay */ /* RTOS Resources */ - TimerHandle_t senseTimer; /**< Handle for non-blocking state verification */ - StaticTimer_t senseTimerBuffer; /**< Memory buffer for static timer allocation */ + TimerHandle_t senseTimer; /* Handle for non-blocking state verification */ + StaticTimer_t senseTimerBuffer; /* Memory buffer for static timer allocation */ } contactor_t; -/** @brief Hardware/RTOS init for all contactors, timers, and mutexes. */ +/** + * @brief Hardware/RTOS init for all contactors, timers, and mutexes. + */ void contactor_init(void); -/** * @brief Reads the physical sense pin for a specific contactor. +/** + * @brief Reads the physical sense pin for a specific contactor. * @return 1 if CLOSED, 0 if OPEN. */ contactor_state_t contactor_get_sense(contactor_num_t contactor_num); -/** * @brief Reads the current logical state for a specific contactor. +/** + * @brief Reads the current logical state for a specific contactor. * @return 1 if CLOSED, 0 if OPEN. */ contactor_state_t contactor_get_commanded_state(contactor_num_t contactor_num); -/** * @brief Commands a contactor state change with safety verification via callback function. +/** + * @brief Commands a contactor state change with safety verification via callback function. * @param wait_ms Wait time for sense delay before returning. * @param emergency Immediate execution; bypasses safety callbacks. * @return SUCCESS or hardware ERROR code. */ -ErrorStatus contactor_set(contactor_num_t contactor_num, contactor_state_t state, uint32_t wait_ms, fault_state_t emergency); +ErrorStatus contactor_set(contactor_num_t contactor_num, contactor_state_t state, uint32_t wait_ms, + fault_state_t emergency); /** @brief When fault is detected, opens all contactors. */ void contactor_emergency_open_all(); \ No newline at end of file diff --git a/Firmware/Drivers/Inc/MotorSafeBits.h b/Firmware/Drivers/Inc/MotorSafeBits.h index 1dd1480c..19c32557 100644 --- a/Firmware/Drivers/Inc/MotorSafeBits.h +++ b/Firmware/Drivers/Inc/MotorSafeBits.h @@ -5,6 +5,7 @@ #include "stm32xx_hal.h" #include #include +#include // The max number of fault bits is dependent on the configUSE_16_BIT_TICKS defined in FreeRTOS.h #if (configUSE_16_BIT_TICKS == 0) diff --git a/Firmware/Drivers/Inc/StatusLEDs.h b/Firmware/Drivers/Inc/StatusLEDs.h index 1ee10a87..c438e782 100644 --- a/Firmware/Drivers/Inc/StatusLEDs.h +++ b/Firmware/Drivers/Inc/StatusLEDs.h @@ -3,8 +3,6 @@ #include "inits.h" #include -#define num_LEDs 15 - /** @brief LED States */ typedef enum { LED_OFF = GPIO_PIN_SET, // Negative logic @@ -30,17 +28,18 @@ typedef enum { WATCHDOG, // moco watchdog fault SWOC, // moco swoc fault MOTOR_FAULT, // moco generic fault - HB // hb led + HB, // hb led + NUM_LEDS, } Status_Mapping_t; /** @brief Sets a specific LED to on (true) or off (false). */ void LED_set(Status_Mapping_t LED, LED_state_t state); /** @brief Turns off all LEDs. */ -void LEDs_clear(void); +void LED_clear(void); /** @brief Configures GPIO pins for all diagnostic LEDs. */ -void LEDs_init(void); +void LED_init(void); /** @brief Toggle the LED */ -void Toggle_LED(Status_Mapping_t LED); +void LED_toggle(Status_Mapping_t LED); diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 0f3d3676..ece0e0ae 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -1,11 +1,14 @@ #include "CANbus.h" +#include "BPSCAN_can_msgs.h" +#include "CarCAN_can_msgs.h" +#include "MotorCAN_can_msgs.h" #define FDCAN_NVIC_PRIO configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 5 FDCAN_HandleTypeDef *motorfdcan; FDCAN_HandleTypeDef *carfdcan; -can_status_t Motor_CANBus_Init(void) { +can_status_t MotorCAN_Init(void) { motorfdcan = hfdcan1; motorfdcan->Instance = FDCAN1; @@ -49,19 +52,86 @@ can_status_t Motor_CANBus_Init(void) { return CAN_OK; } -can_status_t Motor_CANBus_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], - TickType_t delay_ticks) { - +can_status_t MotorCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { return can_fd_send(motorfdcan, header, data, delay_ticks); } -can_status_t Motor_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef *header, - uint8_t data[], TickType_t delay_ticks) { - +can_status_t MotorCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks) { return can_fd_recv(motorfdcan, id, header, data, delay_ticks); } -can_status_t Car_CANBus_Init(void) { +can_status_t MotorCAN_Recv_Velocity(mc_velocitymeasurement_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t motor_vel_rx_data[CAN_DLC_MC_VELOCITYMEASUREMENT] = {0}; + + can_status_t result = + can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, motor_vel_rx_data, delay); + + if (result == CAN_OK) { + out->MC_MotorVelocity = *((float *)&motor_vel_rx_data[0]); + out->MC_VehicleVelocity = *((float *)&motor_vel_rx_data[4]); + } + return result; +} + +can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + header. + uint8_t moco_status_rx_data[CAN_DLC_MC_VELOCITYMEASUREMENT] = {0}; + + can_status_t result = + can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, motor_vel_rx_data, delay); + + if (result == CAN_OK) { + out->MC_LIMIT_OutputVoltagePWM = (moco_status_rx_data[0] >> 0) & 0x1; + out->MC_LIMIT_MotorCurrent = (moco_status_rx_data[0] >> 1) & 0x1; + out->MC_LIMIT_Velocity = (moco_status_rx_data[0] >> 2) & 0x1; + out->MC_LIMIT_BusCurrent = (moco_status_rx_data[0] >> 3) & 0x1; + out->MC_LIMIT_BusVoltageUpper = (moco_status_rx_data[0] >> 4) & 0x1; + out->MC_LIMIT_BusVoltageLower = (moco_status_rx_data[0] >> 5) & 0x1; + out->MC_LIMIT_MotorTemp = (moco_status_rx_data[0] >> 6) & 0x1; + out->MC_LIMIT_Reserved = ((uint16_t)(moco_status_rx_data[0] >> 7) & 0x1) | + ((uint16_t)moco_status_rx_data[1] << 1); + + out->MC_FAULT_HardwareOverCurrent = (moco_status_rx_data[2] >> 0) & 0x1; + out->MC_FAULT_SoftwareOverCurrent = (moco_status_rx_data[2] >> 1) & 0x1; + out->MC_FAULT_DcBusOverVoltage = (moco_status_rx_data[2] >> 2) & 0x1; + out->MC_FAULT_BadMotorPositionHallSeq = (moco_status_rx_data[2] >> 3) & 0x1; + out->MC_FAULT_WatchdogCausedLastReset = (moco_status_rx_data[2] >> 4) & 0x1; + out->MC_FAULT_ConfigRead = (moco_status_rx_data[2] >> 5) & 0x1; + out->MC_FAULT_15vRailUnderVoltage = (moco_status_rx_data[2] >> 6) & 0x1; + out->MC_FAULT_DesaturationFault = (moco_status_rx_data[2] >> 7) & 0x1; + out->MC_FAULT_MotorOverSpeed = (moco_status_rx_data[3] >> 0) & 0x1; + out->MC_FAULT_Reserved = (moco_status_rx_data[3] >> 1) & 0x7F; + + out->MC_ActiveMotor = + (uint16_t)moco_status_rx_data[4] | ((uint16_t)moco_status_rx_data[5] << 8); + out->MC_TxErrorCount = moco_status_rx_data[6]; + out->MC_RxErrorCount = moco_status_rx_data[7]; + } + return result; +} + +can_status_t MotorCAN_Send_Drive_Cmd(mc_drivecommand_t *out, TickType_t delay) { + +} +void send_motor_drive_cmd(float velocity, float current) { + uint8_t data[8] = {0}; + + memcpy(&data[0], &velocity, sizeof(float)); + memcpy(&data[4], ¤t, sizeof(float)); + + vcucan_send(CAN_ID_MC_DRIVECOMMAND, data, 8); +} + +///////// Carcan + +can_status_t CarCAN_Init(void) { carfdcan = hfdcan3; carfdcan->Instance = FDCAN3; @@ -104,18 +174,45 @@ can_status_t Car_CANBus_Init(void) { return CAN_OK; } -can_status_t Car_CANBus_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], - TickType_t delay_ticks) { - +can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { return can_fd_send(carfdcan, header, data, delay_ticks); } -can_status_t Car_CANBus_Recieve(uint16_t id, FDCAN_RxHeaderTypeDef *header, - uint8_t data[], TickType_t delay_ticks) { - +can_status_t CarCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks) { return can_fd_recv(carfdcan, id, header, data, delay_ticks); } +can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t bps_status_rx_data[CAN_DLC_BPS_STATUS] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_BPS_STATUS, &header, bps_status_rx_data, delay); + + if (result == CAN_OK) { + out->BPS_Fault = bps_status_rx_data[0]; + out->BPS_Regen_OK = (bps_status_rx_data[1] >> 0) & 1; + out->BPS_Charge_OK = (bps_status_rx_data[1] >> 1) & 1; + out->HV_Plus_Contactor_State = (bps_status_rx_data[1] >> 2) & 1; + out->HV_Minus_Contactor_State = (bps_status_rx_data[1] >> 3) & 1; + out->Array_Contactor_State = (bps_status_rx_data[1] >> 4) & 1; + out->Array_Precharge_Contactor_State = (bps_status_rx_data[1] >> 5) & 1; + out->Main_Battery_Voltage = (uint32_t)(bps_status_rx_data[4] | + ((uint32_t)bps_status_rx_data[5] << 8) | + ((uint32_t)bps_status_rx_data[6] << 16) | + ((uint32_t)bps_status_rx_data[7] << 24)); + out->Main_Battery_Avg_Temperature = (int16_t)((uint16_t)bps_status_rx_data[2] | ((uint16_t)bps_status_rx_data[3] << 8)); + } + return result; +} + +can_status_t CarCAN_Recv_LWS(lws_standard_t) + +//////// HAL bs + static uint32_t HAL_RCC_FDCAN_CLK_ENABLED = 0; void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *fdcanHandle) { @@ -153,8 +250,7 @@ void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *fdcanHandle) { HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, FDCAN_NVIC_PRIO, 0); HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn); - } - else if (fdcanHandle->Instance == FDCAN3) { + } else if (fdcanHandle->Instance == FDCAN3) { /** Initializes the peripherals clocks */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; @@ -206,8 +302,7 @@ void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *fdcanHandle) { /* FDCAN1 interrupt Deinit */ HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn); - } - else if (fdcanHandle->Instance == FDCAN3) { + } else if (fdcanHandle->Instance == FDCAN3) { /* Peripheral clock disable */ HAL_RCC_FDCAN_CLK_ENABLED--; if (HAL_RCC_FDCAN_CLK_ENABLED == 0) { diff --git a/Firmware/Drivers/Src/FaultBits.c b/Firmware/Drivers/Src/FaultBits.c index f0faf095..f79f4682 100644 --- a/Firmware/Drivers/Src/FaultBits.c +++ b/Firmware/Drivers/Src/FaultBits.c @@ -1,62 +1,3 @@ -// #include "FaultBits.h" - -// // Event group handle to store fault state bits -// EventGroupHandle_t faultStateBits; - -// // Static buffer to store the event handle -// StaticEventGroup_t faultStateBitsBuffer; - -// uint8_t faultBits_init(void) { -// faultStateBits = xEventGroupCreateStatic(&faultStateBitsBuffer); -// if (faultStateBits == NULL) { -// return 0; -// } -// return 1; -// } - -// void set_faultBit(fault_bit_t bit) { -// // not a valid fault -// if (bit >= NUM_FAULTS) { -// return; -// } - -// // chat we're cooked -// xEventGroupSetBits(faultStateBits, FAULT_BIT(bit)); -// // should never return from here -// taskYIELD(); -// } - -// void set_faultBitFromISR(fault_bit_t bit) { -// BaseType_t xHigherPriorityTaskWoken = pdFALSE; - -// if (bit >= NUM_FAULTS) { -// return; -// } - -// xEventGroupSetBitsFromISR(faultStateBits, FAULT_BIT(bit), &xHigherPriorityTaskWoken); - -// portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -// } - -// EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait) { -// // NUM_FAULTS indiciates you want to wait for all bits -// if (bit > NUM_FAULTS) { -// return 0; -// } - -// // if NUM -// // EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? ALL_FAULT_BITS : (FAULT_BIT(bit)); -// EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? FAULT_BITMASK : (FAULT_BIT(bit)); - -// EventBits_t pending = xEventGroupWaitBits(faultStateBits, -// uxBitsToWaitFor, // wait for any defined fault -// pdFALSE, // fault bits are not reset -// pdFALSE, // wait for ANY bit to be set -// xTicksToWait); -// return pending; -// } - - #include "FaultBits.h" #include diff --git a/Firmware/Drivers/Src/MotorSafeBits.c b/Firmware/Drivers/Src/MotorSafeBits.c index 8ce543ec..6dd57809 100644 --- a/Firmware/Drivers/Src/MotorSafeBits.c +++ b/Firmware/Drivers/Src/MotorSafeBits.c @@ -1,9 +1,6 @@ #include "MotorSafeBits.h" -// Event group handle to store fault state bits EventGroupHandle_t motorSafeBits; - -// Static buffer to store the event handle StaticEventGroup_t motorSafeBitsBuffer; BaseType_t MotorSafeBits_Init() { @@ -25,7 +22,6 @@ void set_MotorSafeBit(motor_status_bit_t bit) { } void clear_MotorSafeBit(motor_status_bit_t bit) { - // not a valid fault if (bit >= NUM_MOTOR_STATUS_BITS || motorSafeBits == NULL) { return; diff --git a/Firmware/Drivers/Src/StatusLEDs.c b/Firmware/Drivers/Src/StatusLEDs.c index 9d2239e8..42c7ebb5 100644 --- a/Firmware/Drivers/Src/StatusLEDs.c +++ b/Firmware/Drivers/Src/StatusLEDs.c @@ -3,9 +3,7 @@ #include "StatusLEDs.h" -static uint16_t LEDbitmap; - -static const GpioPin_t DebugLEDs[num_LEDs] = { +static const GpioPin_t DebugLEDs[NUM_LEDS] = { {PRECHARGE_COMPLETE_LED_PORT, PRECHARGE_COMPLETE_LED_PIN}, {PRECHARGE_TO_LED_PORT, PRECHARGE_TO_LED_PIN}, {PRECHARGE_SENSE_TO_LED_PORT, PRECHARGE_SENSE_TO_LED_PIN}, @@ -23,16 +21,15 @@ static const GpioPin_t DebugLEDs[num_LEDs] = { {HB_LED_PORT, HB_LED_PIN} }; -void Toggle_LED(Status_Mapping_t LED) { - if (LED < 0 || LED >= num_LEDs) { +void LED_toggle(Status_Mapping_t LED) { + if (LED < 0 || LED >= NUM_LEDS) { return; } HAL_GPIO_TogglePin(DebugLEDs[LED].port, DebugLEDs[LED].pin); } void LED_set(Status_Mapping_t LED, LED_state_t state) { - // make sure LED is within bound - if (LED > num_LEDs || LED < 0) { + if (LED < 0 || LED >= NUM_LEDS) { return; } if (LED == HB) { @@ -43,22 +40,23 @@ void LED_set(Status_Mapping_t LED, LED_state_t state) { } } -void LEDs_clear() { - LEDbitmap = 0; - for (int i = 0; i < num_LEDs; i++) { +void LED_clear() { + for (uint8_t i = 0; i < NUM_LEDS; i++) { LED_set(i, LED_OFF); } } -void LEDs_init() { +void LED_init() { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); - for (size_t i = 0; i < num_LEDs; ++i) { - + for (uint8_t i = 0; i < NUM_LEDS; ++i) { GPIO_InitTypeDef led_config = { - .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_NOPULL, .Pin = DebugLEDs[i].pin}; + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL, + .Pin = DebugLEDs[i].pin + }; HAL_GPIO_Init(DebugLEDs[i].port, &led_config); LED_set(i, LED_OFF); diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 9524b108..f96a561e 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 9524b10828818c1f7fd28b93137135e449c921fb +Subproject commit f96a561e3c16666dcf02c1ea90400dd13bd49602 diff --git a/Firmware/Tasks/Inc/FSM.h b/Firmware/Tasks/Inc/FSM.h new file mode 100644 index 00000000..26f6631b --- /dev/null +++ b/Firmware/Tasks/Inc/FSM.h @@ -0,0 +1,85 @@ +/** + * @file FSM.h + * @brief Prohelion wavesculptor 22 motor controller FSM types and public API + * @copyright Copyright (c) 2026 UT Longhorn Racing Solar + * + * WARNING: BITFIELD_INPUT_LIST order must match BITS dict in + * scripts/fsm_generator.py. If you add/reorder entries, + * update that script and regenerate fsm_table.h. Same + * with FSMState_e + */ + +#pragma once + +#include "inits.h" + +// make sure if you change this to also change it in scripts/fsm_generator.py +#define BITFIELD_INPUT_LIST(X) \ + X(NEUTRAL) \ + X(FORWARD) \ + X(REVERSE) \ + X(CRUISE_CONTROL_BUTTON) \ + X(REGEN_BUTTON) \ + X(READY_TO_REGEN) \ + X(REGEN_ENABLED) \ + X(BRAKE) \ + X(PRECHARGE_COMPLETE) + +/** + * @brief + */ +typedef enum { +#define X(name) BIT_IDX_##name, + BITFIELD_INPUT_LIST(X) +#undef X + BITFIELD_INPUT_COUNT +} InputBitsIdx_e; + +#define FSM_INPUT_BIT(x) (1U << x) + +typedef enum { +#define X(name) name##_BIT = (1U << BIT_IDX_##name), + BITFIELD_INPUT_LIST(X) +#undef X +} InputBits_t; + +#define NEXT_STATES_LENGTH (1U << BITFIELD_INPUT_COUNT) +#define ALL_INPUT_BITS ((1U << BITFIELD_INPUT_COUNT) - 1U) + +// must match in the generator script +typedef enum { + STATE_INIT = 0, + FORWARD_DRIVE, + NEUTRAL_DRIVE, + REVERSE_DRIVE, + REGEN, + CRUISE_CONTROL, + DISABLED, + CAR_NOT_READY, + NUM_STATES +} FSMState_e; + +typedef struct { + FSMState_e stateName; + void (*stateHandler)(void); + uint8_t NextStates[NEXT_STATES_LENGTH]; +} MocoState_t; + +extern MocoState_t FSM[NUM_STATES]; +extern MocoState_t currentState; + +void fsm_init(void); +void fsm_step(void); +void fsm_disable(void); +void fsm_recover(void); +void fsm_set_precharge_complete(bool val); + +uint16_t fsm_get_car_status(void); +bool fsm_is_over_rollover_speed(void); + +void Task_UpdateControlStatus(void *args); +void Task_FSM(void *args); +void Task_BroadcastVCUStatus(void *args); + +float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, + uint8_t out_max); diff --git a/Firmware/Tasks/Inc/fsm_table.h b/Firmware/Tasks/Inc/fsm_table.h new file mode 100644 index 00000000..8871fed9 --- /dev/null +++ b/Firmware/Tasks/Inc/fsm_table.h @@ -0,0 +1,544 @@ +/** + * @file fsm_table.h + * @brief Auto-generated FSM table (FULL); do not edit + * Regenerate: python3 generate_fsm.py --full + */ + +#pragma once +#include "FSM.h" + +extern MocoState_t FSM[NUM_STATES]; + +#ifdef DEFINE_FSM_TABLE +MocoState_t FSM[NUM_STATES] = { + + [STATE_INIT] = { STATE_INIT, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY + }}, + [FORWARD_DRIVE] = { FORWARD_DRIVE, NULL, { + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CRUISE_CONTROL, NEUTRAL_DRIVE, CRUISE_CONTROL, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CRUISE_CONTROL, NEUTRAL_DRIVE, CRUISE_CONTROL, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CRUISE_CONTROL, NEUTRAL_DRIVE, CRUISE_CONTROL, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + REGEN, NEUTRAL_DRIVE, REGEN, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + REGEN, NEUTRAL_DRIVE, REGEN, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CRUISE_CONTROL, NEUTRAL_DRIVE, CRUISE_CONTROL, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CRUISE_CONTROL, NEUTRAL_DRIVE, CRUISE_CONTROL, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CRUISE_CONTROL, NEUTRAL_DRIVE, CRUISE_CONTROL, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + REGEN, NEUTRAL_DRIVE, REGEN, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + REGEN, NEUTRAL_DRIVE, REGEN, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [NEUTRAL_DRIVE] = { NEUTRAL_DRIVE, NULL, { + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [REVERSE_DRIVE] = { REVERSE_DRIVE, NULL, { + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [REGEN] = { REGEN, NULL, { + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, + FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN, FORWARD_DRIVE, FORWARD_DRIVE, REGEN, REGEN + }}, + [CRUISE_CONTROL] = { CRUISE_CONTROL, NULL, { + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, + FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, + CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL, CRUISE_CONTROL + }}, + [DISABLED] = { DISABLED, NULL, { + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED + }}, + [CAR_NOT_READY] = { CAR_NOT_READY, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, +}; +#endif diff --git a/Firmware/Tasks/Inc/fsm_table_dnr.h b/Firmware/Tasks/Inc/fsm_table_dnr.h new file mode 100644 index 00000000..707801dc --- /dev/null +++ b/Firmware/Tasks/Inc/fsm_table_dnr.h @@ -0,0 +1,544 @@ +/** + * @file fsm_table_dnr.h + * @brief Auto-generated FSM table (DNR); do not edit + * Regenerate: python3 generate_fsm.py --dnr + */ + +#pragma once +#include "FSM.h" + +extern MocoState_t FSM[NUM_STATES]; + +#ifdef DEFINE_FSM_TABLE +MocoState_t FSM[NUM_STATES] = { + + [STATE_INIT] = { STATE_INIT, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY + }}, + [FORWARD_DRIVE] = { FORWARD_DRIVE, NULL, { + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [NEUTRAL_DRIVE] = { NEUTRAL_DRIVE, NULL, { + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [REVERSE_DRIVE] = { REVERSE_DRIVE, NULL, { + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [REGEN] = { REGEN, NULL, { + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [CRUISE_CONTROL] = { CRUISE_CONTROL, NULL, { + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, + [DISABLED] = { DISABLED, NULL, { + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, + DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED + }}, + [CAR_NOT_READY] = { CAR_NOT_READY, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + }}, +}; +#endif diff --git a/Firmware/Tasks/Inc/rollover_speed_table.h b/Firmware/Tasks/Inc/rollover_speed_table.h new file mode 100644 index 00000000..2a7264de --- /dev/null +++ b/Firmware/Tasks/Inc/rollover_speed_table.h @@ -0,0 +1,111 @@ +/** + * @file rollover_speed_table.h + * @brief Auto-generated rollover speed limit lookup table — do not edit + * Regenerate: python3 scripts/generate_rollover_table.py + * + * Index : abs(LWS_Angle / 10) [integer degrees, 0-720] + * Value : max allowable speed in cm/s | 0xFFFF = no limit (straight) + */ + +#pragma once + +#include + +#define ROLLOVER_TABLE_NO_LIMIT 0xFFFFU +#define ROLLOVER_TABLE_MAX_DEG 720U + +// Index: abs(LWS_Angle / 10) in integer degrees (0-720) +// Value: max allowable speed in cm/s | 0xFFFF = no limit +static const uint16_t rollover_speed_table[721] = { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0-7 deg + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 8-15 deg + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 16-23 deg + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x09D8, 0x09AF, // 24-31 deg + 0x0988, 0x0963, 0x093F, 0x091D, 0x08FD, 0x08DD, 0x08BF, 0x08A2, // 32-39 deg + 0x0886, 0x086B, 0x0852, 0x0839, 0x0821, 0x0809, 0x07F3, 0x07DD, // 40-47 deg + 0x07C8, 0x07B3, 0x079F, 0x078C, 0x0779, 0x0767, 0x0756, 0x0744, // 48-55 deg + 0x0734, 0x0723, 0x0714, 0x0704, 0x06F5, 0x06E6, 0x06D8, 0x06CA, // 56-63 deg + 0x06BC, 0x06AF, 0x06A2, 0x0695, 0x0688, 0x067C, 0x0670, 0x0665, // 64-71 deg + 0x0659, 0x064E, 0x0643, 0x0638, 0x062E, 0x0623, 0x0619, 0x060F, // 72-79 deg + 0x0605, 0x05FC, 0x05F2, 0x05E9, 0x05E0, 0x05D7, 0x05CE, 0x05C6, // 80-87 deg + 0x05BD, 0x05B5, 0x05AD, 0x05A5, 0x059D, 0x0595, 0x058D, 0x0586, // 88-95 deg + 0x057E, 0x0577, 0x0570, 0x0568, 0x0561, 0x055B, 0x0554, 0x054D, // 96-103 deg + 0x0546, 0x0540, 0x0539, 0x0533, 0x052D, 0x0527, 0x0521, 0x051B, // 104-111 deg + 0x0515, 0x050F, 0x0509, 0x0503, 0x04FE, 0x04F8, 0x04F3, 0x04ED, // 112-119 deg + 0x04E8, 0x04E3, 0x04DE, 0x04D8, 0x04D3, 0x04CE, 0x04C9, 0x04C4, // 120-127 deg + 0x04C0, 0x04BB, 0x04B6, 0x04B1, 0x04AD, 0x04A8, 0x04A4, 0x049F, // 128-135 deg + 0x049B, 0x0496, 0x0492, 0x048E, 0x048A, 0x0485, 0x0481, 0x047D, // 136-143 deg + 0x0479, 0x0475, 0x0471, 0x046D, 0x0469, 0x0465, 0x0461, 0x045E, // 144-151 deg + 0x045A, 0x0456, 0x0452, 0x044F, 0x044B, 0x0448, 0x0444, 0x0440, // 152-159 deg + 0x043D, 0x043A, 0x0436, 0x0433, 0x042F, 0x042C, 0x0429, 0x0425, // 160-167 deg + 0x0422, 0x041F, 0x041C, 0x0419, 0x0415, 0x0412, 0x040F, 0x040C, // 168-175 deg + 0x0409, 0x0406, 0x0403, 0x0400, 0x03FD, 0x03FA, 0x03F7, 0x03F5, // 176-183 deg + 0x03F2, 0x03EF, 0x03EC, 0x03E9, 0x03E7, 0x03E4, 0x03E1, 0x03DE, // 184-191 deg + 0x03DC, 0x03D9, 0x03D7, 0x03D4, 0x03D1, 0x03CF, 0x03CC, 0x03CA, // 192-199 deg + 0x03C7, 0x03C5, 0x03C2, 0x03C0, 0x03BD, 0x03BB, 0x03B8, 0x03B6, // 200-207 deg + 0x03B4, 0x03B1, 0x03AF, 0x03AD, 0x03AA, 0x03A8, 0x03A6, 0x03A3, // 208-215 deg + 0x03A1, 0x039F, 0x039D, 0x039B, 0x0398, 0x0396, 0x0394, 0x0392, // 216-223 deg + 0x0390, 0x038E, 0x038B, 0x0389, 0x0387, 0x0385, 0x0383, 0x0381, // 224-231 deg + 0x037F, 0x037D, 0x037B, 0x0379, 0x0377, 0x0375, 0x0373, 0x0371, // 232-239 deg + 0x036F, 0x036D, 0x036B, 0x0369, 0x0368, 0x0366, 0x0364, 0x0362, // 240-247 deg + 0x0360, 0x035E, 0x035C, 0x035B, 0x0359, 0x0357, 0x0355, 0x0353, // 248-255 deg + 0x0352, 0x0350, 0x034E, 0x034C, 0x034B, 0x0349, 0x0347, 0x0346, // 256-263 deg + 0x0344, 0x0342, 0x0341, 0x033F, 0x033D, 0x033C, 0x033A, 0x0338, // 264-271 deg + 0x0337, 0x0335, 0x0333, 0x0332, 0x0330, 0x032F, 0x032D, 0x032C, // 272-279 deg + 0x032A, 0x0328, 0x0327, 0x0325, 0x0324, 0x0322, 0x0321, 0x031F, // 280-287 deg + 0x031E, 0x031C, 0x031B, 0x0319, 0x0318, 0x0316, 0x0315, 0x0313, // 288-295 deg + 0x0312, 0x0311, 0x030F, 0x030E, 0x030C, 0x030B, 0x030A, 0x0308, // 296-303 deg + 0x0307, 0x0305, 0x0304, 0x0303, 0x0301, 0x0300, 0x02FF, 0x02FD, // 304-311 deg + 0x02FC, 0x02FA, 0x02F9, 0x02F8, 0x02F7, 0x02F5, 0x02F4, 0x02F3, // 312-319 deg + 0x02F1, 0x02F0, 0x02EF, 0x02ED, 0x02EC, 0x02EB, 0x02EA, 0x02E8, // 320-327 deg + 0x02E7, 0x02E6, 0x02E5, 0x02E3, 0x02E2, 0x02E1, 0x02E0, 0x02DE, // 328-335 deg + 0x02DD, 0x02DC, 0x02DB, 0x02DA, 0x02D8, 0x02D7, 0x02D6, 0x02D5, // 336-343 deg + 0x02D4, 0x02D3, 0x02D1, 0x02D0, 0x02CF, 0x02CE, 0x02CD, 0x02CC, // 344-351 deg + 0x02CA, 0x02C9, 0x02C8, 0x02C7, 0x02C6, 0x02C5, 0x02C4, 0x02C3, // 352-359 deg + 0x02C2, 0x02C0, 0x02BF, 0x02BE, 0x02BD, 0x02BC, 0x02BB, 0x02BA, // 360-367 deg + 0x02B9, 0x02B8, 0x02B7, 0x02B6, 0x02B5, 0x02B3, 0x02B2, 0x02B1, // 368-375 deg + 0x02B0, 0x02AF, 0x02AE, 0x02AD, 0x02AC, 0x02AB, 0x02AA, 0x02A9, // 376-383 deg + 0x02A8, 0x02A7, 0x02A6, 0x02A5, 0x02A4, 0x02A3, 0x02A2, 0x02A1, // 384-391 deg + 0x02A0, 0x029F, 0x029E, 0x029D, 0x029C, 0x029B, 0x029A, 0x0299, // 392-399 deg + 0x0298, 0x0297, 0x0296, 0x0295, 0x0294, 0x0293, 0x0293, 0x0292, // 400-407 deg + 0x0291, 0x0290, 0x028F, 0x028E, 0x028D, 0x028C, 0x028B, 0x028A, // 408-415 deg + 0x0289, 0x0288, 0x0287, 0x0286, 0x0286, 0x0285, 0x0284, 0x0283, // 416-423 deg + 0x0282, 0x0281, 0x0280, 0x027F, 0x027E, 0x027D, 0x027D, 0x027C, // 424-431 deg + 0x027B, 0x027A, 0x0279, 0x0278, 0x0277, 0x0277, 0x0276, 0x0275, // 432-439 deg + 0x0274, 0x0273, 0x0272, 0x0271, 0x0271, 0x0270, 0x026F, 0x026E, // 440-447 deg + 0x026D, 0x026C, 0x026B, 0x026B, 0x026A, 0x0269, 0x0268, 0x0267, // 448-455 deg + 0x0267, 0x0266, 0x0265, 0x0264, 0x0263, 0x0262, 0x0262, 0x0261, // 456-463 deg + 0x0260, 0x025F, 0x025E, 0x025E, 0x025D, 0x025C, 0x025B, 0x025A, // 464-471 deg + 0x025A, 0x0259, 0x0258, 0x0257, 0x0257, 0x0256, 0x0255, 0x0254, // 472-479 deg + 0x0253, 0x0253, 0x0252, 0x0251, 0x0250, 0x0250, 0x024F, 0x024E, // 480-487 deg + 0x024D, 0x024D, 0x024C, 0x024B, 0x024A, 0x024A, 0x0249, 0x0248, // 488-495 deg + 0x0247, 0x0247, 0x0246, 0x0245, 0x0244, 0x0244, 0x0243, 0x0242, // 496-503 deg + 0x0241, 0x0241, 0x0240, 0x023F, 0x023F, 0x023E, 0x023D, 0x023C, // 504-511 deg + 0x023C, 0x023B, 0x023A, 0x023A, 0x0239, 0x0238, 0x0237, 0x0237, // 512-519 deg + 0x0236, 0x0235, 0x0235, 0x0234, 0x0233, 0x0232, 0x0232, 0x0231, // 520-527 deg + 0x0230, 0x0230, 0x022F, 0x022E, 0x022E, 0x022D, 0x022C, 0x022C, // 528-535 deg + 0x022B, 0x022A, 0x022A, 0x0229, 0x0228, 0x0227, 0x0227, 0x0226, // 536-543 deg + 0x0225, 0x0225, 0x0224, 0x0223, 0x0223, 0x0222, 0x0221, 0x0221, // 544-551 deg + 0x0220, 0x021F, 0x021F, 0x021E, 0x021E, 0x021D, 0x021C, 0x021C, // 552-559 deg + 0x021B, 0x021A, 0x021A, 0x0219, 0x0218, 0x0218, 0x0217, 0x0216, // 560-567 deg + 0x0216, 0x0215, 0x0214, 0x0214, 0x0213, 0x0213, 0x0212, 0x0211, // 568-575 deg + 0x0211, 0x0210, 0x020F, 0x020F, 0x020E, 0x020D, 0x020D, 0x020C, // 576-583 deg + 0x020C, 0x020B, 0x020A, 0x020A, 0x0209, 0x0209, 0x0208, 0x0207, // 584-591 deg + 0x0207, 0x0206, 0x0205, 0x0205, 0x0204, 0x0204, 0x0203, 0x0202, // 592-599 deg + 0x0202, 0x0201, 0x0201, 0x0200, 0x01FF, 0x01FF, 0x01FE, 0x01FE, // 600-607 deg + 0x01FD, 0x01FC, 0x01FC, 0x01FB, 0x01FB, 0x01FA, 0x01F9, 0x01F9, // 608-615 deg + 0x01F8, 0x01F8, 0x01F7, 0x01F6, 0x01F6, 0x01F5, 0x01F5, 0x01F4, // 616-623 deg + 0x01F3, 0x01F3, 0x01F2, 0x01F2, 0x01F1, 0x01F1, 0x01F0, 0x01EF, // 624-631 deg + 0x01EF, 0x01EE, 0x01EE, 0x01ED, 0x01EC, 0x01EC, 0x01EB, 0x01EB, // 632-639 deg + 0x01EA, 0x01EA, 0x01E9, 0x01E8, 0x01E8, 0x01E7, 0x01E7, 0x01E6, // 640-647 deg + 0x01E6, 0x01E5, 0x01E4, 0x01E4, 0x01E3, 0x01E3, 0x01E2, 0x01E2, // 648-655 deg + 0x01E1, 0x01E1, 0x01E0, 0x01DF, 0x01DF, 0x01DE, 0x01DE, 0x01DD, // 656-663 deg + 0x01DD, 0x01DC, 0x01DC, 0x01DB, 0x01DA, 0x01DA, 0x01D9, 0x01D9, // 664-671 deg + 0x01D8, 0x01D8, 0x01D7, 0x01D7, 0x01D6, 0x01D5, 0x01D5, 0x01D4, // 672-679 deg + 0x01D4, 0x01D3, 0x01D3, 0x01D2, 0x01D2, 0x01D1, 0x01D1, 0x01D0, // 680-687 deg + 0x01D0, 0x01CF, 0x01CE, 0x01CE, 0x01CD, 0x01CD, 0x01CC, 0x01CC, // 688-695 deg + 0x01CB, 0x01CB, 0x01CA, 0x01CA, 0x01C9, 0x01C9, 0x01C8, 0x01C7, // 696-703 deg + 0x01C7, 0x01C6, 0x01C6, 0x01C5, 0x01C5, 0x01C4, 0x01C4, 0x01C3, // 704-711 deg + 0x01C3, 0x01C2, 0x01C2, 0x01C1, 0x01C1, 0x01C0, 0x01C0, 0x01BF, // 712-719 deg + 0x01BF, // 720-720 deg +}; diff --git a/Firmware/Tasks/Src/FSM.c b/Firmware/Tasks/Src/FSM.c new file mode 100644 index 00000000..6b56a61c --- /dev/null +++ b/Firmware/Tasks/Src/FSM.c @@ -0,0 +1,246 @@ +/** + * @file FSM.c + * @brief Motor controller FSM implementation + * @copyright Copyright (c) 2026 UT Longhorn Racing Solar + */ + +#define DEFINE_FSM_TABLE +#include "fsm_table_dnr.h" + +#include "BPSCAN_can_msgs.h" +#include "CarCAN_can_msgs.h" +#include "FSM.h" +#include "FaultBits.h" +#include "MotorCAN_can_msgs.h" +#include "Watchdogs.h" +#include "rollover_speed_table.h" +#include +#include + +#define MAX_VELOCITY 100.0f // meters per second +#define BRAKE_THRESH 42.0f // percent +#define BRAKE_THRESH_HYST 30.0f // percent + +EventBits_t fsm_inputsbits; + +MocoState_t currentState; + +static driver_input_status_t driver_input = {0}; +static accel_brake_position_t accel_brake = {0}; +static lws_standard_t lws = {0}; +static controls_status_t controls_status = {0}; +static mc_status_t motor_status = {0}; +static bps_status_t bps_status = {0}; +static mc_velocitymeasurement_t motor_velocity = {0}; + +static float accel_pedal_pct = 0.0f; +static float brake_pedal_pct = 0.0f; +static float brake_threshold = BRAKE_THRESH; +static bool precharge_complete = false; +static bool rollover_limit_active = false; +static volatile uint16_t car_status = 0; + +// method stubs so linker doesnt shit itself +static void handle_state_init(void); +static void handle_state_not_ready(void); +static void handle_state_forward(void); +static void handle_state_neutral(void); +static void handle_state_reverse(void); +static void handle_state_regen(void); +static void handle_state_cruise(void); +static void handle_state_disabled(void); + +static void update_from_can(void); +static void rebuild_bitfield(void); +static float apply_rollover_limit(float requested_current); + +void fsm_init(void) { + FSM[STATE_INIT].stateHandler = handle_state_init; + FSM[FORWARD_DRIVE].stateHandler = handle_state_forward; + FSM[NEUTRAL_DRIVE].stateHandler = handle_state_neutral; + FSM[REVERSE_DRIVE].stateHandler = handle_state_reverse; + FSM[REGEN].stateHandler = handle_state_regen; + FSM[CRUISE_CONTROL].stateHandler = handle_state_cruise; + FSM[DISABLED].stateHandler = handle_state_disabled; + FSM[CAR_NOT_READY].stateHandler = handle_state_not_ready; + + currentState = FSM[STATE_INIT]; + currentState.stateHandler(); +} + +void fsm_step(void) { + + currentState = FSM[currentState.NextStates[car_status]]; + if (currentState.stateHandler) currentState.stateHandler(); +} + +void fsm_disable(void) { currentState = FSM[DISABLED]; } +void fsm_recover(void) { currentState = FSM[CAR_NOT_READY]; } +void fsm_set_precharge_complete(bool val) { precharge_complete = val; } +uint16_t fsm_get_car_status(void) { return (uint16_t)car_status; } +bool fsm_is_over_rollover_speed(void) { return rollover_limit_active; } + +static void update_from_can(void) { + + carcan_try_recv(CAN_ID_DRIVER_INPUT_STATUS, handle_driver_input, &driver_input); + carcan_try_recv(CAN_ID_ACCEL_BRAKE_POSITION, handle_accel_brake, &accel_brake); + carcan_try_recv(CAN_ID_LWS_STANDARD, handle_lws, &lws); + carcan_try_recv(CAN_ID_CONTROLS_STATUS, handle_controls_status, &controls_status); + carcan_try_recv(CAN_ID_BPS_STATUS, handle_bps, &bps_status); + vcucan_try_recv(CAN_ID_MC_VELOCITYMEASUREMENT, handle_motor_velocity, &motor_velocity); + vcucan_try_recv(CAN_ID_MC_STATUS, handle_motor_status, &motor_status); +} + +static void rebuild_bitfield(void) { + uint16_t s = 0; + + if (driver_input.Gear_Forward) + s |= FORWARD_BIT; + else if (driver_input.Gear_Reverse) + s |= REVERSE_BIT; + else + s |= NEUTRAL_BIT; + + if (driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; + if (driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; + if (driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; + if (bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; + if (precharge_complete) s |= PRECHARGE_COMPLETE_BIT; + + accel_pedal_pct = accel_brake.Accel_Pos_Main; + brake_pedal_pct = accel_brake.Brake_Pos_Main; + + if (brake_pedal_pct >= brake_threshold) { + s |= BRAKE_BIT; + brake_threshold = BRAKE_THRESH_HYST; + } else { + brake_threshold = BRAKE_THRESH; + } + + car_status = s; +} + +// goofy ahh logic, uses lut +static float apply_rollover_limit(float requested_current) { + int deg = abs((int)lws.LWS_Angle) / 10; + if (deg > (int)ROLLOVER_TABLE_MAX_DEG) deg = (int)ROLLOVER_TABLE_MAX_DEG; + + uint16_t v_max_cms = rollover_speed_table[deg]; + uint16_t v_now_cms = (uint16_t)(motor_velocity.MC_VehicleVelocity * 100.0f); + + if (v_max_cms != ROLLOVER_TABLE_NO_LIMIT && v_now_cms > v_max_cms) { + rollover_limit_active = true; + return 0.0f; + } + rollover_limit_active = false; + return requested_current; +} + +float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, + uint8_t out_max) { + if (in_min >= in_max || input <= in_min) return (float)out_min / 100.0f; + if (input >= in_max) return (float)out_max / 100.0f; + uint16_t oi = input - in_min; + uint16_t ir = in_max - in_min; + uint16_t or_ = out_max - out_min; + return ((float)(oi * or_) / (float)ir + (float)out_min) / 100.0f; +} + +//// state handlers + +static void handle_state_init(void) { currentState = FSM[CAR_NOT_READY]; } +static void handle_state_neutral(void) { send_motor_drive_cmd(0.0f, 0.0f); } +static void handle_state_disabled(void) { send_motor_drive_cmd(0.0f, 0.0f); } +static void handle_state_regen(void) { send_motor_drive_cmd(0.0f, 1.0f); } +static void handle_state_not_ready(void) { send_motor_drive_cmd(0.0f, 0.0f); } + +static void handle_state_forward(void) { + if (motor_velocity.MC_VehicleVelocity < -0.5f) { + // if we're actually going backwards, let off the pedal until we slow down + send_motor_drive_cmd(0.0f, 0.0f); + } else { + send_motor_drive_cmd(MAX_VELOCITY, apply_rollover_limit(accel_pedal_pct)); + } +} + +static void handle_state_reverse(void) { + if (motor_velocity.MC_VehicleVelocity > 0.5f) { + // if we're actually going forwards, let off the pedal until we slow down + send_motor_drive_cmd(0.0f, 0.0f); + } else { + send_motor_drive_cmd(-MAX_VELOCITY, apply_rollover_limit(accel_pedal_pct)); + } +} + +static void handle_state_cruise(void) { + float current = apply_rollover_limit(accel_pedal_pct); + float velocity = rollover_limit_active ? 0.0f : MAX_VELOCITY; + send_motor_drive_cmd(velocity, current); +} + +//////// rtos tasks + +void Task_UpdateControlStatus(void *args __attribute__((unused))) { + TickType_t last = xTaskGetTickCount(); + while (1) { + update_from_can(); + rebuild_bitfield(); + vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); + } +} + +void Task_FSM(void *args __attribute__((unused))) { + TickType_t last = xTaskGetTickCount(); + while (1) { + fsm_step(); + vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); + } +} + +// VCU_Status 0x10 3 bytes 100ms +void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { + uint8_t buf[3]; + + while (1) { + // Byte 0: VCU_Fault — map internal faults to DBC enum + uint8_t vcu_fault = VCU_STATUS_VCU_FAULT_NO_FAULT; + if (faults_is_active(FAULT_ID_PRECHARGE_TIMEOUT)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_PRECHARGE_TIMEOUT; + else if (faults_is_active(FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE; + else if (faults_is_active(FAULT_ID_MOTOR_15V_UNDERVOLTAGE)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE; + else if (faults_is_active(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT) || + faults_is_active(FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT) || + faults_is_active(FAULT_ID_MOTOR_BAD_HALL_SEQUENCE) || + faults_is_active(FAULT_ID_MOTOR_WD_RESET) || + faults_is_active(FAULT_ID_MOTOR_CONFIG_READ) || + faults_is_active(FAULT_ID_MOTOR_DESATURATION) || + faults_is_active(FAULT_ID_MOTOR_OVERSPEED)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_CONTROLLER_FAULT; + buf[0] = vcu_fault; + + // Byte 1: status bits per DBC positions 8-14 + bool pedals_ok = + !accel_brake.Accel_Pos_Main_Fault && !accel_brake.Accel_Pos_Redundant_Fault && + !accel_brake.Brake_Pos_Main_Fault && !accel_brake.Brake_Pos_Redundant_Fault && + !accel_brake.Brake_Pressure_1_Fault && !accel_brake.Brake_Pressure_2_Fault; + + bool driver_input_ok = !faults_is_active(FAULT_ID_CONTROLS_STATUS_WATCHDOG) && + !faults_is_active(FAULT_ID_CONTROLS_FAULT); + + buf[1] = ((uint8_t)precharge_complete << 0) | // Motor_Contactor_State + ((uint8_t)precharge_complete << 1) | // Motor_Precharge_Contactor_State + ((uint8_t)precharge_complete << 2) | // Motor_Ready_To_Drive + ((uint8_t)driver_input_ok << 3) | // VCU_Driver_Input_OK + ((uint8_t)pedals_ok << 4) | // VCU_Pedals_OK + ((uint8_t)!!(car_status & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK + ((uint8_t)(currentState.stateName == REGEN) << 6); // VCU_Regen_Active + + // Byte 2: VCU_FSM_State bits [3:0] + buf[2] = (uint8_t)(currentState.stateName & 0x0FU); + + carcan_send(CAN_ID_VCU_STATUS, buf, sizeof(buf)); + vTaskDelay(pdMS_TO_TICKS(100)); + } +} diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index ad11c638..808f2b88 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -66,7 +66,7 @@ // fault_printf_debug_counter = 0; // } -// Toggle_LED(HB); +// LED_toggle(HB); // vTaskDelay(FAULT_LOOP_PERIOD_MS); // } // } @@ -239,7 +239,7 @@ void Task_FaultHandler(void *args __attribute__((unused))) { } FHT_set_fault_leds(bits); - Toggle_LED(HB); + LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(FAULT_LOOP_PERIOD_MS)); } } diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 31f94951..a9312dd0 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -26,8 +26,8 @@ void Task_Init() { MotorSafeBits_Init(); - Motor_CANBus_Init(); - Car_CANBus_Init(); + MotorCAN_Init(); + CarCAN_Init(); xTaskCreateStatic( Task_FaultHandler, // Task function diff --git a/Firmware/Tasks/Src/MotorControlTask.c b/Firmware/Tasks/Src/MotorControlTask.c index c8f451d9..5bd5a6dc 100644 --- a/Firmware/Tasks/Src/MotorControlTask.c +++ b/Firmware/Tasks/Src/MotorControlTask.c @@ -84,7 +84,7 @@ void Task_MotorControl(void){ while(1){ // Send power command - Motor_CANBus_Send(&mocoPowerCommandHeader, motor_power_tx_data, portMAX_DELAY); + MotorCAN_Send(&mocoPowerCommandHeader, motor_power_tx_data, portMAX_DELAY); // check if the car is in a drivable state motorSafeBits = MotorSafeBits_WaitMask(motorDrivableBits, pdMS_TO_TICKS(0)); @@ -103,7 +103,7 @@ void Task_MotorControl(void){ packDriveCommand(motorDriveCommand, motor_drive_tx_data); - Motor_CANBus_Send(&mocoDriveCommandHeader, motor_drive_tx_data, portMAX_DELAY); + MotorCAN_Send(&mocoDriveCommandHeader, motor_drive_tx_data, portMAX_DELAY); print_debug_counter++; if(print_debug_counter > MOTOR_CONTROLLER_PRINT_DEBUG_COUNT){ @@ -114,7 +114,7 @@ void Task_MotorControl(void){ print_debug_counter = 0; } - Toggle_LED(CAR_HB); + LED_toggle(CAR_HB); // minimum delay for drive command is 250ms, or else the wavesculptor will reset to neutral vTaskDelay(pdMS_TO_TICKS(MOTOR_CONTROL_TASK_PERIOD_MS)); diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index 92b5f6d7..15cb5af0 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -1,70 +1,56 @@ #include "MotorTelemetryTask.h" -#define MOTOR_TELEMETRY_QUEUE_SIZE 32 +#define MOTOR_TELEMETRY_QUEUE_SIZE 32 static StaticQueue_t motorTelemetryQueueBuffer; static uint8_t motorTelemetryQueueStorage[MOTOR_TELEMETRY_QUEUE_SIZE * sizeof(can_rx_payload_t)]; static QueueHandle_t motorTelemetryQueue; - -void print_slcan(const can_rx_payload_t payload) -{ - - uint32_t id = payload.header.Identifier; - uint8_t len = (payload.header.DataLength); +void print_slcan(const can_rx_payload_t payload) { + uint32_t id = payload.header.Identifier; + uint8_t len = (payload.header.DataLength); /* SLCAN supports max 8 bytes */ - if (len > 8) - len = 8; + if (len > 8) len = 8; - if (payload.header.IdType == FDCAN_STANDARD_ID) - { + if (payload.header.IdType == FDCAN_STANDARD_ID) { /* tIII DLC DATA... */ printf("t%03lX%1X", id & 0x7FF, len); - } - else - { + } else { /* TIIIIIIII DLC DATA... */ printf("T%08lX%1X", id & 0x1FFFFFFF, len); } - for (uint8_t i = 0; i < len; i++) - { + for (uint8_t i = 0; i < len; i++) { printf("%02X", payload.data[i]); } printf("\r\n"); } -void MotorTelemetryTask_Init(void){ - motorTelemetryQueue = xQueueCreateStatic( - MOTOR_TELEMETRY_QUEUE_SIZE, - sizeof(can_rx_payload_t), - motorTelemetryQueueStorage, - &motorTelemetryQueueBuffer - ); +void MotorTelemetryTask_Init(void) { + motorTelemetryQueue = + xQueueCreateStatic(MOTOR_TELEMETRY_QUEUE_SIZE, sizeof(can_rx_payload_t), + motorTelemetryQueueStorage, &motorTelemetryQueueBuffer); - if(motorTelemetryQueue == NULL){ + if (motorTelemetryQueue == NULL) { return; } } -void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, can_rx_payload_t recv_payload ){ - + +void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, + can_rx_payload_t recv_payload) { // only forward motorCAN messages to CarCAN - if(motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance){ + if (motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance) { BaseType_t higherPriorityTaskWoken = pdFALSE; - xQueueSendFromISR( - motorTelemetryQueue, - &recv_payload, - &higherPriorityTaskWoken - ); + xQueueSendFromISR(motorTelemetryQueue, &recv_payload, &higherPriorityTaskWoken); // don't yield at the end of this since the rest of the ISR needs to run } } -void Task_MotorTelemetry(){ +void Task_MotorTelemetry() { // motor canbus MUST be initialized by now MotorTelemetryTask_Init(); @@ -82,16 +68,16 @@ void Task_MotorTelemetry(){ carCanTransmitHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; carCanTransmitHeader.MessageMarker = 0; - while(1){ - if (xQueueReceive(motorTelemetryQueue, &payload, portMAX_DELAY) == pdTRUE){ + while (1) { + if (xQueueReceive(motorTelemetryQueue, &payload, portMAX_DELAY) == pdTRUE) { // copy the incoming message's ID and data length carCanTransmitHeader.Identifier = payload.header.Identifier; carCanTransmitHeader.DataLength = payload.header.DataLength; // forward the motorCAN message to CarCAN - Car_CANBus_Send(&carCanTransmitHeader, payload.data, portMAX_DELAY); + CarCAN_Send(&carCanTransmitHeader, payload.data, portMAX_DELAY); - // print the incoming message over + // print the incoming message over print_slcan(payload); taskYIELD(); } diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index f42a4e67..68fac377 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -164,7 +164,7 @@ void Task_Precharge() { clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); } - Toggle_LED(HB); + LED_toggle(HB); vTaskDelay(PRECHARGE_TASK_DELAY_MS); } } \ No newline at end of file diff --git a/Firmware/Tasks/Src/ReadMotorCAN.c b/Firmware/Tasks/Src/ReadMotorCAN.c index 12b122b9..b016044e 100644 --- a/Firmware/Tasks/Src/ReadMotorCAN.c +++ b/Firmware/Tasks/Src/ReadMotorCAN.c @@ -18,7 +18,7 @@ void Task_ReadMotorCAN(){ while(1){ - if(Motor_CANBus_Recieve(CAN_ID_MC_STATUS, &motorstatus_rx_header, motorstatus_rx_data, portMAX_DELAY) == CAN_OK){ + if(MotorCAN_Recv(CAN_ID_MC_STATUS, &motorstatus_rx_header, motorstatus_rx_data, portMAX_DELAY) == CAN_OK){ can_recv_errors = 0; }else{ can_recv_errors++; diff --git a/Firmware/config/Inc/BPSCAN_can_msgs.h b/Firmware/config/Inc/BPSCAN_can_msgs.h new file mode 100644 index 00000000..7c838a1f --- /dev/null +++ b/Firmware/config/Inc/BPSCAN_can_msgs.h @@ -0,0 +1,163 @@ +#pragma once + +#include + +/* ================= CAN ID Macros ================= */ + +#define CAN_ID_BPS_VOLTAGE_ARR_0 0x2 +#define CAN_ID_BPS_VOLTAGE_ARR_1 0x3 +#define CAN_ID_BPS_VOLTAGE_ARR_2 0x4 +#define CAN_ID_BPS_VOLTAGE_ARR_3 0x5 +#define CAN_ID_BPS_VOLTAGE_ARR_4 0x6 +#define CAN_ID_BPS_VOLTAGE_ARR_5 0x7 +#define CAN_ID_BPS_VOLTAGE_ARR_6 0x8 +#define CAN_ID_BPS_VOLTAGE_ARR_7 0x9 +#define CAN_ID_BPS_PACK_CURRENT 0xA +#define CAN_ID_BPS_TEMPERATURE_ARR_0 0x10 +#define CAN_ID_BPS_TEMPERATURE_ARR_1 0x11 +#define CAN_ID_BPS_TEMPERATURE_ARR_2 0x12 +#define CAN_ID_BPS_TEMPERATURE_ARR_3 0x13 +#define CAN_ID_BPS_TEMPERATURE_ARR_4 0x14 +#define CAN_ID_BPS_TEMPERATURE_ARR_5 0x15 +#define CAN_ID_BPS_TEMPERATURE_ARR_6 0x16 +#define CAN_ID_BPS_TEMPERATURE_ARR_7 0x17 +#define CAN_ID_BPS_PRECHARGE_VOLTAGES 0x20 + +/* ================= CAN Length Macros ================= */ + +#define CAN_DLC_BPS_VOLTAGE_ARR_0 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_1 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_2 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_3 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_4 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_5 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_6 4 +#define CAN_DLC_BPS_VOLTAGE_ARR_7 4 +#define CAN_DLC_BPS_PACK_CURRENT 5 +#define CAN_DLC_BPS_TEMPERATURE_ARR_0 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_1 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_2 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_3 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_4 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_5 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_6 7 +#define CAN_DLC_BPS_TEMPERATURE_ARR_7 7 +#define CAN_DLC_BPS_PRECHARGE_VOLTAGES 6 + + +/* ================= Message Structs ================= */ + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_0_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_1_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_2_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_3_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_4_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_5_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_6_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_VoltTemp_BQ_Fault; +} bps_voltage_arr_7_t; + +typedef struct { + int32_t Main_Battery_Current; + uint16_t Main_Battery_Current_RawV; +} bps_pack_current_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_0_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_1_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_2_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_3_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_4_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_5_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_6_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; + int32_t BPS_Temperature_Tap_Data; + uint16_t BPS_Temperature_Tap_RawV; +} bps_temperature_arr_7_t; + +typedef struct { + uint32_t Precharge_Battery_Voltage; + uint32_t Precharge_Array_Voltage; +} bps_precharge_voltages_t; + diff --git a/Firmware/config/Inc/CarCAN_can_msgs.h b/Firmware/config/Inc/CarCAN_can_msgs.h new file mode 100644 index 00000000..b68de6b8 --- /dev/null +++ b/Firmware/config/Inc/CarCAN_can_msgs.h @@ -0,0 +1,470 @@ +#pragma once + +#include + +/* ================= CAN ID Macros ================= */ + +#define CAN_ID_BPS_STATUS 0x1 +#define CAN_ID_BPS_AGGREGATE_ARR 0xB +#define CAN_ID_VCU_STATUS 0x18 +#define CAN_ID_CONTROLS_STATUS 0x19 +#define CAN_ID_VCU_PRECHARGE_VOLTAGES 0x21 +#define CAN_ID_ACCEL_BRAKE_POSITION 0x50 +#define CAN_ID_ACCEL_BRAKE_POSITION_VOLTAGE 0x51 +#define CAN_ID_DRIVER_INPUT_STATUS 0x60 +#define CAN_ID_MPPT_A_POWER 0x200 +#define CAN_ID_MPPT_A_STATUS 0x201 +#define CAN_ID_MPPT_A_SETMODE 0x209 +#define CAN_ID_MPPT_B_POWER 0x210 +#define CAN_ID_MPPT_B_STATUS 0x211 +#define CAN_ID_MPPT_B_SETMODE 0x219 +#define CAN_ID_MPPT_C_POWER 0x220 +#define CAN_ID_MPPT_C_STATUS 0x221 +#define CAN_ID_MPPT_C_SETMODE 0x229 +#define CAN_ID_LWS_STANDARD 0x2B0 +#define CAN_ID_SUPP_BATTERY_STATUS 0x300 +#define CAN_ID_SUPP_BATTERY_CHARGER_STATUS 0x301 +#define CAN_ID_BBPDU_STATUS 0x350 +#define CAN_ID_BBPDU_SET_SWITCHES 0x351 +#define CAN_ID_BBPDU_SET_CURRENT_LIMIT 0x352 +#define CAN_ID_PUMP_STATUS_FLOWRATE 0x500 +#define CAN_ID_COOLANT_TEMPERATURE 0x501 +#define CAN_ID_RADIATOR_FANSPEED 0x502 +#define CAN_ID_LV_CARRIER_STATUS 0x600 +#define CAN_ID_BRAKE_PRESSURE 0x650 +#define CAN_ID_DISPLAY_CAMERAS_STATUS 0x700 +#define CAN_ID_TELEMETRY_STATUS 0x750 +#define CAN_ID_LWS_CONFIG 0x7C0 + +/* ================= CAN Length Macros ================= */ + +#define CAN_DLC_BPS_STATUS 7 +#define CAN_DLC_BPS_AGGREGATE_ARR 7 +#define CAN_DLC_VCU_STATUS 6 +#define CAN_DLC_CONTROLS_STATUS 4 +#define CAN_DLC_VCU_PRECHARGE_VOLTAGES 6 +#define CAN_DLC_ACCEL_BRAKE_POSITION 5 +#define CAN_DLC_ACCEL_BRAKE_POSITION_VOLTAGE 8 +#define CAN_DLC_DRIVER_INPUT_STATUS 2 +#define CAN_DLC_MPPT_A_POWER 8 +#define CAN_DLC_MPPT_A_STATUS 5 +#define CAN_DLC_MPPT_A_SETMODE 1 +#define CAN_DLC_MPPT_B_POWER 8 +#define CAN_DLC_MPPT_B_STATUS 5 +#define CAN_DLC_MPPT_B_SETMODE 1 +#define CAN_DLC_MPPT_C_POWER 8 +#define CAN_DLC_MPPT_C_STATUS 5 +#define CAN_DLC_MPPT_C_SETMODE 1 +#define CAN_DLC_LWS_STANDARD 5 +#define CAN_DLC_SUPP_BATTERY_STATUS 8 +#define CAN_DLC_SUPP_BATTERY_CHARGER_STATUS 8 +#define CAN_DLC_BBPDU_STATUS 5 +#define CAN_DLC_BBPDU_SET_SWITCHES 4 +#define CAN_DLC_BBPDU_SET_CURRENT_LIMIT 4 +#define CAN_DLC_PUMP_STATUS_FLOWRATE 6 +#define CAN_DLC_COOLANT_TEMPERATURE 4 +#define CAN_DLC_RADIATOR_FANSPEED 8 +#define CAN_DLC_LV_CARRIER_STATUS 2 +#define CAN_DLC_BRAKE_PRESSURE 8 +#define CAN_DLC_DISPLAY_CAMERAS_STATUS 2 +#define CAN_DLC_TELEMETRY_STATUS 8 +#define CAN_DLC_LWS_CONFIG 2 + + +/* ================= Value Table Enums ================= */ + +typedef enum { + BPS_STATUS_BPS_FAULT_DISCHARGING_OVERCURRENT = 16, + BPS_STATUS_BPS_FAULT_CHARGING_OVERCURRENT = 15, + BPS_STATUS_BPS_FAULT_ESTOP_3 = 14, + BPS_STATUS_BPS_FAULT_ESTOP_2 = 13, + BPS_STATUS_BPS_FAULT_ESTOP_1 = 12, + BPS_STATUS_BPS_FAULT_ARRAY_PCHG_CONTACTOR_SENSE = 11, + BPS_STATUS_BPS_FAULT_ARRAY_CONTACTOR_SENSE = 10, + BPS_STATUS_BPS_FAULT_HV_MINUS_CONTACTOR_SENSE = 9, + BPS_STATUS_BPS_FAULT_HV_PLUS_CONTACTOR_SENSE = 8, + BPS_STATUS_BPS_FAULT_WATCHDOG = 7, + BPS_STATUS_BPS_FAULT_ARRAY_PRECHARGE_TIMEOUT = 6, + BPS_STATUS_BPS_FAULT_ELCON = 5, + BPS_STATUS_BPS_FAULT_OVERTEMPERATURE = 4, + BPS_STATUS_BPS_FAULT_REGEN = 3, + BPS_STATUS_BPS_FAULT_UNDERVOLTAGE = 2, + BPS_STATUS_BPS_FAULT_OVERVOLTAGE = 1, + BPS_STATUS_BPS_FAULT_NO_FAULT = 0, +} bps_status_bps_fault_e; + +typedef enum { + VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE = 6, + VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE = 5, + VCU_STATUS_VCU_FAULT_MOTOR_CONTROLLER_FAULT = 4, + VCU_STATUS_VCU_FAULT_MOTOR_PRECHARGE_TIMEOUT = 3, + VCU_STATUS_VCU_FAULT_MOTOR_PCHG_CONTACTOR_SENSE = 2, + VCU_STATUS_VCU_FAULT_MOTOR_CONTACTOR_SENSE = 1, + VCU_STATUS_VCU_FAULT_NO_FAULT = 0, +} vcu_status_vcu_fault_e; + +typedef enum { + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_DRIVE_INPUTS_INVALID_ = 3, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BPS_WATCHDOG = 2, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_STEERING_ANGLE_SENSOR_WATCHDOG = 1, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_NO_FAULT = 0, +} controls_status_controls_leader_fault_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_13_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_13_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_13_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_13_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_13_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_14_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_14_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_14_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_14_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_14_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_15_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_15_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_15_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_15_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_15_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_16_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_16_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_16_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_16_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_16_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_9_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_9_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_9_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_9_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_9_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_10_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_10_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_10_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_10_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_10_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_11_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_11_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_11_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_11_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_11_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_12_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_12_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_12_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_12_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_12_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_5_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_5_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_5_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_5_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_5_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_6_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_6_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_6_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_6_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_6_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_7_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_7_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_7_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_7_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_7_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_8_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_8_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_8_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_8_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_8_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_1_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_1_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_1_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_1_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_1_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_2_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_2_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_2_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_2_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_2_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_3_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_3_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_3_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_3_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_3_e; + +typedef enum { + BBPDU_SET_SWITCHES_HSS_CONTROL_4_DO_NOTHING_YOU_RE_STUPID = 3, + BBPDU_SET_SWITCHES_HSS_CONTROL_4_TURN_OFF = 2, + BBPDU_SET_SWITCHES_HSS_CONTROL_4_TURN_ON = 1, + BBPDU_SET_SWITCHES_HSS_CONTROL_4_DO_NOTHING_KEEP_CURRENT_STATE = 0, +} bbpdu_set_switches_hss_control_4_e; + +typedef enum { + LWS_CONFIG_LWS_CCW_RESETS_CALIBRATION_STATUS = 5, + LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0_ = 3, +} lws_config_lws_ccw_e; + +/* ================= Message Structs ================= */ + +typedef struct { + uint8_t BPS_Fault; + uint8_t BPS_Charge_OK; + uint8_t BPS_Regen_OK; + uint8_t HV_Plus_Contactor_State; + uint8_t HV_Minus_Contactor_State; + uint8_t Array_Contactor_State; + uint8_t Array_Precharge_Contactor_State; + uint32_t Main_Battery_Voltage; + int16_t Main_Battery_Avg_Temperature; +} bps_status_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Voltage_Tap_Data; + int32_t BPS_Temperature_Tap_Data; +} bps_aggregate_arr_t; + +typedef struct { + uint8_t VCU_Fault; + uint8_t Motor_Contactor_State; + uint8_t Motor_Precharge_Contactor_State; + uint8_t Motor_Ready_To_Drive; + uint8_t VCU_Driver_Input_OK; + uint8_t VCU_Pedals_OK; + uint8_t VCU_Regen_OK; + uint8_t VCU_Regen_Active; + uint8_t VCU_Steering_Angle_OK; + uint8_t VCU_FSM_State; + uint16_t VCU_FSM_Inputs; +} vcu_status_t; + +typedef struct { + uint8_t Controls_Leader_Fault; + uint16_t Controls_Lighting_Fault; +} controls_status_t; + +typedef struct { + uint32_t Precharge_Battery_Voltage; + uint32_t Precharge_Motor_Voltage; +} vcu_precharge_voltages_t; + +typedef struct { + uint8_t Accel_Pos_Main; + uint8_t Accel_Pos_Redundant; + uint8_t Brake_Pos_Main; + uint8_t Brake_Pos_Redundant; + uint8_t Accel_Pos_Main_Fault; + uint8_t Accel_Pos_Redundant_Fault; + uint8_t Brake_Pos_Main_Fault; + uint8_t Brake_Pos_Redundant_Fault; + uint8_t Brake_Pressure_1_Fault; + uint8_t Brake_Pressure_2_Fault; +} accel_brake_position_t; + +typedef struct { + uint16_t Accel_Pos_Voltage_Main; + uint16_t Accel_Pos_Voltage_Redundant; + uint16_t Brake_Pos_Voltage_Main; + uint16_t Brake_Pos_Voltage_Redundant; +} accel_brake_position_voltage_t; + +typedef struct { + uint8_t Ignition_Array; + uint8_t Ignition_Motor; + uint8_t Ignition_Off; + uint8_t Cruise_Enable; + uint8_t Cruise_Set; + uint8_t Gear_Forward; + uint8_t Gear_Neutral; + uint8_t Gear_Reverse; + uint8_t Hazard_Pressed; + uint8_t Horn_Pressed; + uint8_t Blinker_Left; + uint8_t Blinker_Right; + uint8_t PushToTalk_Pressed; + uint8_t Regen_Activate; + uint8_t Regen_Enable; +} driver_input_status_t; + +typedef struct { + int16_t MPPT_Vin; + int16_t MPPT_Iin; + int16_t MPPT_Vout; + int16_t MPPT_Iout; +} mppt_a_power_t; + +typedef struct { + uint8_t MPPT_Mode; + uint8_t MPPT_Fault; + int8_t MPPT_Enabled; + int8_t MPPT_AmbientTemperature; + int8_t MPPT_HeatsinkTemperature; +} mppt_a_status_t; + +typedef struct { + uint8_t Boost_Enable; +} mppt_a_setmode_t; + +typedef struct { + int16_t MPPT_Vin; + int16_t MPPT_Iin; + int16_t MPPT_Vout; + int16_t MPPT_Iout; +} mppt_b_power_t; + +typedef struct { + uint8_t MPPT_Mode; + uint8_t MPPT_Fault; + int8_t MPPT_Enabled; + int8_t MPPT_AmbientTemperature; + int8_t MPPT_HeatsinkTemperature; +} mppt_b_status_t; + +typedef struct { + uint8_t Boost_Enable; +} mppt_b_setmode_t; + +typedef struct { + int16_t MPPT_Vin; + int16_t MPPT_Iin; + int16_t MPPT_Vout; + int16_t MPPT_Iout; +} mppt_c_power_t; + +typedef struct { + uint8_t MPPT_Mode; + uint8_t MPPT_Fault; + int8_t MPPT_Enabled; + int8_t MPPT_AmbientTemperature; + int8_t MPPT_HeatsinkTemperature; +} mppt_c_status_t; + +typedef struct { + uint8_t Boost_Enable; +} mppt_c_setmode_t; + +typedef struct { + int16_t LWS_Angle; + uint8_t LWS_Speed; + uint8_t LWS_OK; + uint8_t LWS_CAL; + uint8_t LWS_TRIM; +} lws_standard_t; + +typedef struct { + uint16_t Supplemental_Battery_Voltage; +} supp_battery_status_t; + +typedef struct { + uint8_t SuppCharger_Status; + int16_t Supplemental_Battery_Current; + uint16_t Supplemental_DCDC_Voltage; + int16_t Supplemental_DCDC_Current; +} supp_battery_charger_status_t; + +typedef struct { + uint8_t HSS_Channel; + uint8_t HSS_Fault; + uint8_t HSS_Enabled; + uint16_t HSS_Measured_Voltage; + uint16_t HSS_Measured_Current; +} bbpdu_status_t; + +typedef struct { + uint8_t HSS_Control_13; + uint8_t HSS_Control_14; + uint8_t HSS_Control_15; + uint8_t HSS_Control_16; + uint8_t HSS_Control_9; + uint8_t HSS_Control_10; + uint8_t HSS_Control_11; + uint8_t HSS_Control_12; + uint8_t HSS_Control_5; + uint8_t HSS_Control_6; + uint8_t HSS_Control_7; + uint8_t HSS_Control_8; + uint8_t HSS_Control_1; + uint8_t HSS_Control_2; + uint8_t HSS_Control_3; + uint8_t HSS_Control_4; +} bbpdu_set_switches_t; + +typedef struct { + uint8_t HSS_Channel; + uint16_t HSS_Current_Limit; +} bbpdu_set_current_limit_t; + +typedef struct { + uint8_t Pump_DutyCycle; + uint8_t Pump_Fault; + uint16_t FlowRate_1; + uint16_t FlowRate_2; +} pump_status_flowrate_t; + +typedef struct { + int16_t Coolant_Temperature_1; + int16_t Coolant_Temperature_2; +} coolant_temperature_t; + +typedef struct { + uint16_t Radiator_Fan_Speed_Measurement_1; + uint16_t Radiator_Fan_Speed_Measurement_2; + uint16_t Radiator_Fan_Speed_Target_1; + uint16_t Radiator_Fan_Speed_Target_2; +} radiator_fanspeed_t; + +typedef struct { + uint8_t LTC4421_HVDCDC_Selected; + uint8_t LTC4421_HVDCDC_Fault; + uint8_t LTC4421_HVDCDC_Valid; + uint8_t LTC4421_SuppBatt_Selected; + uint8_t LTC4421_SuppBatt_Fault; + uint8_t LTC4421_SuppBatt_Valid; + uint8_t LV_EN_SupplementalBattery; + uint8_t LV_EN_PowerSupply; +} lv_carrier_status_t; + +typedef struct { + uint16_t Brake_Pressure_1; + uint16_t Brake_Pressure_1_Voltage; + uint16_t Brake_Pressure_2; + uint16_t Brake_Pressure_2_Voltage; +} brake_pressure_t; + +typedef struct { + uint8_t Display_FrameRate; + uint8_t Camera_Status_Backup; + uint8_t Camera_Status_Left; + uint8_t Camera_Status_Right; +} display_cameras_status_t; + +typedef struct { +} telemetry_status_t; + +typedef struct { + uint8_t LWS_CCW; +} lws_config_t; + diff --git a/Firmware/config/Inc/ControlsCAN_can_msgs.h b/Firmware/config/Inc/ControlsCAN_can_msgs.h new file mode 100644 index 00000000..ed3b852b --- /dev/null +++ b/Firmware/config/Inc/ControlsCAN_can_msgs.h @@ -0,0 +1,224 @@ +#pragma once + +#include + +/* ================= CAN ID Macros ================= */ + +#define CAN_ID_LIGHTING_COMMAND 0x660 +#define CAN_ID_LIGHTING_BOARD0_STATUS 0x670 +#define CAN_ID_LIGHTING_BOARD1_STATUS 0x671 +#define CAN_ID_LIGHTING_BOARD2_STATUS 0x672 +#define CAN_ID_LIGHTING_BOARD3_STATUS 0x673 +#define CAN_ID_LIGHTING_BOARD4_STATUS 0x674 +#define CAN_ID_LIGHTING_BOARD5_STATUS 0x675 +#define CAN_ID_LIGHTING_BOARD6_STATUS 0x676 + +/* ================= CAN Length Macros ================= */ + +#define CAN_DLC_LIGHTING_COMMAND 1 +#define CAN_DLC_LIGHTING_BOARD0_STATUS 8 +#define CAN_DLC_LIGHTING_BOARD1_STATUS 8 +#define CAN_DLC_LIGHTING_BOARD2_STATUS 8 +#define CAN_DLC_LIGHTING_BOARD3_STATUS 8 +#define CAN_DLC_LIGHTING_BOARD4_STATUS 8 +#define CAN_DLC_LIGHTING_BOARD5_STATUS 8 +#define CAN_DLC_LIGHTING_BOARD6_STATUS 8 + + +/* ================= Value Table Enums ================= */ + +typedef enum { + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board0_status_lighting_board_faults_e; + +typedef enum { + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board1_status_lighting_board_faults_e; + +typedef enum { + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board2_status_lighting_board_faults_e; + +typedef enum { + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board3_status_lighting_board_faults_e; + +typedef enum { + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board4_status_lighting_board_faults_e; + +typedef enum { + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board5_status_lighting_board_faults_e; + +typedef enum { + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, + LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, +} lighting_board6_status_lighting_board_faults_e; + +/* ================= Message Structs ================= */ + +typedef struct { + uint8_t Headlights_On; + uint8_t Left_Indicator_On; + uint8_t Right_Indicator_On; + uint8_t Blinker_Sync; + uint8_t Brakelights_On; + uint8_t BPS_Strobe_On; + uint8_t Custom_Mode0_On; + uint8_t Custom_Mode1_On; +} lighting_command_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board0_status_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board1_status_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board2_status_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board3_status_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board4_status_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board5_status_t; + +typedef struct { + uint8_t Lighting_Board_Faults; + uint8_t Light_Headlight_Active; + uint8_t Light_LTurn_Active; + uint8_t Light_RTurn_Active; + uint8_t Light_BPS_Strobe_Active; + uint8_t Light_Brakelight_Active; + uint8_t Light_Custom0_Active; + uint8_t Light_Custom1_Active; + uint8_t Light_Custom2_Active; + uint16_t Addr_LED_Current; + uint16_t LED0_Current; + uint16_t LED1_Current; +} lighting_board6_status_t; + diff --git a/Firmware/config/Inc/MotorCAN_can_msgs.h b/Firmware/config/Inc/MotorCAN_can_msgs.h index 86cd5e73..0c5c5466 100644 --- a/Firmware/config/Inc/MotorCAN_can_msgs.h +++ b/Firmware/config/Inc/MotorCAN_can_msgs.h @@ -22,6 +22,26 @@ #define CAN_ID_MC_ODOMETERBUSAHMEASUREMENT 0x42E #define CAN_ID_MC_SLIPSPEEDMEASUREMENT 0x437 +/* ================= CAN Length Macros ================= */ + +#define CAN_DLC_MC_DRIVECOMMAND 8 +#define CAN_DLC_MC_POWERCOMMAND 4 +#define CAN_DLC_MC_RESETCOMMAND 1 +#define CAN_DLC_MC_INFO 8 +#define CAN_DLC_MC_STATUS 8 +#define CAN_DLC_MC_BUSMEASUREMENT 8 +#define CAN_DLC_MC_VELOCITYMEASUREMENT 8 +#define CAN_DLC_MC_PHASECURRENTMEASUREMENT 8 +#define CAN_DLC_MC_MOTORVOLTAGEVECTORMEASUREMENT 8 +#define CAN_DLC_MC_MOTORCURRENTVECTORMEASUREMENT 8 +#define CAN_DLC_MC_BACKEMFMEASUREMENTPREDICTION 8 +#define CAN_DLC_MC_15VRAILMEASUREMENT 8 +#define CAN_DLC_MC_3V319VRAILMEASUREMENT 8 +#define CAN_DLC_MC_MOTOR_TEMPMEASUREMENT 8 +#define CAN_DLC_MC_DSPBOARDTEMPMEASUREMENT 8 +#define CAN_DLC_MC_ODOMETERBUSAHMEASUREMENT 8 +#define CAN_DLC_MC_SLIPSPEEDMEASUREMENT 8 + /* ================= Message Structs ================= */ diff --git a/Firmware/core/Src/main.c b/Firmware/core/Src/main.c index 7836d321..7d325778 100644 --- a/Firmware/core/Src/main.c +++ b/Firmware/core/Src/main.c @@ -7,7 +7,7 @@ int main(void) { HAL_Init(); SystemClock_Config(); - LEDs_init(); + LED_init(); xTaskCreateStatic( Task_Init, // Task function diff --git a/Firmware/scripts/fsm_generator.py b/Firmware/scripts/fsm_generator.py new file mode 100644 index 00000000..ba5e0f41 --- /dev/null +++ b/Firmware/scripts/fsm_generator.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +import argparse +from pathlib import Path + +OUT_DIR = Path(__file__).resolve().parent.parent / "Tasks/Inc" + +BITS = { + "NEUTRAL_BIT": 1 << 0, + "FORWARD_BIT": 1 << 1, + "REVERSE_BIT": 1 << 2, + "CRUISE_CONTROL_BUTTON_BIT": 1 << 3, + "REGEN_BUTTON_BIT": 1 << 4, + "READY_TO_REGEN_BIT": 1 << 5, + "REGEN_ENABLED_BIT": 1 << 6, + "BRAKE_BIT": 1 << 7, + "PRECHARGE_BIT": 1 << 8, +} + +STATES = [ + "STATE_INIT", + "FORWARD_DRIVE", + "NEUTRAL_DRIVE", + "REVERSE_DRIVE", + "REGEN", + "CRUISE_CONTROL", + "DISABLED", + "CAR_NOT_READY", +] + +STATE_IDX = {s: i for i, s in enumerate(STATES)} +NSL = 1 << len(BITS) + +# preresolve some constants so its easier to write +NEU = BITS["NEUTRAL_BIT"] +FWD = BITS["FORWARD_BIT"] +REV = BITS["REVERSE_BIT"] +CC = BITS["CRUISE_CONTROL_BUTTON_BIT"] +RB = BITS["REGEN_BUTTON_BIT"] +RTR = BITS["READY_TO_REGEN_BIT"] +REN = BITS["REGEN_ENABLED_BIT"] +BRK = BITS["BRAKE_BIT"] +PC = BITS["PRECHARGE_BIT"] + +INIT = STATE_IDX["STATE_INIT"] +FWD_DRIVE = STATE_IDX["FORWARD_DRIVE"] +NEUTRAL = STATE_IDX["NEUTRAL_DRIVE"] +REV_DRIVE = STATE_IDX["REVERSE_DRIVE"] +REGEN = STATE_IDX["REGEN"] +CRUISE = STATE_IDX["CRUISE_CONTROL"] +DISABLED = STATE_IDX["DISABLED"] +NOT_READY = STATE_IDX["CAR_NOT_READY"] + + +def transition_full(cur, bits): + if cur == INIT: + return NOT_READY + + if cur == NOT_READY: + return NEUTRAL if (bits & PC) else NOT_READY + + if cur == DISABLED: + return DISABLED + + if cur == NEUTRAL: + if (bits & FWD) and not (bits & REV) and not (bits & BRK): + return FWD_DRIVE + if (bits & REV) and not (bits & FWD) and not (bits & BRK): + return REV_DRIVE + return NEUTRAL + + if cur == FWD_DRIVE: + if (bits & REV) or (bits & NEU) or (bits & BRK): + return NEUTRAL + if (bits & REN) and (bits & RTR) and (bits & RB): + return REGEN + if (bits & CC) and (bits & REN): + return CRUISE + return FWD_DRIVE + + if cur == REV_DRIVE: + if (bits & REV) and not (bits & FWD) and not (bits & BRK): + return REV_DRIVE + return NEUTRAL + + if cur == REGEN: + if (bits & RB) and (bits & RTR) and (bits & REN) and (bits & FWD): + return REGEN + return FWD_DRIVE + + if cur == CRUISE: + return CRUISE if (bits & CC) else FWD_DRIVE + + return NEUTRAL + + +def transition_dnr(cur, bits): + if cur == INIT: + return NOT_READY + + if cur == NOT_READY: + return NEUTRAL if (bits & PC) else NOT_READY + + if cur == DISABLED: + return DISABLED + + if cur == NEUTRAL: + if (bits & FWD) and not (bits & REV) and not (bits & BRK): + return FWD_DRIVE + if (bits & REV) and not (bits & FWD) and not (bits & BRK): + return REV_DRIVE + return NEUTRAL + + if cur in (FWD_DRIVE, REGEN, CRUISE): + if (bits & REV) or (bits & NEU) or (bits & BRK): + return NEUTRAL + return FWD_DRIVE + + if cur == REV_DRIVE: + if (bits & REV) and not (bits & FWD) and not (bits & BRK): + return REV_DRIVE + return NEUTRAL + + return NEUTRAL + + +def write_table(path, fn, label): + rows = [] + states = STATES + nsl = NSL + + for i, name in enumerate(states): + ns = [states[fn(i, j)] for j in range(nsl)] + chunks = [ + ", ".join(ns[x:x+8]) + for x in range(0, nsl, 8) + ] + + body = ",\n".join(f" {c}" for c in chunks) + + rows.append( + f" [{name}] = {{ {name}, NULL, {{\n{body}\n }}}},\n" + ) + + path.write_text( + f"/**\n" + f" * @file {path.name}\n" + f" * @brief Auto-generated FSM table ({label}); do not edit\n" + f" * Regenerate: python3 generate_fsm.py --{label.lower()}\n" + f" */\n\n" + f"#pragma once\n" + f'#include "FSM.h"\n\n' + f"extern MocoState_t FSM[NUM_STATES];\n\n" + f"#ifdef DEFINE_FSM_TABLE\n" + f"MocoState_t FSM[NUM_STATES] = {{\n\n" + + "".join(rows) + + "};\n" + f"#endif\n" + ) + + print(f"[{label:4}] {path.name} ({len(states)} states x {nsl} inputs)") + + + +def main(): + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group(required=True) + g.add_argument("--full", action="store_true") + g.add_argument("--dnr", action="store_true") + g.add_argument("--all", action="store_true") + args = parser.parse_args() + + OUT_DIR.mkdir(parents=True, exist_ok=True) + + if args.full or args.all: + write_table(OUT_DIR / "fsm_table.h", transition_full, "FULL") + if args.dnr or args.all: + write_table(OUT_DIR / "fsm_table_dnr.h", transition_dnr, "DNR") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Firmware/scripts/steering_angle_lut_generator.py b/Firmware/scripts/steering_angle_lut_generator.py new file mode 100644 index 00000000..af012157 --- /dev/null +++ b/Firmware/scripts/steering_angle_lut_generator.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +""" +generate_rollover_table.py +Generates rollover_speed_table.h — the max allowable speed lookup table. +LWS_Angle is int16_t in 0.1 degree units; table indexed by abs(LWS_Angle / 10). +""" + +import math +from pathlib import Path + +OUT = Path(__file__).resolve().parent.parent / "Tasks/Inc/rollover_speed_table.h" + +G, HALF_TRACK, CG_LATERAL = 9.81, 1.35, 1.612 +CG_HEIGHT, WHEELBASE, STEERING_RATIO, MIN_DEG = 0.481, 2.25, 15.0, 2.0 +NO_LIMIT = 0xFFFF + +def v_max_cms(deg): + wheel_deg = deg / STEERING_RATIO + if abs(wheel_deg) < MIN_DEG: + return NO_LIMIT + R = WHEELBASE / math.tan(math.radians(abs(wheel_deg))) + v_ms = math.sqrt(G * R * HALF_TRACK * CG_LATERAL / (2.0 * CG_HEIGHT * WHEELBASE)) + return min(int(v_ms * 100), NO_LIMIT - 1) + +table = [v_max_cms(i) for i in range(721)] + +rows = [f" " + ", ".join(f"0x{v:04X}" for v in table[i:i+8]) + f", // {i}-{min(i+7, len(table)-1)} deg" + for i in range(0, len(table), 8)] + +OUT.write_text( + "/**\n" + " * @file rollover_speed_table.h\n" + " * @brief Auto-generated rollover speed limit lookup table — do not edit\n" + " * Regenerate: python3 scripts/generate_rollover_table.py\n" + " *\n" + " * Index : abs(LWS_Angle / 10) [integer degrees, 0-720]\n" + " * Value : max allowable speed in cm/s | 0xFFFF = no limit (straight)\n" + " */\n\n" + "#pragma once\n\n" + "#include \n\n" + "#define ROLLOVER_TABLE_NO_LIMIT 0xFFFFU\n" + "#define ROLLOVER_TABLE_MAX_DEG 720U\n\n" + "// Index: abs(LWS_Angle / 10) in integer degrees (0-720)\n" + "// Value: max allowable speed in cm/s | 0xFFFF = no limit\n" + "static const uint16_t rollover_speed_table[721] = {\n" + + "\n".join(rows) + "\n" + "};\n" +) +print(f"Generated {OUT} ({len(table)} entries, {len(table)*2} bytes)") diff --git a/Firmware/tests/CanTxTelemetry_test.c b/Firmware/tests/CanTxTelemetry_test.c index 7b4f702f..ea775b47 100644 --- a/Firmware/tests/CanTxTelemetry_test.c +++ b/Firmware/tests/CanTxTelemetry_test.c @@ -1,17 +1,17 @@ #include "CANbus.h" -#include "stm32xx_hal.h" -#include "inits.h" +#include "CanTxTelemetryTask.h" #include "StatusLEDs.h" +#include "inits.h" #include "pinDefs.h" -#include "CanTxTelemetryTask.h" +#include "stm32xx_hal.h" StaticTask_t task_buffer; StackType_t task_stack[512]; -static void task(void *pvParameters){ +static void task(void *pvParameters) { int test_id = 0x321; - FDCAN_TxHeaderTypeDef tx_header = {0}; + FDCAN_TxHeaderTypeDef tx_header = {0}; tx_header.Identifier = test_id; tx_header.IdType = FDCAN_STANDARD_ID; tx_header.TxFrameType = FDCAN_DATA_FRAME; @@ -32,17 +32,18 @@ static void task(void *pvParameters){ tx_data[5] = 0xBC; tx_data[6] = 0xDE; tx_data[7] = 0xFF; - - while(1){ - if (Motor_CANBus_Send( &tx_header, tx_data, portMAX_DELAY) == CAN_ERR){} + while (1) { - Toggle_LED(HB); + if (MotorCAN_Send(&tx_header, tx_data, portMAX_DELAY) == CAN_ERR) { + } + + LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(1000)); } } -int main(){ +int main() { HAL_Init(); @@ -50,40 +51,26 @@ int main(){ __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - LEDs_init(); - + LED_init(); - Motor_CANBus_Init(); + MotorCAN_Init(); Init_UART_Printf(); - - xTaskCreateStatic( - Task_CanTxTelemetry, // Task function - "Can TX Telemetry Thread", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - CAN_TX_TELEMETRY_THREAD_PRIO, // Task priority - Can_Tx_Telemetry_Task_Stack, // Task handle - &Can_Tx_Telemetry_Task_Buffer // Static task buffer (optional) + xTaskCreateStatic(Task_CanTxTelemetry, // Task function + "Can TX Telemetry Thread", // Name of the task (for debugging) + configMINIMAL_STACK_SIZE, // Stack size in words + NULL, // Task input parameter + CAN_TX_TELEMETRY_THREAD_PRIO, // Task priority + Can_Tx_Telemetry_Task_Stack, // Task handle + &Can_Tx_Telemetry_Task_Buffer // Static task buffer (optional) ); - xTaskCreateStatic( - task, - "task", - 512, - NULL, - tskIDLE_PRIORITY + 2, - task_stack, - &task_buffer); - - + xTaskCreateStatic(task, "task", 512, NULL, tskIDLE_PRIORITY + 2, task_stack, &task_buffer); vTaskStartScheduler(); - - while(1){ - + while (1) { } return 0; } \ No newline at end of file diff --git a/Firmware/tests/Contactors_test.c b/Firmware/tests/Contactors_test.c index 477494cf..e9c4056d 100644 --- a/Firmware/tests/Contactors_test.c +++ b/Firmware/tests/Contactors_test.c @@ -45,7 +45,7 @@ int main() { SystemClock_Config(); - LEDs_init(); + LED_init(); contactor_init(); diff --git a/Firmware/tests/FaultHandler_test.c b/Firmware/tests/FaultHandler_test.c index e7b9e7f5..7b365063 100644 --- a/Firmware/tests/FaultHandler_test.c +++ b/Firmware/tests/FaultHandler_test.c @@ -12,7 +12,7 @@ int main() __HAL_RCC_PWR_CLK_ENABLE(); Init_UART_Printf(); - LEDs_init(); + LED_init(); // Task xTaskCreateStatic( @@ -27,7 +27,7 @@ int main() hprecharge_task = xTaskCreateStatic( Task_Precharge, // Task function - "Precharge", // Name of the task (for debugging) + "Precharge", // Name of the task (for debugging) configMINIMAL_STACK_SIZE, // Stack size in words NULL, // Task input parameter tskIDLE_PRIORITY + 1, // Task priority diff --git a/Firmware/tests/MotorController_test.c b/Firmware/tests/MotorController_test.c index 883c00a7..748c5d43 100644 --- a/Firmware/tests/MotorController_test.c +++ b/Firmware/tests/MotorController_test.c @@ -25,10 +25,10 @@ int main(){ __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - LEDs_init(); + LED_init(); - if(Motor_CANBus_Init() != CAN_OK){ + if(MotorCAN_Init() != CAN_OK){ can_error_handler(); } diff --git a/Firmware/tests/MotorSafe_test.c b/Firmware/tests/MotorSafe_test.c index a8ad654f..eb945bfe 100644 --- a/Firmware/tests/MotorSafe_test.c +++ b/Firmware/tests/MotorSafe_test.c @@ -15,7 +15,7 @@ void waitTask(void *pvParameters){ while(1){ MotorSafeBits_WaitMask((motorDrivableBits), portMAX_DELAY); - Toggle_LED(CAR_DRIVABLE); + LED_toggle(CAR_DRIVABLE); vTaskDelay(pdMS_TO_TICKS(500)); } } @@ -48,7 +48,7 @@ int main(){ __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - LEDs_init(); + LED_init(); Init_UART_Printf(); diff --git a/Firmware/tests/MotorTelemetryTask_test.c b/Firmware/tests/MotorTelemetryTask_test.c index cf2a2725..d96ba410 100644 --- a/Firmware/tests/MotorTelemetryTask_test.c +++ b/Firmware/tests/MotorTelemetryTask_test.c @@ -25,10 +25,10 @@ int main(){ __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - LEDs_init(); + LED_init(); - if(Motor_CANBus_Init() != CAN_OK){ + if(MotorCAN_Init() != CAN_OK){ can_error_handler(); } diff --git a/Firmware/tests/Precharge_test.c b/Firmware/tests/Precharge_test.c index 8ec5583f..643654ed 100644 --- a/Firmware/tests/Precharge_test.c +++ b/Firmware/tests/Precharge_test.c @@ -14,7 +14,7 @@ int main() __HAL_RCC_PWR_CLK_ENABLE(); // Initialize all LED GPIOs - LEDs_init(); + LED_init(); Init_UART_Printf(); diff --git a/Firmware/tests/blinky_test.c b/Firmware/tests/blinky_test.c index 3a848136..f49372e9 100644 --- a/Firmware/tests/blinky_test.c +++ b/Firmware/tests/blinky_test.c @@ -41,13 +41,13 @@ int main(){ */ // Initialize all LED GPIOs - LEDs_init(); + LED_init(); while (1) { // Turn LEDs on one-by-one - for (size_t i = 0; i < num_LEDs; ++i) + for (size_t i = 0; i < NUM_LEDS; ++i) { - Toggle_LED(i); + LED_toggle(i); HAL_Delay(200); } @@ -55,9 +55,9 @@ int main(){ HAL_Delay(500); // Turn LEDs off one-by-one - for (size_t i = 0; i < num_LEDs; ++i) + for (size_t i = 0; i < NUM_LEDS; ++i) { - Toggle_LED(i); + LED_toggle(i); HAL_Delay(200); } diff --git a/Firmware/tests/canbus_test.c b/Firmware/tests/canbus_test.c index 1c1fa8e5..de1a8ec6 100644 --- a/Firmware/tests/canbus_test.c +++ b/Firmware/tests/canbus_test.c @@ -25,7 +25,7 @@ static void task(void *pvParameters) { uint8_t tx_data[TEST_CAN_DATA_LENGTH] = TEST_CAN_DATA; while (1) { - if (Motor_CANBus_Send(&tx_header, tx_data, portMAX_DELAY) != CAN_OK) { + if (MotorCAN_Send(&tx_header, tx_data, portMAX_DELAY) != CAN_OK) { Error_Handler(); } @@ -47,9 +47,9 @@ int main() { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - LEDs_init(); + LED_init(); - if (Motor_CANBus_Init() != CAN_OK) { + if (MotorCAN_Init() != CAN_OK) { can_error_handler(); } diff --git a/Firmware/tests/motorControlTask_test.c b/Firmware/tests/motorControlTask_test.c index f3ccb3e9..7ff192ce 100644 --- a/Firmware/tests/motorControlTask_test.c +++ b/Firmware/tests/motorControlTask_test.c @@ -25,10 +25,10 @@ int main(){ __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - LEDs_init(); + LED_init(); - if(Motor_CANBus_Init() != CAN_OK){ + if(MotorCAN_Init() != CAN_OK){ can_error_handler(); } From 483aedc20667d7e46be78b0ea8dc59e4f3ca35e1 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 4 Apr 2026 21:39:31 -0500 Subject: [PATCH 03/27] shifting stuff around --- Firmware/Drivers/Inc/CANbus.h | 24 +++- Firmware/Drivers/Inc/MotorSafeBits.h | 4 +- Firmware/Drivers/Src/CANbus.c | 168 +++++++++++++++++++++-- Firmware/Drivers/Src/MotorSafeBits.c | 6 +- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSM.h | 25 +++- Firmware/Tasks/Inc/UpdateFSMInputsTask.h | 8 ++ Firmware/Tasks/Src/FSM.c | 118 ++++++++-------- Firmware/Tasks/Src/UpdateFSMInputsTask.c | 149 ++++++++++++++++++++ Firmware/tests/canbus_test.c | 56 +++++--- 10 files changed, 459 insertions(+), 101 deletions(-) create mode 100644 Firmware/Tasks/Inc/UpdateFSMInputsTask.h create mode 100644 Firmware/Tasks/Src/UpdateFSMInputsTask.c diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index 6b251bf0..338a4b26 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -2,20 +2,30 @@ #include "CAN_FD.h" #include "stm32xx_hal.h" +#include "MotorCAN_can_msgs.h" +#include "BPSCAN_can_msgs.h" +#include "CarCAN_can_msgs.h" extern FDCAN_HandleTypeDef *motorfdcan; extern FDCAN_HandleTypeDef *carfdcan; can_status_t MotorCAN_Init(void); - can_status_t MotorCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); - -can_status_t MotorCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], +can_status_t MotorCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); -can_status_t CarCAN_Init(void); +can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay); +can_status_t MotorCAN_Recv_Velocity(mc_velocitymeasurement_t *out, TickType_t delay); -can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); +can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay); -can_status_t CarCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], - TickType_t delay_ticks); \ No newline at end of file +can_status_t CarCAN_Init(void); +can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); +can_status_t CarCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], + TickType_t delay_ticks); + +can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay); +can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay); +can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t delay); +can_status_t CarCAN_Recv_Pedals_Position(accel_brake_position_t *out, TickType_t delay); +can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t delay); \ No newline at end of file diff --git a/Firmware/Drivers/Inc/MotorSafeBits.h b/Firmware/Drivers/Inc/MotorSafeBits.h index 19c32557..716f3650 100644 --- a/Firmware/Drivers/Inc/MotorSafeBits.h +++ b/Firmware/Drivers/Inc/MotorSafeBits.h @@ -21,7 +21,7 @@ typedef enum { MOTOR_CONTACTOR_ENABLED = 3, // The Motor contactor is enabled MOTOR_PRECHARGE_CONTACTOR_ENABLED = 4, // The Motor precharge Contactor is enabled DASHBOARD_IGNITION_MOTOR = 5, // Ignition switch is set to motor - NUM_MOTOR_STATUS_BITS = 6 + NUM_MOTOR_STATUS_BITS } motor_status_bit_t; _Static_assert(NUM_MOTOR_STATUS_BITS <= MAX_MOTOR_SAFE_BITS, @@ -30,7 +30,7 @@ _Static_assert(NUM_MOTOR_STATUS_BITS <= MAX_MOTOR_SAFE_BITS, /* Convert enum to bitmask */ #define MOTOR_STATUS_BIT(motorBit) (1UL << (motorBit)) -BaseType_t MotorSafeBits_Init(); +bool MotorSafeBits_Init(); EventBits_t MotorSafeBits_WaitMask(EventBits_t bitsToWait, TickType_t delay_ticks); diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index ece0e0ae..7c931342 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -2,6 +2,9 @@ #include "BPSCAN_can_msgs.h" #include "CarCAN_can_msgs.h" #include "MotorCAN_can_msgs.h" +#include +#include + #define FDCAN_NVIC_PRIO configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 5 @@ -56,7 +59,7 @@ can_status_t MotorCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickTy return can_fd_send(motorfdcan, header, data, delay_ticks); } -can_status_t MotorCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], +can_status_t MotorCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { return can_fd_recv(motorfdcan, id, header, data, delay_ticks); } @@ -81,11 +84,10 @@ can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay) { if (out == NULL) return CAN_EMPTY; FDCAN_RxHeaderTypeDef header = {0}; - header. uint8_t moco_status_rx_data[CAN_DLC_MC_VELOCITYMEASUREMENT] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, motor_vel_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, moco_status_rx_data, delay); if (result == CAN_OK) { out->MC_LIMIT_OutputVoltagePWM = (moco_status_rx_data[0] >> 0) & 0x1; @@ -114,21 +116,39 @@ can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay) { out->MC_TxErrorCount = moco_status_rx_data[6]; out->MC_RxErrorCount = moco_status_rx_data[7]; } + return result; } -can_status_t MotorCAN_Send_Drive_Cmd(mc_drivecommand_t *out, TickType_t delay) { -} -void send_motor_drive_cmd(float velocity, float current) { - uint8_t data[8] = {0}; +can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay) { + if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; + + FDCAN_TxHeaderTypeDef header = { + .Identifier = CAN_ID_MC_DRIVECOMMAND, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .BitRateSwitch = FDCAN_BRS_OFF, + .FDFormat = FDCAN_CLASSIC_CAN, + .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, + .MessageMarker = 0, + }; + + uint8_t moco_drive_tx_data[CAN_DLC_MC_DRIVECOMMAND] = {0}; - memcpy(&data[0], &velocity, sizeof(float)); - memcpy(&data[4], ¤t, sizeof(float)); + memcpy(&moco_drive_tx_data[0], &velocity, sizeof(float)); + memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); - vcucan_send(CAN_ID_MC_DRIVECOMMAND, data, 8); + can_status_t result = + can_fd_recv(motorfdcan, CAN_ID_MC_DRIVECOMMAND, &header, moco_drive_tx_data, delay); + + return result; } + + ///////// Carcan can_status_t CarCAN_Init(void) { @@ -178,7 +198,7 @@ can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType return can_fd_send(carfdcan, header, data, delay_ticks); } -can_status_t CarCAN_Recv(uint16_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], +can_status_t CarCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { return can_fd_recv(carfdcan, id, header, data, delay_ticks); } @@ -209,7 +229,131 @@ can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { return result; } -can_status_t CarCAN_Recv_LWS(lws_standard_t) +can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t controls_status_rx_data[CAN_DLC_CONTROLS_STATUS] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_CONTROLS_STATUS, &header, controls_status_rx_data, delay); + + if (result == CAN_OK) { + out->Controls_Leader_Fault = controls_status_rx_data[0]; + out->Controls_Lighting_Fault = (uint16_t) (controls_status_rx_data[1]); + } + + return result; +} + +can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t steering_angle_rx_data[CAN_DLC_LWS_STANDARD] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_LWS_STANDARD, &header, steering_angle_rx_data, delay); + + if (result == CAN_OK) { + // Angle: Byte0 (LSB), Byte1 (MSB) + out->LWS_Angle = (int16_t)( + (steering_angle_rx_data[1] << 8) | + steering_angle_rx_data[0]); + + // Speed: Byte2 + out->LWS_Speed = steering_angle_rx_data[2]; + + // Status bits: Byte3 + out->LWS_OK = (steering_angle_rx_data[3] >> 0) & 0x01; + out->LWS_CAL = (steering_angle_rx_data[3] >> 1) & 0x01; + out->LWS_TRIM = (steering_angle_rx_data[3] >> 2) & 0x01; + } + + return result; +} + +can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t driver_input_rx_data[CAN_DLC_DRIVER_INPUT_STATUS] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_DRIVER_INPUT_STATUS, &header, driver_input_rx_data, delay); + + if (result == CAN_OK) { + out->Ignition_Array = driver_input_rx_data[0] & (0x01); + out->Ignition_Motor = driver_input_rx_data[0] & (0x01 << 1); + out->Ignition_Off = driver_input_rx_data[0] & (0x01 << 2); + out->Cruise_Enable = driver_input_rx_data[0] & (0x01 << 3); + out->Cruise_Set = driver_input_rx_data[0] & (0x01 << 4); + out->Gear_Forward = driver_input_rx_data[0] & (0x01 << 5); + out->Gear_Neutral = driver_input_rx_data[0] & (0x01 << 6); + out->Gear_Reverse = driver_input_rx_data[0] & (0x01 << 7); + + out->Hazard_Pressed = driver_input_rx_data[1] & (0x01); + out->Horn_Pressed = driver_input_rx_data[1] & (0x01 << 1); + out->Blinker_Left = driver_input_rx_data[1] & (0x01 << 2); + out->Blinker_Right = driver_input_rx_data[1] & (0x01 << 3); + out->PushToTalk_Pressed = driver_input_rx_data[1] & (0x01 << 4); + out->Regen_Activate = driver_input_rx_data[1] & (0x01 << 5); + out->Regen_Enable = driver_input_rx_data[1] & (0x01 << 6); + } + + return result; +} + +can_status_t CarCAN_Recv_Pedals_Position(accel_brake_position_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t pedals_pos_rx_data[CAN_ID_ACCEL_BRAKE_POSITION] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_ACCEL_BRAKE_POSITION, &header, driver_input_rx_data, delay); + + if (result == CAN_OK) { + out->Accel_Pos_Main = driver_input_rx_data[0]; + out->Accel_Pos_Redundant = driver_input_rx_data[1]; + out->Brake_Pos_Main = driver_input_rx_data[2]; + out->Brake_Pos_Redundant = driver_input_rx_data[3]; + out->Accel_Pos_Main_Fault = driver_input_rx_data[4] & (0x01); + out->Accel_Pos_Redundant_Fault = driver_input_rx_data[4] & (0x01 << 1); + out->Brake_Pos_Main_Fault = driver_input_rx_data[4] & (0x01 << 2); + out->Brake_Pos_Redundant_Fault = driver_input_rx_data[4] & (0x01 << 3); + } + + return result; +} + + +CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { + if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; + + FDCAN_TxHeaderTypeDef header = { + .Identifier = CAN_ID_MC_VELOCITYMEASUREMENT, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .BitRateSwitch = FDCAN_BRS_OFF, + .FDFormat = FDCAN_CLASSIC_CAN, + .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, + .MessageMarker = 0, + }; + + uint8_t moco_drive_tx_data[CAN_DLC_MC_VELOCITYMEASUREMENT] = {0}; + + memcpy(&moco_drive_tx_data[0], &velocity, sizeof(float)); + memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); + + can_status_t result = + can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, motor_vel_rx_data, delay); + + return result; +} + //////// HAL bs diff --git a/Firmware/Drivers/Src/MotorSafeBits.c b/Firmware/Drivers/Src/MotorSafeBits.c index 6dd57809..8d6bb2a9 100644 --- a/Firmware/Drivers/Src/MotorSafeBits.c +++ b/Firmware/Drivers/Src/MotorSafeBits.c @@ -3,12 +3,12 @@ EventGroupHandle_t motorSafeBits; StaticEventGroup_t motorSafeBitsBuffer; -BaseType_t MotorSafeBits_Init() { +bool MotorSafeBits_Init() { motorSafeBits = xEventGroupCreateStatic(&motorSafeBitsBuffer); if (motorSafeBits == NULL) { - return pdFALSE; + return false; } - return pdTRUE; + return true; } void set_MotorSafeBit(motor_status_bit_t bit) { diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index f96a561e..070e4906 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit f96a561e3c16666dcf02c1ea90400dd13bd49602 +Subproject commit 070e490631959c2e2121ae898cb9ec636ebf24d3 diff --git a/Firmware/Tasks/Inc/FSM.h b/Firmware/Tasks/Inc/FSM.h index 26f6631b..6d65f4b8 100644 --- a/Firmware/Tasks/Inc/FSM.h +++ b/Firmware/Tasks/Inc/FSM.h @@ -12,6 +12,8 @@ #pragma once #include "inits.h" +#include "CANbus.h" +#include "event_groups.h" // make sure if you change this to also change it in scripts/fsm_generator.py #define BITFIELD_INPUT_LIST(X) \ @@ -43,8 +45,8 @@ typedef enum { #undef X } InputBits_t; -#define NEXT_STATES_LENGTH (1U << BITFIELD_INPUT_COUNT) -#define ALL_INPUT_BITS ((1U << BITFIELD_INPUT_COUNT) - 1U) +#define NEXT_STATES_LENGTH (1U << BITFIELD_INPUT_COUNT) +#define FSM_INPUTS_MASK_ALL ((1U << BITFIELD_INPUT_COUNT) - 1U) // must match in the generator script typedef enum { @@ -68,11 +70,28 @@ typedef struct { extern MocoState_t FSM[NUM_STATES]; extern MocoState_t currentState; +typedef struct { + driver_input_status_t driver_input; + accel_brake_position_t accel_brake; + lws_standard_t lws; + controls_status_t controls_status; + mc_status_t motor_status; + bps_status_t bps_status; + mc_velocitymeasurement_t motor_velocity; +} FSMDataIn_t; + +extern FSMDataIn_t *g_data_read; +extern FSMDataIn_t *g_data_write; + + + void fsm_init(void); void fsm_step(void); void fsm_disable(void); void fsm_recover(void); -void fsm_set_precharge_complete(bool val); + +void fsm_set_all_inputs(EventBits_t mask); +void fsm_set_input(EventBits_t mask); uint16_t fsm_get_car_status(void); bool fsm_is_over_rollover_speed(void); diff --git a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h new file mode 100644 index 00000000..71efb0c5 --- /dev/null +++ b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h @@ -0,0 +1,8 @@ +#pragma once + +#include "inits.h" +#include "CANbus.h" +#include "FSM.h" + + +void Task_UpdateFSMInputs(); diff --git a/Firmware/Tasks/Src/FSM.c b/Firmware/Tasks/Src/FSM.c index 6b56a61c..57dc81f6 100644 --- a/Firmware/Tasks/Src/FSM.c +++ b/Firmware/Tasks/Src/FSM.c @@ -21,24 +21,31 @@ #define BRAKE_THRESH 42.0f // percent #define BRAKE_THRESH_HYST 30.0f // percent -EventBits_t fsm_inputsbits; +StaticEventGroup_t fsmInputBuffer = {0}; +EventGroupHandle_t fsmInputGroup = {0}; -MocoState_t currentState; +MocoState_t current_state = {0}; -static driver_input_status_t driver_input = {0}; -static accel_brake_position_t accel_brake = {0}; -static lws_standard_t lws = {0}; -static controls_status_t controls_status = {0}; -static mc_status_t motor_status = {0}; -static bps_status_t bps_status = {0}; -static mc_velocitymeasurement_t motor_velocity = {0}; +static FSMDataIn_t fsm_input_read = {0}; +static FSMDataIn_t fsm_input_write = {0}; -static float accel_pedal_pct = 0.0f; -static float brake_pedal_pct = 0.0f; +FSMDataIn_t *g_data_read = &fsm_input_read; +FSMDataIn_t *g_data_write = &fsm_input_write; + +// static driver_input_status_t driver_input = {0}; +// static accel_brake_position_t accel_brake = {0}; +// static lws_standard_t lws = {0}; +// static controls_status_t controls_status = {0}; +// static mc_status_t motor_status = {0}; +// static bps_status_t bps_status = {0}; +// static mc_velocitymeasurement_t motor_velocity = {0}; + +// static float accel_pedal_pct = 0.0f; +// static float brake_pedal_pct = 0.0f; static float brake_threshold = BRAKE_THRESH; -static bool precharge_complete = false; +// static bool precharge_complete = false; static bool rollover_limit_active = false; -static volatile uint16_t car_status = 0; +static volatile uint16_t fsm_inputs = 0; // method stubs so linker doesnt shit itself static void handle_state_init(void); @@ -64,61 +71,58 @@ void fsm_init(void) { FSM[DISABLED].stateHandler = handle_state_disabled; FSM[CAR_NOT_READY].stateHandler = handle_state_not_ready; - currentState = FSM[STATE_INIT]; - currentState.stateHandler(); + current_state = FSM[STATE_INIT]; + current_state.stateHandler(); } void fsm_step(void) { - - currentState = FSM[currentState.NextStates[car_status]]; - if (currentState.stateHandler) currentState.stateHandler(); + fsm_inputs = xEventGroupGetBits(fsmInputGroup); + current_state = FSM[current_state.NextStates[fsm_inputs]]; + if (current_state.stateHandler) current_state.stateHandler(); } -void fsm_disable(void) { currentState = FSM[DISABLED]; } -void fsm_recover(void) { currentState = FSM[CAR_NOT_READY]; } -void fsm_set_precharge_complete(bool val) { precharge_complete = val; } -uint16_t fsm_get_car_status(void) { return (uint16_t)car_status; } +void fsm_disable(void) { current_state = FSM[DISABLED]; } +void fsm_recover(void) { current_state = FSM[CAR_NOT_READY]; } +uint16_t fsm_get_fsm_inputs(void) { return (uint16_t)fsm_inputs; } bool fsm_is_over_rollover_speed(void) { return rollover_limit_active; } -static void update_from_can(void) { - - carcan_try_recv(CAN_ID_DRIVER_INPUT_STATUS, handle_driver_input, &driver_input); - carcan_try_recv(CAN_ID_ACCEL_BRAKE_POSITION, handle_accel_brake, &accel_brake); - carcan_try_recv(CAN_ID_LWS_STANDARD, handle_lws, &lws); - carcan_try_recv(CAN_ID_CONTROLS_STATUS, handle_controls_status, &controls_status); - carcan_try_recv(CAN_ID_BPS_STATUS, handle_bps, &bps_status); - vcucan_try_recv(CAN_ID_MC_VELOCITYMEASUREMENT, handle_motor_velocity, &motor_velocity); - vcucan_try_recv(CAN_ID_MC_STATUS, handle_motor_status, &motor_status); +void fsm_set_all_inputs(EventBits_t mask) { + xEventGroupClearBits(fsmInputGroup, FSM_INPUTS_MASK_ALL); + xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); +} + +void fsm_set_input(EventBits_t mask) { + xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); } -static void rebuild_bitfield(void) { - uint16_t s = 0; +// static void rebuild_bitfield(void) { +// uint16_t s = 0; - if (driver_input.Gear_Forward) - s |= FORWARD_BIT; - else if (driver_input.Gear_Reverse) - s |= REVERSE_BIT; - else - s |= NEUTRAL_BIT; +// if (driver_input.Gear_Forward) +// s |= FORWARD_BIT; +// else if (driver_input.Gear_Reverse) +// s |= REVERSE_BIT; +// else +// s |= NEUTRAL_BIT; - if (driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; - if (driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; - if (driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; - if (bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; - if (precharge_complete) s |= PRECHARGE_COMPLETE_BIT; +// if (driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; +// if (driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; +// if (driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; +// if (bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; +// if (precharge_complete) s |= PRECHARGE_COMPLETE_BIT; - accel_pedal_pct = accel_brake.Accel_Pos_Main; - brake_pedal_pct = accel_brake.Brake_Pos_Main; +// accel_pedal_pct = accel_brake.Accel_Pos_Main; +// brake_pedal_pct = accel_brake.Brake_Pos_Main; - if (brake_pedal_pct >= brake_threshold) { - s |= BRAKE_BIT; - brake_threshold = BRAKE_THRESH_HYST; - } else { - brake_threshold = BRAKE_THRESH; - } +// if (brake_pedal_pct >= brake_threshold) { +// s |= BRAKE_BIT; +// brake_threshold = BRAKE_THRESH_HYST; +// } else { +// brake_threshold = BRAKE_THRESH; +// } - car_status = s; -} +// car_status = s; +// } // goofy ahh logic, uses lut static float apply_rollover_limit(float requested_current) { @@ -148,7 +152,7 @@ float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_ //// state handlers -static void handle_state_init(void) { currentState = FSM[CAR_NOT_READY]; } +static void handle_state_init(void) { current_state = FSM[CAR_NOT_READY]; } static void handle_state_neutral(void) { send_motor_drive_cmd(0.0f, 0.0f); } static void handle_state_disabled(void) { send_motor_drive_cmd(0.0f, 0.0f); } static void handle_state_regen(void) { send_motor_drive_cmd(0.0f, 1.0f); } @@ -235,10 +239,10 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { ((uint8_t)driver_input_ok << 3) | // VCU_Driver_Input_OK ((uint8_t)pedals_ok << 4) | // VCU_Pedals_OK ((uint8_t)!!(car_status & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK - ((uint8_t)(currentState.stateName == REGEN) << 6); // VCU_Regen_Active + ((uint8_t)(current_state.stateName == REGEN) << 6); // VCU_Regen_Active // Byte 2: VCU_FSM_State bits [3:0] - buf[2] = (uint8_t)(currentState.stateName & 0x0FU); + buf[2] = (uint8_t)(current_state.stateName & 0x0FU); carcan_send(CAN_ID_VCU_STATUS, buf, sizeof(buf)); vTaskDelay(pdMS_TO_TICKS(100)); diff --git a/Firmware/Tasks/Src/UpdateFSMInputsTask.c b/Firmware/Tasks/Src/UpdateFSMInputsTask.c new file mode 100644 index 00000000..ec223ce1 --- /dev/null +++ b/Firmware/Tasks/Src/UpdateFSMInputsTask.c @@ -0,0 +1,149 @@ +#include "UpdateFSMInputsTask.h" +#include "event_groups.h" + +static void rebuild_inputs(void) { + EventBits_t s = 0; + + if (driver_input.Gear_Forward) + s |= FORWARD_BIT; + else if (driver_input.Gear_Reverse) + s |= REVERSE_BIT; + else + s |= NEUTRAL_BIT; + + if (driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; + if (driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; + if (driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; + if (bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; + if (precharge_complete) s |= PRECHARGE_COMPLETE_BIT; + + + + if (brake_pedal_pct >= brake_threshold) { + s |= BRAKE_BIT; + brake_threshold = BRAKE_THRESH_HYST; + } else { + brake_threshold = BRAKE_THRESH; + } + + fsm_set_all_inputs(s); +} + +void Task_UpdateControlStatus(void *args __attribute__((unused))) { + TickType_t last = xTaskGetTickCount(); + while (1) { + // update from can + FSMDataIn_t *update = g_data_write; + MotorCAN_Recv_Status(&update->motor_status, 0); + MotorCAN_Recv_Velocity(&update->motor_velocity, 0); + CarCAN_Recv_BPS_Status(&update->bps_status, 0); + CarCAN_Recv_Pedals_Position(&update->accel_brake, 0); + CarCAN_Recv_Controls_Status(&update->controls_status, 0); + CarCAN_Recv_Driver_Input(&update->driver_input, 0); + CarCAN_Recv_LWS(&update->lws, 0); + + FSMDataIn_t *tmp; + taskENTER_CRITICAL(); + tmp = g_data_read; + g_data_read = g_data_write; + g_data_write = tmp; + taskEXIT_CRITICAL(); + + rebuild_inputs(&); + vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); + } +} + +void Task_UpdateInputs(void *args) +{ + TickType_t last = xTaskGetTickCount(); + + while (1) + { + fsm_inputs_t* w = (fsm_inputs_t*)write_ptr; + + // ---- CAN updates ---- + carcan_try_recv(CAN_ID_DRIVER_INPUT_STATUS, handle_driver_input, &w->driver_input); + carcan_try_recv(CAN_ID_ACCEL_BRAKE_POSITION, handle_accel_brake, &w->accel_brake); + carcan_try_recv(CAN_ID_LWS_STANDARD, handle_lws, &w->lws); + carcan_try_recv(CAN_ID_CONTROLS_STATUS, handle_controls_status, &w->controls_status); + carcan_try_recv(CAN_ID_BPS_STATUS, handle_bps, &w->bps_status); + vcucan_try_recv(CAN_ID_MC_VELOCITYMEASUREMENT, handle_motor_velocity, &w->motor_velocity); + vcucan_try_recv(CAN_ID_MC_STATUS, handle_motor_status, &w->motor_status); + + // ---- Build event bits (level-triggered) ---- + EventBits_t set = 0; + EventBits_t clr = 0; + + // 🚗 Gear (mutually exclusive) + clr |= (FORWARD_BIT | REVERSE_BIT | NEUTRAL_BIT); + if (w->driver_input.Gear_Forward) set |= FORWARD_BIT; + else if (w->driver_input.Gear_Reverse) set |= REVERSE_BIT; + else set |= NEUTRAL_BIT; + + // 🎮 Buttons + if (w->driver_input.Regen_Activate) set |= REGEN_BUTTON_BIT; + else clr |= REGEN_BUTTON_BIT; + + if (w->driver_input.Regen_Enable) set |= REGEN_ENABLED_BIT; + else clr |= REGEN_ENABLED_BIT; + + if (w->driver_input.Cruise_Enable) set |= CRUISE_CONTROL_BUTTON_BIT; + else clr |= CRUISE_CONTROL_BUTTON_BIT; + + // 🔋 System + if (w->bps_status.BPS_Regen_OK) set |= READY_TO_REGEN_BIT; + else clr |= READY_TO_REGEN_BIT; + + if (precharge_complete) set |= PRECHARGE_COMPLETE_BIT; + else clr |= PRECHARGE_COMPLETE_BIT; + + // 🦶 Brake (with hysteresis) + float brake = w->accel_brake.Brake_Pos_Main; + + if (brake >= brake_threshold) { + set |= BRAKE_BIT; + brake_threshold = BRAKE_THRESH_HYST; + } else { + clr |= BRAKE_BIT; + brake_threshold = BRAKE_THRESH; + } + + // 🛡 Pedals OK + bool pedals_ok = + !w->accel_brake.Accel_Pos_Main_Fault && + !w->accel_brake.Accel_Pos_Redundant_Fault && + !w->accel_brake.Brake_Pos_Main_Fault && + !w->accel_brake.Brake_Pos_Redundant_Fault && + !w->accel_brake.Brake_Pressure_1_Fault && + !w->accel_brake.Brake_Pressure_2_Fault; + + if (pedals_ok) set |= PEDALS_OK_BIT; + else clr |= PEDALS_OK_BIT; + + // 🎛 Driver input OK + bool driver_ok = + !faults_is_active(FAULT_ID_CONTROLS_STATUS_WATCHDOG) && + !faults_is_active(FAULT_ID_CONTROLS_FAULT); + + if (driver_ok) set |= DRIVER_INPUT_OK_BIT; + else clr |= DRIVER_INPUT_OK_BIT; + + // ⚠️ Faults + if (faults_any_active()) set |= FAULT_ACTIVE_BIT; + else clr |= FAULT_ACTIVE_BIT; + + // ---- Apply bits atomically-ish ---- + xEventGroupClearBits(fsm_event_group, clr); + xEventGroupSetBits(fsm_event_group, set); + + // ---- Swap buffers ---- + taskENTER_CRITICAL(); + fsm_inputs_t* tmp = (fsm_inputs_t*)read_ptr; + read_ptr = write_ptr; + write_ptr = tmp; + taskEXIT_CRITICAL(); + + vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); + } +} \ No newline at end of file diff --git a/Firmware/tests/canbus_test.c b/Firmware/tests/canbus_test.c index de1a8ec6..2151bef6 100644 --- a/Firmware/tests/canbus_test.c +++ b/Firmware/tests/canbus_test.c @@ -1,3 +1,12 @@ +/** + * canbus test!! + * + * Sends and receives as 2 different tasks. + * For rx: send data from candapter at ID 0x123 to see an led blink + * For tx: use candapter to see if 123456789ABCDEFF is being received at 0x321 + * + */ + #include "CANbus.h" #include "StatusLEDs.h" #include "inits.h" @@ -7,13 +16,33 @@ StaticTask_t task_buffer; StackType_t task_stack[512]; -#define TEST_CAN_ID 0x321 -#define TEST_CAN_DATA {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF} +#define TEST_CAN_ID_RX 0x123 +#define TEST_CAN_ID_TX 0x321 +#define TEST_CAN_DATA_TX {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF} #define TEST_CAN_DATA_LENGTH 8 -static void task(void *pvParameters) { +void can_error_handler() { + while (1) { + LED_set(MOTOR_FAULT, LED_ON); + } +} + +static void rx_task(void *pvParameters) { + FDCAN_RxHeaderTypeDef rx_header = {0}; + uint8_t rx_data[TEST_CAN_DATA_LENGTH] = {0}; + while (1) { + if (MotorCAN_Recv(TEST_CAN_ID_RX, &rx_header, rx_data, portMAX_DELAY) == CAN_ERR) { + can_error_handler(); + } + + LED_toggle(PRECHARGE_COMPLETE); + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +static void tx_task(void *pvParameters) { FDCAN_TxHeaderTypeDef tx_header = {0}; - tx_header.Identifier = TEST_CAN_ID; + tx_header.Identifier = TEST_CAN_ID_TX; tx_header.IdType = FDCAN_STANDARD_ID; tx_header.TxFrameType = FDCAN_DATA_FRAME; tx_header.DataLength = FDCAN_DLC_BYTES_8; @@ -23,20 +52,14 @@ static void task(void *pvParameters) { tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; tx_header.MessageMarker = 0; - uint8_t tx_data[TEST_CAN_DATA_LENGTH] = TEST_CAN_DATA; + uint8_t tx_data[TEST_CAN_DATA_LENGTH] = TEST_CAN_DATA_TX; while (1) { - if (MotorCAN_Send(&tx_header, tx_data, portMAX_DELAY) != CAN_OK) { - Error_Handler(); + if (MotorCAN_Send(&tx_header, tx_data, portMAX_DELAY) == CAN_ERR) { + can_error_handler(); } - - HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); - vTaskDelay(pdMS_TO_TICKS(1000)); - } -} -void can_error_handler() { - while (1) { - LED_set(MOTOR_FAULT, LED_ON); + LED_toggle(HB); + vTaskDelay(pdMS_TO_TICKS(1000)); } } @@ -53,7 +76,8 @@ int main() { can_error_handler(); } - xTaskCreateStatic(task, "task", 512, NULL, tskIDLE_PRIORITY + 2, task_stack, &task_buffer); + xTaskCreateStatic(tx_task, "tx_task", 512, NULL, tskIDLE_PRIORITY + 2, task_stack, &task_buffer); + xTaskCreateStatic(rx_task, "rx_task", 512, NULL, tskIDLE_PRIORITY + 1, task_stack, &task_buffer); vTaskStartScheduler(); From 2960d7a21c23b20f825c386720282cccfd815c1b Mon Sep 17 00:00:00 2001 From: Akshay Date: Mon, 6 Apr 2026 01:19:11 -0500 Subject: [PATCH 04/27] building --- Firmware/Drivers/Inc/CANbus.h | 3 +- Firmware/Drivers/Inc/Contactors.h | 2 +- Firmware/Drivers/Inc/Watchdogs.h | 13 +- Firmware/Drivers/Src/CANbus.c | 49 +- Firmware/Drivers/Src/Watchdogs.c | 15 +- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSM.h | 4 +- Firmware/Tasks/Inc/UpdateFSMInputsTask.h | 2 + Firmware/Tasks/Inc/VCUStatusTask.h | 6 + Firmware/Tasks/Src/CanTxTelemetryTask.c | 69 -- Firmware/Tasks/Src/FSM.c | 250 ----- Firmware/Tasks/Src/FSMTask.c | 157 +++ Firmware/Tasks/Src/InitTask.c | 119 ++- Firmware/Tasks/Src/MotorControlTask.c | 123 --- Firmware/Tasks/Src/ReadMotorCAN.c | 29 - Firmware/Tasks/Src/UpdateFSMInputsTask.c | 118 +-- Firmware/Tasks/Src/VCUStatusTask.c | 76 ++ Firmware/config/Inc/BPSCAN_can_msgs.h | 268 +++-- Firmware/config/Inc/CarCAN_can_msgs.h | 1051 ++++++++++++++++---- Firmware/config/Inc/MotorCAN_can_msgs.h | 104 +- Firmware/config/Inc/SteeringCAN_can_msgs.h | 55 + 21 files changed, 1576 insertions(+), 939 deletions(-) create mode 100644 Firmware/Tasks/Inc/VCUStatusTask.h delete mode 100644 Firmware/Tasks/Src/CanTxTelemetryTask.c delete mode 100644 Firmware/Tasks/Src/FSM.c create mode 100644 Firmware/Tasks/Src/FSMTask.c delete mode 100644 Firmware/Tasks/Src/MotorControlTask.c delete mode 100644 Firmware/Tasks/Src/ReadMotorCAN.c create mode 100644 Firmware/Tasks/Src/VCUStatusTask.c create mode 100644 Firmware/config/Inc/SteeringCAN_can_msgs.h diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index 338a4b26..ab198e69 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -5,6 +5,7 @@ #include "MotorCAN_can_msgs.h" #include "BPSCAN_can_msgs.h" #include "CarCAN_can_msgs.h" +#include "SteeringCAN_can_msgs.h" extern FDCAN_HandleTypeDef *motorfdcan; extern FDCAN_HandleTypeDef *carfdcan; @@ -27,5 +28,5 @@ can_status_t CarCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t dat can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay); can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t delay); -can_status_t CarCAN_Recv_Pedals_Position(accel_brake_position_t *out, TickType_t delay); +can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t delay); \ No newline at end of file diff --git a/Firmware/Drivers/Inc/Contactors.h b/Firmware/Drivers/Inc/Contactors.h index ce155af9..b90084a9 100644 --- a/Firmware/Drivers/Inc/Contactors.h +++ b/Firmware/Drivers/Inc/Contactors.h @@ -1,4 +1,4 @@ -#pragma once + #pragma once #include "inits.h" diff --git a/Firmware/Drivers/Inc/Watchdogs.h b/Firmware/Drivers/Inc/Watchdogs.h index e73dfa55..e56625f2 100644 --- a/Firmware/Drivers/Inc/Watchdogs.h +++ b/Firmware/Drivers/Inc/Watchdogs.h @@ -50,7 +50,7 @@ WATCHDOG_LIST(X) /** - * @brief Initialize the watchdog system. This must be called before creating + * @brief Initialize all watchdogs. This must be called before using * any watchdog timers. */ void watchdog_init(void); @@ -103,14 +103,3 @@ bool watchdog_is_alive(int idx); * iterating over all timers or for debugging. */ uint8_t watchdog_count(void); - -/** - * @brief Helper macro to initialize all watchdogs defined in WATCHDOG_LIST with one call - */ -#define WATCHDOG_INIT_ALL_FSM_SIGNALS() \ - do { \ - WATCHDOG_LIST(WATCHDOG_CREATE_ONE_); \ - } while (0); - -#define WATCHDOG_CREATE_ONE_(name, str, timeout, fault) \ - watchdog_create(str, WD_IDX_##name, timeout, fault); diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 7c931342..2956b901 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -128,7 +128,7 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d .Identifier = CAN_ID_MC_DRIVECOMMAND, .IdType = FDCAN_STANDARD_ID, .TxFrameType = FDCAN_DATA_FRAME, - .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), + .DataLength = CAN_DLC_MC_DRIVECOMMAND, .ErrorStateIndicator = FDCAN_ESI_ACTIVE, .BitRateSwitch = FDCAN_BRS_OFF, .FDFormat = FDCAN_CLASSIC_CAN, @@ -142,7 +142,7 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_MC_DRIVECOMMAND, &header, moco_drive_tx_data, delay); + can_fd_send(motorfdcan, &header, moco_drive_tx_data, delay); return result; } @@ -240,7 +240,7 @@ can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t dela if (result == CAN_OK) { out->Controls_Leader_Fault = controls_status_rx_data[0]; - out->Controls_Lighting_Fault = (uint16_t) (controls_status_rx_data[1]); + // out->Controls_Lighting_Fault = (uint16_t) (controls_status_rx_data[1]); } return result; @@ -265,9 +265,9 @@ can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay) { out->LWS_Speed = steering_angle_rx_data[2]; // Status bits: Byte3 - out->LWS_OK = (steering_angle_rx_data[3] >> 0) & 0x01; - out->LWS_CAL = (steering_angle_rx_data[3] >> 1) & 0x01; - out->LWS_TRIM = (steering_angle_rx_data[3] >> 2) & 0x01; + out->LWS_Fault = (steering_angle_rx_data[3] >> 0) & 0x01; + out->LWS_CalibrationStaus = (steering_angle_rx_data[3] >> 1) & 0x01; + out->LWS_Trimming_Status = (steering_angle_rx_data[3] >> 2) & 0x01; } return result; @@ -304,38 +304,38 @@ can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t del return result; } -can_status_t CarCAN_Recv_Pedals_Position(accel_brake_position_t *out, TickType_t delay) { +can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) { if (out == NULL) return CAN_EMPTY; FDCAN_RxHeaderTypeDef header = {0}; - uint8_t pedals_pos_rx_data[CAN_ID_ACCEL_BRAKE_POSITION] = {0}; + uint8_t pedals_pos_rx_data[CAN_DLC_PEDAL_STATUS] = {0}; can_status_t result = - can_fd_recv(carfdcan, CAN_ID_ACCEL_BRAKE_POSITION, &header, driver_input_rx_data, delay); + can_fd_recv(carfdcan, CAN_ID_PEDAL_STATUS, &header, pedals_pos_rx_data, delay); if (result == CAN_OK) { - out->Accel_Pos_Main = driver_input_rx_data[0]; - out->Accel_Pos_Redundant = driver_input_rx_data[1]; - out->Brake_Pos_Main = driver_input_rx_data[2]; - out->Brake_Pos_Redundant = driver_input_rx_data[3]; - out->Accel_Pos_Main_Fault = driver_input_rx_data[4] & (0x01); - out->Accel_Pos_Redundant_Fault = driver_input_rx_data[4] & (0x01 << 1); - out->Brake_Pos_Main_Fault = driver_input_rx_data[4] & (0x01 << 2); - out->Brake_Pos_Redundant_Fault = driver_input_rx_data[4] & (0x01 << 3); + out->AccelPedal_Main_Pos = pedals_pos_rx_data[0]; + out->AccelPedal_Redundant_Pos = pedals_pos_rx_data[1]; + out->BrakePedal_Main_Pos = pedals_pos_rx_data[2]; + out->BrakePedal_Redundant_Pos = pedals_pos_rx_data[3]; + out->AccelPedal_Main_Fault = pedals_pos_rx_data[4] & (0x01); + out->AccelPedal_Redundant_Fault = pedals_pos_rx_data[4] & (0x01 << 1); + out->BrakePedal_Main_Fault = pedals_pos_rx_data[4] & (0x01 << 2); + out->BrakePedal_Redundant_Fault = pedals_pos_rx_data[4] & (0x01 << 3); } return result; } -CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { - if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; +can_status_t CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; FDCAN_TxHeaderTypeDef header = { - .Identifier = CAN_ID_MC_VELOCITYMEASUREMENT, + .Identifier = CAN_ID_VCU_STATUS, .IdType = FDCAN_STANDARD_ID, .TxFrameType = FDCAN_DATA_FRAME, - .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), + .DataLength = CAN_DLC_VCU_STATUS, .ErrorStateIndicator = FDCAN_ESI_ACTIVE, .BitRateSwitch = FDCAN_BRS_OFF, .FDFormat = FDCAN_CLASSIC_CAN, @@ -343,13 +343,12 @@ CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { .MessageMarker = 0, }; - uint8_t moco_drive_tx_data[CAN_DLC_MC_VELOCITYMEASUREMENT] = {0}; + uint8_t vcu_status_tx_data[CAN_DLC_VCU_STATUS] = {0}; - memcpy(&moco_drive_tx_data[0], &velocity, sizeof(float)); - memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); + // TODO: actually pack ts can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, motor_vel_rx_data, delay); + can_fd_send(carfdcan, &header, vcu_status_tx_data, delay); return result; } diff --git a/Firmware/Drivers/Src/Watchdogs.c b/Firmware/Drivers/Src/Watchdogs.c index fd2c91b2..627a0c12 100644 --- a/Firmware/Drivers/Src/Watchdogs.c +++ b/Firmware/Drivers/Src/Watchdogs.c @@ -9,10 +9,10 @@ #include #include -static StaticTimer_t wd_buffers[MAX_WD_TIMERS]; -static TimerHandle_t wd_timers[MAX_WD_TIMERS]; -static bool wd_alive[MAX_WD_TIMERS]; -static FaultID_e wd_fault_ids[MAX_WD_TIMERS]; +static StaticTimer_t wd_buffers[MAX_WD_TIMERS] = {0}; +static TimerHandle_t wd_timers[MAX_WD_TIMERS] = {0}; +static bool wd_alive[MAX_WD_TIMERS] = {0}; +static FaultID_e wd_fault_ids[MAX_WD_TIMERS] = {0}; static uint8_t wd_count = 0; // Callback function for when a watchdog timer expires @@ -24,9 +24,10 @@ static void wd_callback(TimerHandle_t xTimer) { } void watchdog_init(void) { - memset(wd_timers, 0, sizeof(wd_timers)); - memset(wd_alive, 0, sizeof(wd_alive)); - wd_count = 0; +#define X(name, str, timeout, fault) \ + watchdog_create(str, WD_IDX_##name, timeout, fault); + WATCHDOG_LIST(X) +#undef X } void watchdog_create(const char *name, uint8_t idx, uint32_t timeout_ms, FaultID_e fault_id) { diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 070e4906..7a651473 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 070e490631959c2e2121ae898cb9ec636ebf24d3 +Subproject commit 7a651473f1901789600333fb205b034ab7eb03b9 diff --git a/Firmware/Tasks/Inc/FSM.h b/Firmware/Tasks/Inc/FSM.h index 6d65f4b8..131a4b92 100644 --- a/Firmware/Tasks/Inc/FSM.h +++ b/Firmware/Tasks/Inc/FSM.h @@ -72,7 +72,7 @@ extern MocoState_t currentState; typedef struct { driver_input_status_t driver_input; - accel_brake_position_t accel_brake; + pedal_status_t accel_brake; lws_standard_t lws; controls_status_t controls_status; mc_status_t motor_status; @@ -92,8 +92,8 @@ void fsm_recover(void); void fsm_set_all_inputs(EventBits_t mask); void fsm_set_input(EventBits_t mask); +void fsm_get_inputs(void); -uint16_t fsm_get_car_status(void); bool fsm_is_over_rollover_speed(void); void Task_UpdateControlStatus(void *args); diff --git a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h index 71efb0c5..92f7517e 100644 --- a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h +++ b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h @@ -4,5 +4,7 @@ #include "CANbus.h" #include "FSM.h" +#define BRAKE_THRESH 42.0f // percent +#define BRAKE_THRESH_HYST 30.0f // percent void Task_UpdateFSMInputs(); diff --git a/Firmware/Tasks/Inc/VCUStatusTask.h b/Firmware/Tasks/Inc/VCUStatusTask.h new file mode 100644 index 00000000..f04a6f2e --- /dev/null +++ b/Firmware/Tasks/Inc/VCUStatusTask.h @@ -0,0 +1,6 @@ +#pragma once + +#include "inits.h" + + +void Task_BroadcastVCUStatus(void *args __attribute__((unused))); \ No newline at end of file diff --git a/Firmware/Tasks/Src/CanTxTelemetryTask.c b/Firmware/Tasks/Src/CanTxTelemetryTask.c deleted file mode 100644 index 2806a633..00000000 --- a/Firmware/Tasks/Src/CanTxTelemetryTask.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "CanTxTelemetryTask.h" - -#define CAN_TX_TELEMETRY_QUEUE_SIZE 10 - -static StaticQueue_t canTxTelemetryQueueBuffer; -static uint8_t canTxTelemetryQueueStorage[CAN_TX_TELEMETRY_QUEUE_SIZE * sizeof(can_tx_payload_t)]; -static QueueHandle_t canTxTelemetryQueue; - -void can_tx_print_slcan(const can_tx_payload_t payload) { - - uint32_t id = payload.header.Identifier; - uint8_t len = (payload.header.DataLength); - - /* SLCAN supports max 8 bytes */ - if (len > 8) len = 8; - - if (payload.header.IdType == FDCAN_STANDARD_ID) { - /* tIII DLC DATA... */ - printf("t%03lX%1X", id & 0x7FF, len); - } else { - /* TIIIIIIII DLC DATA... */ - printf("T%08lX%1X", id & 0x1FFFFFFF, len); - } - - for (uint8_t i = 0; i < len; i++) { - printf("%02X", payload.data[i]); - } - - printf("\r\n"); -} - -void CanTxTelemetryTask_Init(void) { - canTxTelemetryQueue = - xQueueCreateStatic(CAN_TX_TELEMETRY_QUEUE_SIZE, sizeof(can_tx_payload_t), - canTxTelemetryQueueStorage, &canTxTelemetryQueueBuffer); - - if (canTxTelemetryQueue == NULL) { - return; - } -} - -void can_fd_tx_callback_hook(FDCAN_HandleTypeDef *hfdcan, const can_tx_payload_t *payload) { - - BaseType_t higherPriorityTaskWoken = pdFALSE; - - if (canTxTelemetryQueue != NULL) { - xQueueSendFromISR(canTxTelemetryQueue, payload, &higherPriorityTaskWoken); - } - // don't yield at the end of this since the rest of the ISR needs to run -} - -void Task_CanTxTelemetry() { - - // car canbus MUST be initialized by now - CanTxTelemetryTask_Init(); - - can_tx_payload_t payload; - - while (1) { - // forward all transmitted can messages to USB - if (xQueueReceive(canTxTelemetryQueue, &payload, portMAX_DELAY) == pdTRUE) { - // TODO: use the embedded-sharepoint slcan formatter - can_tx_print_slcan(payload); - // TODO: should also forward data to ESP32 - - taskYIELD(); - } - } -} \ No newline at end of file diff --git a/Firmware/Tasks/Src/FSM.c b/Firmware/Tasks/Src/FSM.c deleted file mode 100644 index 57dc81f6..00000000 --- a/Firmware/Tasks/Src/FSM.c +++ /dev/null @@ -1,250 +0,0 @@ -/** - * @file FSM.c - * @brief Motor controller FSM implementation - * @copyright Copyright (c) 2026 UT Longhorn Racing Solar - */ - -#define DEFINE_FSM_TABLE -#include "fsm_table_dnr.h" - -#include "BPSCAN_can_msgs.h" -#include "CarCAN_can_msgs.h" -#include "FSM.h" -#include "FaultBits.h" -#include "MotorCAN_can_msgs.h" -#include "Watchdogs.h" -#include "rollover_speed_table.h" -#include -#include - -#define MAX_VELOCITY 100.0f // meters per second -#define BRAKE_THRESH 42.0f // percent -#define BRAKE_THRESH_HYST 30.0f // percent - -StaticEventGroup_t fsmInputBuffer = {0}; -EventGroupHandle_t fsmInputGroup = {0}; - -MocoState_t current_state = {0}; - -static FSMDataIn_t fsm_input_read = {0}; -static FSMDataIn_t fsm_input_write = {0}; - -FSMDataIn_t *g_data_read = &fsm_input_read; -FSMDataIn_t *g_data_write = &fsm_input_write; - -// static driver_input_status_t driver_input = {0}; -// static accel_brake_position_t accel_brake = {0}; -// static lws_standard_t lws = {0}; -// static controls_status_t controls_status = {0}; -// static mc_status_t motor_status = {0}; -// static bps_status_t bps_status = {0}; -// static mc_velocitymeasurement_t motor_velocity = {0}; - -// static float accel_pedal_pct = 0.0f; -// static float brake_pedal_pct = 0.0f; -static float brake_threshold = BRAKE_THRESH; -// static bool precharge_complete = false; -static bool rollover_limit_active = false; -static volatile uint16_t fsm_inputs = 0; - -// method stubs so linker doesnt shit itself -static void handle_state_init(void); -static void handle_state_not_ready(void); -static void handle_state_forward(void); -static void handle_state_neutral(void); -static void handle_state_reverse(void); -static void handle_state_regen(void); -static void handle_state_cruise(void); -static void handle_state_disabled(void); - -static void update_from_can(void); -static void rebuild_bitfield(void); -static float apply_rollover_limit(float requested_current); - -void fsm_init(void) { - FSM[STATE_INIT].stateHandler = handle_state_init; - FSM[FORWARD_DRIVE].stateHandler = handle_state_forward; - FSM[NEUTRAL_DRIVE].stateHandler = handle_state_neutral; - FSM[REVERSE_DRIVE].stateHandler = handle_state_reverse; - FSM[REGEN].stateHandler = handle_state_regen; - FSM[CRUISE_CONTROL].stateHandler = handle_state_cruise; - FSM[DISABLED].stateHandler = handle_state_disabled; - FSM[CAR_NOT_READY].stateHandler = handle_state_not_ready; - - current_state = FSM[STATE_INIT]; - current_state.stateHandler(); -} - -void fsm_step(void) { - fsm_inputs = xEventGroupGetBits(fsmInputGroup); - current_state = FSM[current_state.NextStates[fsm_inputs]]; - if (current_state.stateHandler) current_state.stateHandler(); -} - -void fsm_disable(void) { current_state = FSM[DISABLED]; } -void fsm_recover(void) { current_state = FSM[CAR_NOT_READY]; } -uint16_t fsm_get_fsm_inputs(void) { return (uint16_t)fsm_inputs; } -bool fsm_is_over_rollover_speed(void) { return rollover_limit_active; } - -void fsm_set_all_inputs(EventBits_t mask) { - xEventGroupClearBits(fsmInputGroup, FSM_INPUTS_MASK_ALL); - xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); -} - -void fsm_set_input(EventBits_t mask) { - xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); -} - -// static void rebuild_bitfield(void) { -// uint16_t s = 0; - -// if (driver_input.Gear_Forward) -// s |= FORWARD_BIT; -// else if (driver_input.Gear_Reverse) -// s |= REVERSE_BIT; -// else -// s |= NEUTRAL_BIT; - -// if (driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; -// if (driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; -// if (driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; -// if (bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; -// if (precharge_complete) s |= PRECHARGE_COMPLETE_BIT; - -// accel_pedal_pct = accel_brake.Accel_Pos_Main; -// brake_pedal_pct = accel_brake.Brake_Pos_Main; - -// if (brake_pedal_pct >= brake_threshold) { -// s |= BRAKE_BIT; -// brake_threshold = BRAKE_THRESH_HYST; -// } else { -// brake_threshold = BRAKE_THRESH; -// } - -// car_status = s; -// } - -// goofy ahh logic, uses lut -static float apply_rollover_limit(float requested_current) { - int deg = abs((int)lws.LWS_Angle) / 10; - if (deg > (int)ROLLOVER_TABLE_MAX_DEG) deg = (int)ROLLOVER_TABLE_MAX_DEG; - - uint16_t v_max_cms = rollover_speed_table[deg]; - uint16_t v_now_cms = (uint16_t)(motor_velocity.MC_VehicleVelocity * 100.0f); - - if (v_max_cms != ROLLOVER_TABLE_NO_LIMIT && v_now_cms > v_max_cms) { - rollover_limit_active = true; - return 0.0f; - } - rollover_limit_active = false; - return requested_current; -} - -float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, - uint8_t out_max) { - if (in_min >= in_max || input <= in_min) return (float)out_min / 100.0f; - if (input >= in_max) return (float)out_max / 100.0f; - uint16_t oi = input - in_min; - uint16_t ir = in_max - in_min; - uint16_t or_ = out_max - out_min; - return ((float)(oi * or_) / (float)ir + (float)out_min) / 100.0f; -} - -//// state handlers - -static void handle_state_init(void) { current_state = FSM[CAR_NOT_READY]; } -static void handle_state_neutral(void) { send_motor_drive_cmd(0.0f, 0.0f); } -static void handle_state_disabled(void) { send_motor_drive_cmd(0.0f, 0.0f); } -static void handle_state_regen(void) { send_motor_drive_cmd(0.0f, 1.0f); } -static void handle_state_not_ready(void) { send_motor_drive_cmd(0.0f, 0.0f); } - -static void handle_state_forward(void) { - if (motor_velocity.MC_VehicleVelocity < -0.5f) { - // if we're actually going backwards, let off the pedal until we slow down - send_motor_drive_cmd(0.0f, 0.0f); - } else { - send_motor_drive_cmd(MAX_VELOCITY, apply_rollover_limit(accel_pedal_pct)); - } -} - -static void handle_state_reverse(void) { - if (motor_velocity.MC_VehicleVelocity > 0.5f) { - // if we're actually going forwards, let off the pedal until we slow down - send_motor_drive_cmd(0.0f, 0.0f); - } else { - send_motor_drive_cmd(-MAX_VELOCITY, apply_rollover_limit(accel_pedal_pct)); - } -} - -static void handle_state_cruise(void) { - float current = apply_rollover_limit(accel_pedal_pct); - float velocity = rollover_limit_active ? 0.0f : MAX_VELOCITY; - send_motor_drive_cmd(velocity, current); -} - -//////// rtos tasks - -void Task_UpdateControlStatus(void *args __attribute__((unused))) { - TickType_t last = xTaskGetTickCount(); - while (1) { - update_from_can(); - rebuild_bitfield(); - vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); - } -} - -void Task_FSM(void *args __attribute__((unused))) { - TickType_t last = xTaskGetTickCount(); - while (1) { - fsm_step(); - vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); - } -} - -// VCU_Status 0x10 3 bytes 100ms -void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { - uint8_t buf[3]; - - while (1) { - // Byte 0: VCU_Fault — map internal faults to DBC enum - uint8_t vcu_fault = VCU_STATUS_VCU_FAULT_NO_FAULT; - if (faults_is_active(FAULT_ID_PRECHARGE_TIMEOUT)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_PRECHARGE_TIMEOUT; - else if (faults_is_active(FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE; - else if (faults_is_active(FAULT_ID_MOTOR_15V_UNDERVOLTAGE)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE; - else if (faults_is_active(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT) || - faults_is_active(FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT) || - faults_is_active(FAULT_ID_MOTOR_BAD_HALL_SEQUENCE) || - faults_is_active(FAULT_ID_MOTOR_WD_RESET) || - faults_is_active(FAULT_ID_MOTOR_CONFIG_READ) || - faults_is_active(FAULT_ID_MOTOR_DESATURATION) || - faults_is_active(FAULT_ID_MOTOR_OVERSPEED)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_CONTROLLER_FAULT; - buf[0] = vcu_fault; - - // Byte 1: status bits per DBC positions 8-14 - bool pedals_ok = - !accel_brake.Accel_Pos_Main_Fault && !accel_brake.Accel_Pos_Redundant_Fault && - !accel_brake.Brake_Pos_Main_Fault && !accel_brake.Brake_Pos_Redundant_Fault && - !accel_brake.Brake_Pressure_1_Fault && !accel_brake.Brake_Pressure_2_Fault; - - bool driver_input_ok = !faults_is_active(FAULT_ID_CONTROLS_STATUS_WATCHDOG) && - !faults_is_active(FAULT_ID_CONTROLS_FAULT); - - buf[1] = ((uint8_t)precharge_complete << 0) | // Motor_Contactor_State - ((uint8_t)precharge_complete << 1) | // Motor_Precharge_Contactor_State - ((uint8_t)precharge_complete << 2) | // Motor_Ready_To_Drive - ((uint8_t)driver_input_ok << 3) | // VCU_Driver_Input_OK - ((uint8_t)pedals_ok << 4) | // VCU_Pedals_OK - ((uint8_t)!!(car_status & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK - ((uint8_t)(current_state.stateName == REGEN) << 6); // VCU_Regen_Active - - // Byte 2: VCU_FSM_State bits [3:0] - buf[2] = (uint8_t)(current_state.stateName & 0x0FU); - - carcan_send(CAN_ID_VCU_STATUS, buf, sizeof(buf)); - vTaskDelay(pdMS_TO_TICKS(100)); - } -} diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c new file mode 100644 index 00000000..70f01f7a --- /dev/null +++ b/Firmware/Tasks/Src/FSMTask.c @@ -0,0 +1,157 @@ +/** + * @file FSM.c + * @brief Motor controller FSM implementation + * @copyright Copyright (c) 2026 UT Longhorn Racing Solar + */ + +#define DEFINE_FSM_TABLE +#include "fsm_table_dnr.h" + +#include "BPSCAN_can_msgs.h" +#include "CarCAN_can_msgs.h" +#include "FSM.h" +#include "FaultBits.h" +#include "MotorCAN_can_msgs.h" +#include "Watchdogs.h" +#include "rollover_speed_table.h" +#include +#include + +#define MAX_VELOCITY 100.0f // meters per second + +StaticEventGroup_t fsmInputBuffer = {0}; +EventGroupHandle_t fsmInputGroup = {0}; + +MocoState_t current_state = {0}; + +static FSMDataIn_t fsm_input_read = {0}; +static FSMDataIn_t fsm_input_write = {0}; + +FSMDataIn_t *g_data_read = &fsm_input_read; +FSMDataIn_t *g_data_write = &fsm_input_write; + +static bool rollover_limit_active = false; +static volatile uint16_t fsm_inputs = 0; + +// method stubs so linker doesnt shit itself +static void handle_state_init(void); +static void handle_state_not_ready(void); +static void handle_state_forward(void); +static void handle_state_neutral(void); +static void handle_state_reverse(void); +static void handle_state_regen(void); +static void handle_state_cruise(void); +static void handle_state_disabled(void); + +// static void update_from_can(void); +// static void rebuild_bitfield(void); +static float apply_rollover_limit(float requested_current); + +void fsm_init(void) { + FSM[STATE_INIT].stateHandler = handle_state_init; + FSM[FORWARD_DRIVE].stateHandler = handle_state_forward; + FSM[NEUTRAL_DRIVE].stateHandler = handle_state_neutral; + FSM[REVERSE_DRIVE].stateHandler = handle_state_reverse; + FSM[REGEN].stateHandler = handle_state_regen; + FSM[CRUISE_CONTROL].stateHandler = handle_state_cruise; + FSM[DISABLED].stateHandler = handle_state_disabled; + FSM[CAR_NOT_READY].stateHandler = handle_state_not_ready; + + current_state = FSM[STATE_INIT]; + current_state.stateHandler(); +} + +void fsm_step(void) { + fsm_inputs = xEventGroupGetBits(fsmInputGroup); + current_state = FSM[current_state.NextStates[fsm_inputs]]; + if (current_state.stateHandler) current_state.stateHandler(); +} + +void fsm_disable(void) { current_state = FSM[DISABLED]; } +void fsm_recover(void) { current_state = FSM[CAR_NOT_READY]; } +uint16_t fsm_get_fsm_inputs(void) { return (uint16_t)fsm_inputs; } +bool fsm_is_over_rollover_speed(void) { return rollover_limit_active; } + +void fsm_set_all_inputs(EventBits_t mask) { + xEventGroupClearBits(fsmInputGroup, FSM_INPUTS_MASK_ALL); + xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); +} + +void fsm_set_input(EventBits_t mask) { + xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); +} + +void fsm_get_inputs(void) { + xEventGroupGetBits(fsmInputGroup); +} + +// goofy ahh logic, uses lut +static float apply_rollover_limit(float requested_current) { + int deg = abs((int)g_data_read->lws.LWS_Angle) / 10; + if (deg > (int)ROLLOVER_TABLE_MAX_DEG) deg = (int)ROLLOVER_TABLE_MAX_DEG; + + uint16_t v_max_cms = rollover_speed_table[deg]; + uint16_t v_now_cms = (uint16_t)(g_data_read->motor_velocity.MC_VehicleVelocity * 100.0f); + + if (v_max_cms != ROLLOVER_TABLE_NO_LIMIT && v_now_cms > v_max_cms) { + rollover_limit_active = true; + return 0.0f; + } + rollover_limit_active = false; + return requested_current; +} + +float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, + uint8_t out_max) { + if (in_min >= in_max || input <= in_min) return (float)out_min / 100.0f; + if (input >= in_max) return (float)out_max / 100.0f; + uint16_t oi = input - in_min; + uint16_t ir = in_max - in_min; + uint16_t or_ = out_max - out_min; + return ((float)(oi * or_) / (float)ir + (float)out_min) / 100.0f; +} + +//// state handlers + +static void handle_state_init(void) { current_state = FSM[CAR_NOT_READY]; } +static void handle_state_neutral(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } +static void handle_state_disabled(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } +static void handle_state_regen(void) { MotorCAN_Send_Drive_Cmd(0.0f, 1.0f, 0); } +static void handle_state_not_ready(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } + +static void handle_state_forward(void) { + if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { + // if we're actually going backwards, let off the pedal until we slow down + MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + } else { + MotorCAN_Send_Drive_Cmd(MAX_VELOCITY, apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos), 0); + } +} + +static void handle_state_reverse(void) { + if (g_data_read->motor_velocity.MC_VehicleVelocity > 0.5f) { + // if we're actually going forwards, let off the pedal until we slow down + MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + } else { + MotorCAN_Send_Drive_Cmd(-MAX_VELOCITY, apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos), 0); + } +} + +static void handle_state_cruise(void) { + float current = apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos); + float velocity = rollover_limit_active ? 0.0f : MAX_VELOCITY; + MotorCAN_Send_Drive_Cmd(velocity, current, 0); +} + + + +//////// rtos tasks + + +void Task_FSM(void *args __attribute__((unused))) { + TickType_t last = xTaskGetTickCount(); + while (1) { + fsm_step(); + vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); + } +} diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index a9312dd0..14725f1f 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -9,14 +9,85 @@ StackType_t Precharge_Task_Stack[PRECHARGE_TASK_STACK_SIZE]; StaticTask_t Init_Task_Buffer; StackType_t Init_Task_Stack[INIT_TASK_STACK_SIZE]; -StaticTask_t Motor_Control_Task_Buffer; -StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; +// StaticTask_t Motor_Control_Task_Buffer; +// StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; -StaticTask_t Motor_Telemetry_Task_Buffer; -StackType_t Motor_Telemetry_Task_Stack[MOTOR_TELEMETRY_TASK_STACK_SIZE]; +// StaticTask_t Motor_Telemetry_Task_Buffer; +// StackType_t Motor_Telemetry_Task_Stack[MOTOR_TELEMETRY_TASK_STACK_SIZE]; + +// StaticTask_t Can_Tx_Telemetry_Task_Buffer; +// StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; + +StaticTask_t FSM_Task_Buffer; +StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; + +StaticTask_t VCUStatus_Task_Buffer; +StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; + +// void Task_Init() { +// __HAL_RCC_SYSCFG_CLK_ENABLE(); +// __HAL_RCC_PWR_CLK_ENABLE(); + +// Init_UART_Printf(); + +// MotorSafeBits_Init(); + +// MotorCAN_Init(); +// CarCAN_Init(); + + xTaskCreateStatic( + Task_FaultHandler, // Task function + "FaultHandler", // Name of the task (for debugging) + configMINIMAL_STACK_SIZE, // Stack size in words + NULL, // Task input parameter + FAULT_HANDLER_THREAD_PRIO, // Task priority + FaultHandlerTask_Stack, // Task handle + &FaultHandlerTask_Buffer // Static task buffer (optional) + ); + +// hprecharge_task = xTaskCreateStatic( +// Task_Precharge, // Task function +// "Precharge", // Name of the task (for debugging) +// configMINIMAL_STACK_SIZE, // Stack size in words +// NULL, // Task input parameter +// PRECHARGE_THREAD_PRIO, // Task priority +// Precharge_Task_Stack, // Task handle +// &Precharge_Task_Buffer // Static task buffer (optional) +// ); + +// // xTaskCreateStatic( +// // Task_MotorControl, // Task function +// // "Motor Control Thread", // Name of the task (for debugging) +// // configMINIMAL_STACK_SIZE, // Stack size in words +// // NULL, // Task input parameter +// // MOTOR_CONTROL_THREAD_PRIO, // Task priority +// // Motor_Control_Task_Stack, // Task handle +// // &Motor_Control_Task_Buffer // Static task buffer (optional) +// // ); + +// xTaskCreateStatic( +// Task_MotorTelemetry, // Task function +// "Motor Telemetry Thread", // Name of the task (for debugging) +// configMINIMAL_STACK_SIZE, // Stack size in words +// NULL, // Task input parameter +// MOTOR_TELEMETRY_THREAD_PRIO, // Task priority +// Motor_Telemetry_Task_Stack, // Task handle +// &Motor_Telemetry_Task_Buffer // Static task buffer (optional) +// ); + +// // xTaskCreateStatic( +// // Task_CanTxTelemetry, // Task function +// // "Can TX Telemetry Thread", // Name of the task (for debugging) +// // configMINIMAL_STACK_SIZE, // Stack size in words +// // NULL, // Task input parameter +// // CAN_TX_TELEMETRY_THREAD_PRIO, // Task priority +// // Can_Tx_Telemetry_Task_Stack, // Task handle +// // &Can_Tx_Telemetry_Task_Buffer // Static task buffer (optional) +// // ); + +// vTaskDelete(NULL); +// } -StaticTask_t Can_Tx_Telemetry_Task_Buffer; -StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; void Task_Init() { __HAL_RCC_SYSCFG_CLK_ENABLE(); @@ -39,7 +110,7 @@ void Task_Init() { &FaultHandlerTask_Buffer // Static task buffer (optional) ); - hprecharge_task = xTaskCreateStatic( + xTaskCreateStatic( Task_Precharge, // Task function "Precharge", // Name of the task (for debugging) configMINIMAL_STACK_SIZE, // Stack size in words @@ -50,33 +121,23 @@ void Task_Init() { ); xTaskCreateStatic( - Task_MotorControl, // Task function - "Motor Control Thread", // Name of the task (for debugging) + Task_FSM, // Task function + "FSM Thread", // Name of the task (for debugging) configMINIMAL_STACK_SIZE, // Stack size in words NULL, // Task input parameter - MOTOR_CONTROL_THREAD_PRIO, // Task priority - Motor_Control_Task_Stack, // Task handle - &Motor_Control_Task_Buffer // Static task buffer (optional) + FSM_THREAD_PRIO, // Task priority + FSM_Task_Stack, // Task handle + &FSM_Task_Buffer // Static task buffer (optional) ); xTaskCreateStatic( - Task_MotorTelemetry, // Task function - "Motor Telemetry Thread", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - MOTOR_TELEMETRY_THREAD_PRIO, // Task priority - Motor_Telemetry_Task_Stack, // Task handle - &Motor_Telemetry_Task_Buffer // Static task buffer (optional) - ); - - xTaskCreateStatic( - Task_CanTxTelemetry, // Task function - "Can TX Telemetry Thread", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - CAN_TX_TELEMETRY_THREAD_PRIO, // Task priority - Can_Tx_Telemetry_Task_Stack, // Task handle - &Can_Tx_Telemetry_Task_Buffer // Static task buffer (optional) + Task_BroadcastVCUStatus, // Task function + "VCU Status Thread", // Name of the task (for debugging) + configMINIMAL_STACK_SIZE, // Stack size in words + NULL, // Task input parameter + VCU_STATUS_THREAD_PRIO, // Task priority + VCUStatus_Task_Stack, // Task handle + &VCUStatus_Task_Buffer // Static task buffer (optional) ); vTaskDelete(NULL); diff --git a/Firmware/Tasks/Src/MotorControlTask.c b/Firmware/Tasks/Src/MotorControlTask.c deleted file mode 100644 index 5bd5a6dc..00000000 --- a/Firmware/Tasks/Src/MotorControlTask.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "MotorControlTask.h" -#include "CAN_FD.h" - -// how often we want print outs from this thread -#define MOTOR_CONTROLLER_PRINT_DEBUG_PERIOD 5000 - -// number of times the thread will run before we print out debug info -#define MOTOR_CONTROLLER_PRINT_DEBUG_COUNT (MOTOR_CONTROLLER_PRINT_DEBUG_PERIOD/MOTOR_CONTROL_TASK_PERIOD_MS) - - -static FDCAN_TxHeaderTypeDef mocoDriveCommandHeader; - -static void initDriveCommandHeader(FDCAN_TxHeaderTypeDef *tx_header); -static void initMotorPowerCommandHeader(FDCAN_TxHeaderTypeDef *tx_header); - - -void MotorControlTask_Init(void){ - // set necessary motor drive command parameters - initDriveCommandHeader(&mocoDriveCommandHeader); -} - -static void initMotorPowerCommandHeader(FDCAN_TxHeaderTypeDef *tx_header){ - - tx_header->Identifier = CAN_ID_MC_POWERCOMMAND; - tx_header->IdType = FDCAN_STANDARD_ID; - tx_header->TxFrameType = FDCAN_DATA_FRAME; - tx_header->DataLength = FDCAN_DLC_BYTES_8; - tx_header->ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header->BitRateSwitch = FDCAN_BRS_OFF; - tx_header->FDFormat = FDCAN_CLASSIC_CAN; - tx_header->TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header->MessageMarker = 0; -} - -// helper function to inialize motor drive command headers -static void initDriveCommandHeader(FDCAN_TxHeaderTypeDef *tx_header){ - - tx_header->Identifier = CAN_ID_MC_DRIVECOMMAND; - tx_header->IdType = FDCAN_STANDARD_ID; - tx_header->TxFrameType = FDCAN_DATA_FRAME; - tx_header->DataLength = FDCAN_DLC_BYTES_8; - tx_header->ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header->BitRateSwitch = FDCAN_BRS_OFF; - tx_header->FDFormat = FDCAN_CLASSIC_CAN; - tx_header->TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header->MessageMarker = 0; -} - -// encodes a drive command struct into an array of bytes for can_send -static void packDriveCommand(mc_drivecommand_t motorDriveCommand, uint8_t tx_data[8]){ - memcpy(&tx_data[4], &(motorDriveCommand.MC_MotorCurrentSetpoint), sizeof(float)); - memcpy(&tx_data[0], &(motorDriveCommand.MC_MotorVelocitySetpoint), sizeof(float)); -} - -static void packPowerCommand(mc_powercommand_t motorPowerCommand, uint8_t tx_data[8]){ - memcpy(&tx_data[4], &(motorPowerCommand.MC_MotorPowerSetpoint), sizeof(float)); -} - -static float busCurrentSetPoint = 1.0f; - -void Task_MotorControl(void){ - - // motor canbus MUST be initalized by now - // the motor safe bits MUST be initalized by now - MotorControlTask_Init(); - - // current and velocity setpoint control speed of motor - mc_drivecommand_t motorDriveCommand = {0}; - motorDriveCommand.MC_MotorCurrentSetpoint = 0.0f; - motorDriveCommand.MC_MotorVelocitySetpoint = 0.0f; - uint8_t motor_drive_tx_data[8]; - - uint8_t print_debug_counter = 0; - - // sets the max power of the motor - mc_powercommand_t motorPowerCommand = {0}; - motorPowerCommand.MC_MotorPowerSetpoint = busCurrentSetPoint; - FDCAN_TxHeaderTypeDef mocoPowerCommandHeader; - uint8_t motor_power_tx_data[8]; // the message being sent on the CANbus - initMotorPowerCommandHeader(&mocoPowerCommandHeader); // initializes the can tx header - packPowerCommand(motorPowerCommand, motor_power_tx_data); // packs the motorPower struct into an array of bytes - - EventBits_t motorSafeBits; - while(1){ - - // Send power command - MotorCAN_Send(&mocoPowerCommandHeader, motor_power_tx_data, portMAX_DELAY); - - // check if the car is in a drivable state - motorSafeBits = MotorSafeBits_WaitMask(motorDrivableBits, pdMS_TO_TICKS(0)); - - // no bits are set, so the motor should not be run - if(motorSafeBits == 0){ - motorDriveCommand.MC_MotorCurrentSetpoint = 0.0f; - motorDriveCommand.MC_MotorVelocitySetpoint = 0.0f; - LED_set(CAR_DRIVABLE, LED_OFF); - } - else{ - motorDriveCommand.MC_MotorCurrentSetpoint = 0.2f; - motorDriveCommand.MC_MotorVelocitySetpoint = 12000.0f; - LED_set(CAR_DRIVABLE, LED_ON); - } - - packDriveCommand(motorDriveCommand, motor_drive_tx_data); - - MotorCAN_Send(&mocoDriveCommandHeader, motor_drive_tx_data, portMAX_DELAY); - - print_debug_counter++; - if(print_debug_counter > MOTOR_CONTROLLER_PRINT_DEBUG_COUNT){ - printf("Motor Current Setpoint: "); - printf("%f\r\n", motorDriveCommand.MC_MotorCurrentSetpoint); - printf("Motor Velocity Setpoint: "); - printf("%f\r\n", motorDriveCommand.MC_MotorVelocitySetpoint); - print_debug_counter = 0; - } - - LED_toggle(CAR_HB); - - // minimum delay for drive command is 250ms, or else the wavesculptor will reset to neutral - vTaskDelay(pdMS_TO_TICKS(MOTOR_CONTROL_TASK_PERIOD_MS)); - - } -} diff --git a/Firmware/Tasks/Src/ReadMotorCAN.c b/Firmware/Tasks/Src/ReadMotorCAN.c deleted file mode 100644 index b016044e..00000000 --- a/Firmware/Tasks/Src/ReadMotorCAN.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "ReadMotorCAN.h" - -void Init_ReadMotorCAN(){ - -} - -void Task_ReadMotorCAN(){ - - // Motor CANbus must be initialized by now - - Init_ReadMotorCAN(); - - FDCAN_RxHeaderTypeDef motorstatus_rx_header = {0}; - uint8_t motorstatus_rx_data[8] = {0}; - - uint8_t can_recv_errors = 0; - - while(1){ - - - if(MotorCAN_Recv(CAN_ID_MC_STATUS, &motorstatus_rx_header, motorstatus_rx_data, portMAX_DELAY) == CAN_OK){ - can_recv_errors = 0; - }else{ - can_recv_errors++; - } - - - } -} diff --git a/Firmware/Tasks/Src/UpdateFSMInputsTask.c b/Firmware/Tasks/Src/UpdateFSMInputsTask.c index ec223ce1..c10f454e 100644 --- a/Firmware/Tasks/Src/UpdateFSMInputsTask.c +++ b/Firmware/Tasks/Src/UpdateFSMInputsTask.c @@ -1,25 +1,27 @@ #include "UpdateFSMInputsTask.h" +#include "Contactors.h" #include "event_groups.h" +static float brake_threshold = BRAKE_THRESH; + static void rebuild_inputs(void) { EventBits_t s = 0; - if (driver_input.Gear_Forward) + if (g_data_read->driver_input.Gear_Forward) s |= FORWARD_BIT; - else if (driver_input.Gear_Reverse) + else if (g_data_read->driver_input.Gear_Reverse) s |= REVERSE_BIT; else s |= NEUTRAL_BIT; - if (driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; - if (driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; - if (driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; - if (bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; - if (precharge_complete) s |= PRECHARGE_COMPLETE_BIT; - - + if (g_data_read->driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; + if (g_data_read->driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; + if (g_data_read->driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; + if (g_data_read->bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; + if (contactor_get_sense(MOTOR_CONTACTOR) && contactor_get_sense(MOTOR_PRE_CONTACTOR)) + s |= PRECHARGE_COMPLETE_BIT; - if (brake_pedal_pct >= brake_threshold) { + if (g_data_read->accel_brake.BrakePedal_Main_Pos >= brake_threshold) { s |= BRAKE_BIT; brake_threshold = BRAKE_THRESH_HYST; } else { @@ -49,101 +51,7 @@ void Task_UpdateControlStatus(void *args __attribute__((unused))) { g_data_write = tmp; taskEXIT_CRITICAL(); - rebuild_inputs(&); + rebuild_inputs(); vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); } } - -void Task_UpdateInputs(void *args) -{ - TickType_t last = xTaskGetTickCount(); - - while (1) - { - fsm_inputs_t* w = (fsm_inputs_t*)write_ptr; - - // ---- CAN updates ---- - carcan_try_recv(CAN_ID_DRIVER_INPUT_STATUS, handle_driver_input, &w->driver_input); - carcan_try_recv(CAN_ID_ACCEL_BRAKE_POSITION, handle_accel_brake, &w->accel_brake); - carcan_try_recv(CAN_ID_LWS_STANDARD, handle_lws, &w->lws); - carcan_try_recv(CAN_ID_CONTROLS_STATUS, handle_controls_status, &w->controls_status); - carcan_try_recv(CAN_ID_BPS_STATUS, handle_bps, &w->bps_status); - vcucan_try_recv(CAN_ID_MC_VELOCITYMEASUREMENT, handle_motor_velocity, &w->motor_velocity); - vcucan_try_recv(CAN_ID_MC_STATUS, handle_motor_status, &w->motor_status); - - // ---- Build event bits (level-triggered) ---- - EventBits_t set = 0; - EventBits_t clr = 0; - - // 🚗 Gear (mutually exclusive) - clr |= (FORWARD_BIT | REVERSE_BIT | NEUTRAL_BIT); - if (w->driver_input.Gear_Forward) set |= FORWARD_BIT; - else if (w->driver_input.Gear_Reverse) set |= REVERSE_BIT; - else set |= NEUTRAL_BIT; - - // 🎮 Buttons - if (w->driver_input.Regen_Activate) set |= REGEN_BUTTON_BIT; - else clr |= REGEN_BUTTON_BIT; - - if (w->driver_input.Regen_Enable) set |= REGEN_ENABLED_BIT; - else clr |= REGEN_ENABLED_BIT; - - if (w->driver_input.Cruise_Enable) set |= CRUISE_CONTROL_BUTTON_BIT; - else clr |= CRUISE_CONTROL_BUTTON_BIT; - - // 🔋 System - if (w->bps_status.BPS_Regen_OK) set |= READY_TO_REGEN_BIT; - else clr |= READY_TO_REGEN_BIT; - - if (precharge_complete) set |= PRECHARGE_COMPLETE_BIT; - else clr |= PRECHARGE_COMPLETE_BIT; - - // 🦶 Brake (with hysteresis) - float brake = w->accel_brake.Brake_Pos_Main; - - if (brake >= brake_threshold) { - set |= BRAKE_BIT; - brake_threshold = BRAKE_THRESH_HYST; - } else { - clr |= BRAKE_BIT; - brake_threshold = BRAKE_THRESH; - } - - // 🛡 Pedals OK - bool pedals_ok = - !w->accel_brake.Accel_Pos_Main_Fault && - !w->accel_brake.Accel_Pos_Redundant_Fault && - !w->accel_brake.Brake_Pos_Main_Fault && - !w->accel_brake.Brake_Pos_Redundant_Fault && - !w->accel_brake.Brake_Pressure_1_Fault && - !w->accel_brake.Brake_Pressure_2_Fault; - - if (pedals_ok) set |= PEDALS_OK_BIT; - else clr |= PEDALS_OK_BIT; - - // 🎛 Driver input OK - bool driver_ok = - !faults_is_active(FAULT_ID_CONTROLS_STATUS_WATCHDOG) && - !faults_is_active(FAULT_ID_CONTROLS_FAULT); - - if (driver_ok) set |= DRIVER_INPUT_OK_BIT; - else clr |= DRIVER_INPUT_OK_BIT; - - // ⚠️ Faults - if (faults_any_active()) set |= FAULT_ACTIVE_BIT; - else clr |= FAULT_ACTIVE_BIT; - - // ---- Apply bits atomically-ish ---- - xEventGroupClearBits(fsm_event_group, clr); - xEventGroupSetBits(fsm_event_group, set); - - // ---- Swap buffers ---- - taskENTER_CRITICAL(); - fsm_inputs_t* tmp = (fsm_inputs_t*)read_ptr; - read_ptr = write_ptr; - write_ptr = tmp; - taskEXIT_CRITICAL(); - - vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); - } -} \ No newline at end of file diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c new file mode 100644 index 00000000..e6ed1d10 --- /dev/null +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -0,0 +1,76 @@ +#include "VCUStatusTask.h" +#include "CANbus.h" +#include "event_groups.h" +#include "FaultBits.h" +#include "Contactors.h" +#include "FSM.h" +#include "Watchdogs.h" + +// VCU_Status 0x10 3 bytes 100ms +void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { + uint8_t buf[3]; + + while (1) { + // Byte 0: VCU_Fault — map internal faults to DBC enum + uint8_t vcu_fault = VCU_STATUS_VCU_FAULT_NO_FAULT; + if (faults_is_active(FAULT_ID_PRECHARGE_TIMEOUT)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_PRECHARGE_TIMEOUT; + else if(faults_is_active(VCU_STATUS_VCU_FAULT_MOTOR_PCHG_CONTACTOR_SENSE)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_PCHG_CONTACTOR_SENSE; + else if(faults_is_active(VCU_STATUS_VCU_FAULT_MOTOR_CONTACTOR_SENSE)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_CONTACTOR_SENSE; + else if (faults_is_active(FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE; + else if (faults_is_active(FAULT_ID_MOTOR_15V_UNDERVOLTAGE)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE; + else if (faults_is_active(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT) || + faults_is_active(FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT) || + faults_is_active(FAULT_ID_MOTOR_BAD_HALL_SEQUENCE) || + faults_is_active(FAULT_ID_MOTOR_WD_RESET) || + faults_is_active(FAULT_ID_MOTOR_CONFIG_READ) || + faults_is_active(FAULT_ID_MOTOR_DESATURATION) || + faults_is_active(FAULT_ID_MOTOR_OVERSPEED)) + vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_CONTROLLER_FAULT; + buf[0] = vcu_fault; + + + // Byte 1: status bits per DBC positions 8-14 + bool pedals_ok = !g_data_read->accel_brake.AccelPedal_Main_Fault && + !g_data_read->accel_brake.AccelPedal_Redundant_Fault && + !g_data_read->accel_brake.BrakePedal_Main_Fault && + !g_data_read->accel_brake.BrakePedal_Redundant_Fault; + + bool driver_input_ok = !faults_is_active(FAULT_ID_GENERIC_WATCHDOG_FAULT) && + !faults_is_active(FAULT_ID_CONTROLS_FAULT); + + bool steering_angle_ok = g_data_read->lws.LWS_Fault == 0; + + buf[1] = ((uint8_t)contactor_get_sense(MOTOR_CONTACTOR) << 0) | // Motor_Contactor_State + ((uint8_t)contactor_get_sense(MOTOR_PRE_CONTACTOR) << 1) | // Motor_Precharge_Contactor_State + ((uint8_t) (contactor_get_sense(MOTOR_PRE_CONTACTOR) && vcu_fault == 0) << 2) | // Motor_Ready_To_Drive + ((uint8_t)driver_input_ok << 3) | // VCU_Driver_Input_OK + ((uint8_t)pedals_ok << 4) | // VCU_Pedals_OK + ((uint8_t)!!(fsm_get_car_status() & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK + ((uint8_t)(currentState.stateName == REGEN) << 6) | // VCU_Regen_Active + ((uint8_t)steering_angle_ok << 7); // VCU_Steering_Angle_OK (not implemented, set to OK) + + // Byte 2: VCU_FSM_State bits [3:0] + buf[2] = (uint8_t)(currentState.stateName & 0x0FU); + + buf[3] = fsm_get_car_status; //this supposed to have fsm states as well but stateName covers it for now + + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = CAN_ID_VCU_STATUS; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = FDCAN_DLC_BYTES_8; + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + tx_header.MessageMarker = 0; + + CarCAN_Send(&tx_header, buf, sizeof(buf)); + vTaskDelay(pdMS_TO_TICKS(100)); + } +} \ No newline at end of file diff --git a/Firmware/config/Inc/BPSCAN_can_msgs.h b/Firmware/config/Inc/BPSCAN_can_msgs.h index 7c838a1f..406d8bdd 100644 --- a/Firmware/config/Inc/BPSCAN_can_msgs.h +++ b/Firmware/config/Inc/BPSCAN_can_msgs.h @@ -4,96 +4,242 @@ /* ================= CAN ID Macros ================= */ -#define CAN_ID_BPS_VOLTAGE_ARR_0 0x2 -#define CAN_ID_BPS_VOLTAGE_ARR_1 0x3 -#define CAN_ID_BPS_VOLTAGE_ARR_2 0x4 -#define CAN_ID_BPS_VOLTAGE_ARR_3 0x5 -#define CAN_ID_BPS_VOLTAGE_ARR_4 0x6 -#define CAN_ID_BPS_VOLTAGE_ARR_5 0x7 -#define CAN_ID_BPS_VOLTAGE_ARR_6 0x8 -#define CAN_ID_BPS_VOLTAGE_ARR_7 0x9 +#define CAN_ID_BPS_VT0_VOLTAGE_ARR 0x2 +#define CAN_ID_BPS_VT1_VOLTAGE_ARR 0x3 +#define CAN_ID_BPS_VT2_VOLTAGE_ARR 0x4 +#define CAN_ID_BPS_VT3_VOLTAGE_ARR 0x5 +#define CAN_ID_BPS_VT4_VOLTAGE_ARR 0x6 +#define CAN_ID_BPS_VT5_VOLTAGE_ARR 0x7 +#define CAN_ID_BPS_VT6_VOLTAGE_ARR 0x8 +#define CAN_ID_BPS_VT7_VOLTAGE_ARR 0x9 #define CAN_ID_BPS_PACK_CURRENT 0xA -#define CAN_ID_BPS_TEMPERATURE_ARR_0 0x10 -#define CAN_ID_BPS_TEMPERATURE_ARR_1 0x11 -#define CAN_ID_BPS_TEMPERATURE_ARR_2 0x12 -#define CAN_ID_BPS_TEMPERATURE_ARR_3 0x13 -#define CAN_ID_BPS_TEMPERATURE_ARR_4 0x14 -#define CAN_ID_BPS_TEMPERATURE_ARR_5 0x15 -#define CAN_ID_BPS_TEMPERATURE_ARR_6 0x16 -#define CAN_ID_BPS_TEMPERATURE_ARR_7 0x17 -#define CAN_ID_BPS_PRECHARGE_VOLTAGES 0x20 +#define CAN_ID_BPS_VT0_TEMPERATURE_ARR 0x10 +#define CAN_ID_BPS_VT1_TEMPERATURE_ARR 0x11 +#define CAN_ID_BPS_VT2_TEMPERATURE_ARR 0x12 +#define CAN_ID_BPS_VT3_TEMPERATURE_ARR 0x13 +#define CAN_ID_BPS_VT4_TEMPERATURE_ARR 0x14 +#define CAN_ID_BPS_VT5_TEMPERATURE_ARR 0x15 +#define CAN_ID_BPS_VT6_TEMPERATURE_ARR 0x16 +#define CAN_ID_BPS_VT7_TEMPERATURE_ARR 0x17 +#define CAN_ID_BPS_BALANCE_DISCHARGE 0x7A0 /* ================= CAN Length Macros ================= */ -#define CAN_DLC_BPS_VOLTAGE_ARR_0 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_1 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_2 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_3 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_4 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_5 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_6 4 -#define CAN_DLC_BPS_VOLTAGE_ARR_7 4 +#define CAN_DLC_BPS_VT0_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT1_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT2_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT3_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT4_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT5_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT6_VOLTAGE_ARR 4 +#define CAN_DLC_BPS_VT7_VOLTAGE_ARR 4 #define CAN_DLC_BPS_PACK_CURRENT 5 -#define CAN_DLC_BPS_TEMPERATURE_ARR_0 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_1 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_2 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_3 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_4 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_5 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_6 7 -#define CAN_DLC_BPS_TEMPERATURE_ARR_7 7 -#define CAN_DLC_BPS_PRECHARGE_VOLTAGES 6 +#define CAN_DLC_BPS_VT0_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT1_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT2_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT3_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT4_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT5_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT6_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_VT7_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_BALANCE_DISCHARGE 1 +/* ================= Value Table Enums ================= */ + +typedef enum { + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt0_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt1_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt2_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt3_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt4_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt5_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt6_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_vt7_voltage_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt0_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt1_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt2_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt3_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt4_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt5_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt6_temperature_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_vt7_temperature_arr_bps_temperature_tap_fault_e; + /* ================= Message Structs ================= */ typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_0_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt0_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_1_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt1_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_2_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt2_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_3_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt3_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_4_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt4_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_5_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt5_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_6_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt6_voltage_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint16_t BPS_Voltage_Tap_Data; - uint8_t BPS_VoltTemp_BQ_Fault; -} bps_voltage_arr_7_t; + uint8_t BPS_Voltage_Tap_Fault; +} bps_vt7_voltage_arr_t; typedef struct { int32_t Main_Battery_Current; @@ -105,59 +251,59 @@ typedef struct { uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_0_t; +} bps_vt0_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_1_t; +} bps_vt1_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_2_t; +} bps_vt2_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_3_t; +} bps_vt3_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_4_t; +} bps_vt4_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_5_t; +} bps_vt5_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_6_t; +} bps_vt6_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; uint16_t BPS_Temperature_Tap_RawV; -} bps_temperature_arr_7_t; +} bps_vt7_temperature_arr_t; typedef struct { - uint32_t Precharge_Battery_Voltage; - uint32_t Precharge_Array_Voltage; -} bps_precharge_voltages_t; + uint8_t BPS_Segment_idx; + uint8_t BPS_Tap_idx; +} bps_balance_discharge_t; diff --git a/Firmware/config/Inc/CarCAN_can_msgs.h b/Firmware/config/Inc/CarCAN_can_msgs.h index b68de6b8..239822fd 100644 --- a/Firmware/config/Inc/CarCAN_can_msgs.h +++ b/Firmware/config/Inc/CarCAN_can_msgs.h @@ -5,94 +5,224 @@ /* ================= CAN ID Macros ================= */ #define CAN_ID_BPS_STATUS 0x1 -#define CAN_ID_BPS_AGGREGATE_ARR 0xB +#define CAN_ID_BPS_VOLTAGE_AGGREGATE_ARR 0xB +#define CAN_ID_BPS_TEMPERATURE_AGGREGATE_ARR 0xC +#define CAN_ID_BPS_TEMP_RAWV_AGGREGATE_ARR 0xD #define CAN_ID_VCU_STATUS 0x18 #define CAN_ID_CONTROLS_STATUS 0x19 +#define CAN_ID_BPS_PRECHARGE_VOLTAGES 0x20 #define CAN_ID_VCU_PRECHARGE_VOLTAGES 0x21 -#define CAN_ID_ACCEL_BRAKE_POSITION 0x50 -#define CAN_ID_ACCEL_BRAKE_POSITION_VOLTAGE 0x51 +#define CAN_ID_PEDAL_STATUS 0x50 +#define CAN_ID_PEDAL_ACCEL_RAWV 0x51 +#define CAN_ID_PEDAL_BRAKE_RAWV 0x52 #define CAN_ID_DRIVER_INPUT_STATUS 0x60 -#define CAN_ID_MPPT_A_POWER 0x200 +#define CAN_ID_MPPT_A_POWERMEASUREMENTS 0x200 #define CAN_ID_MPPT_A_STATUS 0x201 +#define CAN_ID_MPPT_A_SWEEPMEASUREMENTS 0x202 #define CAN_ID_MPPT_A_SETMODE 0x209 -#define CAN_ID_MPPT_B_POWER 0x210 -#define CAN_ID_MPPT_B_STATUS 0x211 -#define CAN_ID_MPPT_B_SETMODE 0x219 -#define CAN_ID_MPPT_C_POWER 0x220 -#define CAN_ID_MPPT_C_STATUS 0x221 -#define CAN_ID_MPPT_C_SETMODE 0x229 -#define CAN_ID_LWS_STANDARD 0x2B0 +#define CAN_ID_MPPT_A_PERFORMSWEEP 0x210 +#define CAN_ID_MPPT_A_SETOUTPUTVOLTAGELIMIT 0x211 +#define CAN_ID_MPPT_A_SETOUTPUTCURRENTLIMIT 0x212 +#define CAN_ID_MPPT_B_POWERMEASUREMENTS 0x220 +#define CAN_ID_MPPT_B_STATUS 0x221 +#define CAN_ID_MPPT_B_SWEEPMEASUREMENTS 0x222 +#define CAN_ID_MPPT_B_SETMODE 0x229 +#define CAN_ID_MPPT_B_PERFORMSWEEP 0x230 +#define CAN_ID_MPPT_B_SETOUTPUTVOLTAGELIMIT 0x231 +#define CAN_ID_MPPT_B_SETOUTPUTCURRENTLIMIT 0x232 +#define CAN_ID_MPPT_C_POWERMEASUREMENTS 0x240 +#define CAN_ID_MPPT_C_STATUS 0x241 +#define CAN_ID_MPPT_C_SWEEPMEASUREMENTS 0x242 +#define CAN_ID_MPPT_C_SETMODE 0x249 +#define CAN_ID_MPPT_C_PERFORMSWEEP 0x250 +#define CAN_ID_MPPT_C_SETOUTPUTVOLTAGELIMIT 0x251 +#define CAN_ID_MPPT_C_SETOUTPUTCURRENTLIMIT 0x252 #define CAN_ID_SUPP_BATTERY_STATUS 0x300 #define CAN_ID_SUPP_BATTERY_CHARGER_STATUS 0x301 -#define CAN_ID_BBPDU_STATUS 0x350 -#define CAN_ID_BBPDU_SET_SWITCHES 0x351 -#define CAN_ID_BBPDU_SET_CURRENT_LIMIT 0x352 -#define CAN_ID_PUMP_STATUS_FLOWRATE 0x500 +#define CAN_ID_PDU_STATUS_ARR 0x350 +#define CAN_ID_PDU_SET_SWITCH_ARR 0x351 +#define CAN_ID_PDU_SET_CURRENT_LIMIT_ARR 0x352 +#define CAN_ID_PUMP_STATUS 0x500 #define CAN_ID_COOLANT_TEMPERATURE 0x501 #define CAN_ID_RADIATOR_FANSPEED 0x502 #define CAN_ID_LV_CARRIER_STATUS 0x600 -#define CAN_ID_BRAKE_PRESSURE 0x650 -#define CAN_ID_DISPLAY_CAMERAS_STATUS 0x700 +#define CAN_ID_BRAKE_PRESSURE_1 0x650 +#define CAN_ID_BRAKE_PRESSURE_2 0x651 +#define CAN_ID_DISPLAY_STATUS 0x700 #define CAN_ID_TELEMETRY_STATUS 0x750 -#define CAN_ID_LWS_CONFIG 0x7C0 /* ================= CAN Length Macros ================= */ -#define CAN_DLC_BPS_STATUS 7 -#define CAN_DLC_BPS_AGGREGATE_ARR 7 -#define CAN_DLC_VCU_STATUS 6 -#define CAN_DLC_CONTROLS_STATUS 4 +#define CAN_DLC_BPS_STATUS 8 +#define CAN_DLC_BPS_VOLTAGE_AGGREGATE_ARR 6 +#define CAN_DLC_BPS_TEMPERATURE_AGGREGATE_ARR 8 +#define CAN_DLC_BPS_TEMP_RAWV_AGGREGATE_ARR 4 +#define CAN_DLC_VCU_STATUS 4 +#define CAN_DLC_CONTROLS_STATUS 6 +#define CAN_DLC_BPS_PRECHARGE_VOLTAGES 6 #define CAN_DLC_VCU_PRECHARGE_VOLTAGES 6 -#define CAN_DLC_ACCEL_BRAKE_POSITION 5 -#define CAN_DLC_ACCEL_BRAKE_POSITION_VOLTAGE 8 +#define CAN_DLC_PEDAL_STATUS 6 +#define CAN_DLC_PEDAL_ACCEL_RAWV 5 +#define CAN_DLC_PEDAL_BRAKE_RAWV 5 #define CAN_DLC_DRIVER_INPUT_STATUS 2 -#define CAN_DLC_MPPT_A_POWER 8 +#define CAN_DLC_MPPT_A_POWERMEASUREMENTS 8 #define CAN_DLC_MPPT_A_STATUS 5 +#define CAN_DLC_MPPT_A_SWEEPMEASUREMENTS 6 #define CAN_DLC_MPPT_A_SETMODE 1 -#define CAN_DLC_MPPT_B_POWER 8 +#define CAN_DLC_MPPT_A_PERFORMSWEEP 5 +#define CAN_DLC_MPPT_A_SETOUTPUTVOLTAGELIMIT 2 +#define CAN_DLC_MPPT_A_SETOUTPUTCURRENTLIMIT 2 +#define CAN_DLC_MPPT_B_POWERMEASUREMENTS 8 #define CAN_DLC_MPPT_B_STATUS 5 +#define CAN_DLC_MPPT_B_SWEEPMEASUREMENTS 6 #define CAN_DLC_MPPT_B_SETMODE 1 -#define CAN_DLC_MPPT_C_POWER 8 +#define CAN_DLC_MPPT_B_PERFORMSWEEP 5 +#define CAN_DLC_MPPT_B_SETOUTPUTVOLTAGELIMIT 2 +#define CAN_DLC_MPPT_B_SETOUTPUTCURRENTLIMIT 2 +#define CAN_DLC_MPPT_C_POWERMEASUREMENTS 8 #define CAN_DLC_MPPT_C_STATUS 5 +#define CAN_DLC_MPPT_C_SWEEPMEASUREMENTS 6 #define CAN_DLC_MPPT_C_SETMODE 1 -#define CAN_DLC_LWS_STANDARD 5 -#define CAN_DLC_SUPP_BATTERY_STATUS 8 -#define CAN_DLC_SUPP_BATTERY_CHARGER_STATUS 8 -#define CAN_DLC_BBPDU_STATUS 5 -#define CAN_DLC_BBPDU_SET_SWITCHES 4 -#define CAN_DLC_BBPDU_SET_CURRENT_LIMIT 4 -#define CAN_DLC_PUMP_STATUS_FLOWRATE 6 +#define CAN_DLC_MPPT_C_PERFORMSWEEP 5 +#define CAN_DLC_MPPT_C_SETOUTPUTVOLTAGELIMIT 2 +#define CAN_DLC_MPPT_C_SETOUTPUTCURRENTLIMIT 2 +#define CAN_DLC_SUPP_BATTERY_STATUS 5 +#define CAN_DLC_SUPP_BATTERY_CHARGER_STATUS 5 +#define CAN_DLC_PDU_STATUS_ARR 5 +#define CAN_DLC_PDU_SET_SWITCH_ARR 1 +#define CAN_DLC_PDU_SET_CURRENT_LIMIT_ARR 3 +#define CAN_DLC_PUMP_STATUS 6 #define CAN_DLC_COOLANT_TEMPERATURE 4 #define CAN_DLC_RADIATOR_FANSPEED 8 -#define CAN_DLC_LV_CARRIER_STATUS 2 -#define CAN_DLC_BRAKE_PRESSURE 8 -#define CAN_DLC_DISPLAY_CAMERAS_STATUS 2 +#define CAN_DLC_LV_CARRIER_STATUS 1 +#define CAN_DLC_BRAKE_PRESSURE_1 6 +#define CAN_DLC_BRAKE_PRESSURE_2 6 +#define CAN_DLC_DISPLAY_STATUS 2 #define CAN_DLC_TELEMETRY_STATUS 8 -#define CAN_DLC_LWS_CONFIG 2 /* ================= Value Table Enums ================= */ typedef enum { - BPS_STATUS_BPS_FAULT_DISCHARGING_OVERCURRENT = 16, - BPS_STATUS_BPS_FAULT_CHARGING_OVERCURRENT = 15, - BPS_STATUS_BPS_FAULT_ESTOP_3 = 14, - BPS_STATUS_BPS_FAULT_ESTOP_2 = 13, - BPS_STATUS_BPS_FAULT_ESTOP_1 = 12, - BPS_STATUS_BPS_FAULT_ARRAY_PCHG_CONTACTOR_SENSE = 11, - BPS_STATUS_BPS_FAULT_ARRAY_CONTACTOR_SENSE = 10, - BPS_STATUS_BPS_FAULT_HV_MINUS_CONTACTOR_SENSE = 9, - BPS_STATUS_BPS_FAULT_HV_PLUS_CONTACTOR_SENSE = 8, - BPS_STATUS_BPS_FAULT_WATCHDOG = 7, + BPS_STATUS_BPS_FAULT_DISCHARGING_OVERCURRENT = 17, + BPS_STATUS_BPS_FAULT_CHARGING_OVERCURRENT = 16, + BPS_STATUS_BPS_FAULT_ESTOP_3 = 15, + BPS_STATUS_BPS_FAULT_ESTOP_2 = 14, + BPS_STATUS_BPS_FAULT_ESTOP_1 = 13, + BPS_STATUS_BPS_FAULT_ARRAY_PCHG_CONTACTOR_SENSE = 12, + BPS_STATUS_BPS_FAULT_ARRAY_CONTACTOR_SENSE = 11, + BPS_STATUS_BPS_FAULT_HV_MINUS_CONTACTOR_SENSE = 10, + BPS_STATUS_BPS_FAULT_HV_PLUS_CONTACTOR_SENSE = 9, + BPS_STATUS_BPS_FAULT_SEGMENT_WATCHDOG = 8, + BPS_STATUS_BPS_FAULT_INTERNAL_WATCHDOG = 7, BPS_STATUS_BPS_FAULT_ARRAY_PRECHARGE_TIMEOUT = 6, BPS_STATUS_BPS_FAULT_ELCON = 5, BPS_STATUS_BPS_FAULT_OVERTEMPERATURE = 4, BPS_STATUS_BPS_FAULT_REGEN = 3, BPS_STATUS_BPS_FAULT_UNDERVOLTAGE = 2, BPS_STATUS_BPS_FAULT_OVERVOLTAGE = 1, - BPS_STATUS_BPS_FAULT_NO_FAULT = 0, + BPS_STATUS_BPS_FAULT_OK = 0, + BPS_STATUS_BPS_FAULT_AMPERES_WATCHDOG = 18, } bps_status_bps_fault_e; +typedef enum { + BPS_STATUS_BPS_CHARGE_OK_OK = 1, + BPS_STATUS_BPS_CHARGE_OK_NOT_OK = 0, +} bps_status_bps_charge_ok_e; + +typedef enum { + BPS_STATUS_BPS_REGEN_OK_OK = 1, + BPS_STATUS_BPS_REGEN_OK_NOT_OK = 0, +} bps_status_bps_regen_ok_e; + +typedef enum { + BPS_STATUS_HV_PLUS_CONTACTOR_STATE_CLOSED = 1, + BPS_STATUS_HV_PLUS_CONTACTOR_STATE_OPEN = 0, +} bps_status_hv_plus_contactor_state_e; + +typedef enum { + BPS_STATUS_HV_MINUS_CONTACTOR_STATE_CLOSED = 1, + BPS_STATUS_HV_MINUS_CONTACTOR_STATE_OPEN = 0, +} bps_status_hv_minus_contactor_state_e; + +typedef enum { + BPS_STATUS_ARRAY_CONTACTOR_STATE_CLOSED = 1, + BPS_STATUS_ARRAY_CONTACTOR_STATE_OPEN = 0, +} bps_status_array_contactor_state_e; + +typedef enum { + BPS_STATUS_ARRAY_PRECHARGE_CONTACTOR_STATE_CLOSED = 1, + BPS_STATUS_ARRAY_PRECHARGE_CONTACTOR_STATE_OPEN = 0, +} bps_status_array_precharge_contactor_state_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT0_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT0_STATUS_OK = 0, +} bps_status_bps_segment0_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT1_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT1_STATUS_OK = 0, +} bps_status_bps_segment1_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT2_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT2_STATUS_OK = 0, +} bps_status_bps_segment2_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT3_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT3_STATUS_OK = 0, +} bps_status_bps_segment3_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT4_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT4_STATUS_OK = 0, +} bps_status_bps_segment4_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT5_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT5_STATUS_OK = 0, +} bps_status_bps_segment5_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT6_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT6_STATUS_OK = 0, +} bps_status_bps_segment6_status_e; + +typedef enum { + BPS_STATUS_BPS_SEGMENT7_STATUS_FAULT = 1, + BPS_STATUS_BPS_SEGMENT7_STATUS_OK = 0, +} bps_status_bps_segment7_status_e; + +typedef enum { + BPS_VOLTAGE_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_OK = 1, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_NOT_OK = 0, +} bps_voltage_aggregate_arr_bps_tap_msg_wdog_e; + +typedef enum { + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, +} bps_voltage_aggregate_arr_bps_voltage_tap_fault_e; + +typedef enum { + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, +} bps_temperature_aggregate_arr_bps_temperature_tap_fault_e; + +typedef enum { + BPS_TEMP_RAWV_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_OK = 1, + BPS_TEMP_RAWV_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_NOT_OK = 0, +} bps_temp_rawv_aggregate_arr_bps_tap_msg_wdog_e; + typedef enum { VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE = 6, VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE = 5, @@ -104,128 +234,525 @@ typedef enum { } vcu_status_vcu_fault_e; typedef enum { - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_DRIVE_INPUTS_INVALID_ = 3, + VCU_STATUS_MOTOR_CONTACTOR_STATE_CLOSED = 1, + VCU_STATUS_MOTOR_CONTACTOR_STATE_OPEN = 0, +} vcu_status_motor_contactor_state_e; + +typedef enum { + VCU_STATUS_MOTOR_PRECHARGE_CONTACTOR_STATE_CLOSED = 1, + VCU_STATUS_MOTOR_PRECHARGE_CONTACTOR_STATE_OPEN = 0, +} vcu_status_motor_precharge_contactor_state_e; + +typedef enum { + VCU_STATUS_MOTOR_READY_OK = 1, + VCU_STATUS_MOTOR_READY_NOT_OK = 0, +} vcu_status_motor_ready_e; + +typedef enum { + VCU_STATUS_VCU_DRIVER_INPUT_OK_OK = 1, + VCU_STATUS_VCU_DRIVER_INPUT_OK_NOT_OK = 0, +} vcu_status_vcu_driver_input_ok_e; + +typedef enum { + VCU_STATUS_VCU_PEDALS_OK_OK = 1, + VCU_STATUS_VCU_PEDALS_OK_NOT_OK = 0, +} vcu_status_vcu_pedals_ok_e; + +typedef enum { + VCU_STATUS_VCU_REGEN_OK_OK = 1, + VCU_STATUS_VCU_REGEN_OK_NOT_OK = 0, +} vcu_status_vcu_regen_ok_e; + +typedef enum { + VCU_STATUS_VCU_REGEN_ACTIVE_ACTIVE = 1, + VCU_STATUS_VCU_REGEN_ACTIVE_INACTIVE = 0, +} vcu_status_vcu_regen_active_e; + +typedef enum { + VCU_STATUS_VCU_STEERING_ANGLE_OK_OK = 1, + VCU_STATUS_VCU_STEERING_ANGLE_OK_NOT_OK = 0, +} vcu_status_vcu_steering_angle_ok_e; + +typedef enum { + VCU_STATUS_VCU_FSM_STATE_VEHICLE_NOT_READY = 7, + VCU_STATUS_VCU_FSM_STATE_DISABLED = 6, + VCU_STATUS_VCU_FSM_STATE_CRUISE_CONTROL = 5, + VCU_STATUS_VCU_FSM_STATE_REGEN = 4, + VCU_STATUS_VCU_FSM_STATE_REVERSE_DRIVE = 3, + VCU_STATUS_VCU_FSM_STATE_NEUTRAL_DRIVE = 2, + VCU_STATUS_VCU_FSM_STATE_FORWARD_DRIVE = 1, + VCU_STATUS_VCU_FSM_STATE_INIT = 0, +} vcu_status_vcu_fsm_state_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_PCHG_OK_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_PCHG_OK_TRUE = 1, +} vcu_status_vcu_fsm_in_pchg_ok_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_BRAKE_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_BRAKE_TRUE = 1, +} vcu_status_vcu_fsm_in_brake_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_FORWARD_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_FORWARD_TRUE = 1, +} vcu_status_vcu_fsm_in_forward_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_NEUTRAL_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_NEUTRAL_TRUE = 1, +} vcu_status_vcu_fsm_in_neutral_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_REVERSE_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_REVERSE_TRUE = 1, +} vcu_status_vcu_fsm_in_reverse_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_REGEN_RDY_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_REGEN_RDY_TRUE = 1, +} vcu_status_vcu_fsm_in_regen_rdy_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_REGEN_ENABLE_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_REGEN_ENABLE_TRUE = 1, +} vcu_status_vcu_fsm_in_regen_enable_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_CRUISE_REQ_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_CRUISE_REQ_TRUE = 1, +} vcu_status_vcu_fsm_in_cruise_req_e; + +typedef enum { + VCU_STATUS_VCU_FSM_IN_REGEN_REQ_FALSE = 0, + VCU_STATUS_VCU_FSM_IN_REGEN_REQ_TRUE = 1, +} vcu_status_vcu_fsm_in_regen_req_e; + +typedef enum { + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_LIGHTING_BOARD_FAULT = 4, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_INVALID_DRIVER_INPUTS = 3, CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BPS_WATCHDOG = 2, - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_STEERING_ANGLE_SENSOR_WATCHDOG = 1, - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_NO_FAULT = 0, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BOSCH_LWS_WATCHDOG = 1, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_OK = 0, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_LIGHTING_BOARD_WATCHDOG = 5, } controls_status_controls_leader_fault_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_13_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_13_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_13_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_13_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_13_e; + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_WATCHDOG = 8, +} controls_status_lightingboard_front_status_e; + +typedef enum { + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_WATCHDOG = 8, +} controls_status_lightingboard_left_status_e; + +typedef enum { + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_WATCHDOG = 8, +} controls_status_lightingboard_right_status_e; + +typedef enum { + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LIGHT_COMMAND_WATCHDOG = 7, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_WATCHDOG = 8, +} controls_status_lightingboard_rear_status_e; + +typedef enum { + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LIGHT_COMMAND_WATCHDOG = 7, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_WATCHDOG = 8, +} controls_status_lightingboard_canopy_status_e; + +typedef enum { + PEDAL_STATUS_ACCELPEDAL_MAIN_FAULT_FAULT = 1, + PEDAL_STATUS_ACCELPEDAL_MAIN_FAULT_OK = 0, +} pedal_status_accelpedal_main_fault_e; + +typedef enum { + PEDAL_STATUS_ACCELPEDAL_REDUNDANT_FAULT_FAULT = 1, + PEDAL_STATUS_ACCELPEDAL_REDUNDANT_FAULT_OK = 0, +} pedal_status_accelpedal_redundant_fault_e; + +typedef enum { + PEDAL_STATUS_BRAKEPEDAL_MAIN_FAULT_FAULT = 1, + PEDAL_STATUS_BRAKEPEDAL_MAIN_FAULT_OK = 0, +} pedal_status_brakepedal_main_fault_e; + +typedef enum { + PEDAL_STATUS_BRAKEPEDAL_REDUNDANT_FAULT_FAULT = 1, + PEDAL_STATUS_BRAKEPEDAL_REDUNDANT_FAULT_OK = 0, +} pedal_status_brakepedal_redundant_fault_e; + +typedef enum { + DRIVER_INPUT_STATUS_IGNITION_ARRAY_SELECTED = 1, + DRIVER_INPUT_STATUS_IGNITION_ARRAY__ = 0, +} driver_input_status_ignition_array_e; + +typedef enum { + DRIVER_INPUT_STATUS_IGNITION_MOTOR_SELECTED = 1, + DRIVER_INPUT_STATUS_IGNITION_MOTOR__ = 0, +} driver_input_status_ignition_motor_e; + +typedef enum { + DRIVER_INPUT_STATUS_IGNITION_OFF_SELECTED = 1, + DRIVER_INPUT_STATUS_IGNITION_OFF__ = 0, +} driver_input_status_ignition_off_e; + +typedef enum { + DRIVER_INPUT_STATUS_CRUISE_ENABLE_ENABLED = 1, + DRIVER_INPUT_STATUS_CRUISE_ENABLE_DISABLED = 0, +} driver_input_status_cruise_enable_e; + +typedef enum { + DRIVER_INPUT_STATUS_CRUISE_SET_PRESSED = 1, + DRIVER_INPUT_STATUS_CRUISE_SET__ = 0, +} driver_input_status_cruise_set_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_14_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_14_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_14_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_14_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_14_e; + DRIVER_INPUT_STATUS_GEAR_FORWARD_SELECTED = 1, + DRIVER_INPUT_STATUS_GEAR_FORWARD__ = 0, +} driver_input_status_gear_forward_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_15_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_15_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_15_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_15_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_15_e; + DRIVER_INPUT_STATUS_GEAR_NEUTRAL_SELECTED = 1, + DRIVER_INPUT_STATUS_GEAR_NEUTRAL__ = 0, +} driver_input_status_gear_neutral_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_16_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_16_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_16_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_16_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_16_e; + DRIVER_INPUT_STATUS_GEAR_REVERSE_SELECTED = 1, + DRIVER_INPUT_STATUS_GEAR_REVERSE__ = 0, +} driver_input_status_gear_reverse_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_9_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_9_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_9_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_9_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_9_e; + DRIVER_INPUT_STATUS_HAZARD_PRESSED_ON = 1, + DRIVER_INPUT_STATUS_HAZARD_PRESSED_OFF = 0, +} driver_input_status_hazard_pressed_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_10_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_10_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_10_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_10_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_10_e; + DRIVER_INPUT_STATUS_HORN_PRESSED_ON = 1, + DRIVER_INPUT_STATUS_HORN_PRESSED_OFF = 0, +} driver_input_status_horn_pressed_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_11_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_11_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_11_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_11_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_11_e; + DRIVER_INPUT_STATUS_BLINKER_LEFT_SELECTED = 1, + DRIVER_INPUT_STATUS_BLINKER_LEFT__ = 0, +} driver_input_status_blinker_left_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_12_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_12_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_12_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_12_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_12_e; + DRIVER_INPUT_STATUS_BLINKER_RIGHT_SELECTED = 1, + DRIVER_INPUT_STATUS_BLINKER_RIGHT__ = 0, +} driver_input_status_blinker_right_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_5_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_5_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_5_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_5_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_5_e; + DRIVER_INPUT_STATUS_PUSHTOTALK_PRESSED_PRESSED = 1, + DRIVER_INPUT_STATUS_PUSHTOTALK_PRESSED__ = 0, +} driver_input_status_pushtotalk_pressed_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_6_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_6_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_6_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_6_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_6_e; + DRIVER_INPUT_STATUS_REGEN_ACTIVATE_PRESSED = 1, + DRIVER_INPUT_STATUS_REGEN_ACTIVATE__ = 0, +} driver_input_status_regen_activate_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_7_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_7_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_7_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_7_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_7_e; + DRIVER_INPUT_STATUS_REGEN_ENABLE_ENABLED = 1, + DRIVER_INPUT_STATUS_REGEN_ENABLE_DISABLED = 0, +} driver_input_status_regen_enable_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_8_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_8_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_8_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_8_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_8_e; + MPPT_A_STATUS_MPPT_MODE_FAULT = 6, + MPPT_A_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, + MPPT_A_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_INPUT_VOLTAGE = 0, +} mppt_a_status_mppt_mode_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_1_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_1_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_1_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_1_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_1_e; + MPPT_A_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, + MPPT_A_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, + MPPT_A_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, + MPPT_A_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, + MPPT_A_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, + MPPT_A_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, + MPPT_A_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, + MPPT_A_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, + MPPT_A_STATUS_MPPT_FAULT_OK = 0, +} mppt_a_status_mppt_fault_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_2_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_2_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_2_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_2_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_2_e; + MPPT_A_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, + MPPT_A_STATUS_MPPT_ENABLED_ENABLED = 1, + MPPT_A_STATUS_MPPT_ENABLED_DISABLED = 0, +} mppt_a_status_mppt_enabled_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_3_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_3_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_3_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_3_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_3_e; + MPPT_A_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, + MPPT_A_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, + MPPT_A_SETMODE_MPPT_SET_ENABLE_DISABLED = 0, +} mppt_a_setmode_mppt_set_enable_e; typedef enum { - BBPDU_SET_SWITCHES_HSS_CONTROL_4_DO_NOTHING_YOU_RE_STUPID = 3, - BBPDU_SET_SWITCHES_HSS_CONTROL_4_TURN_OFF = 2, - BBPDU_SET_SWITCHES_HSS_CONTROL_4_TURN_ON = 1, - BBPDU_SET_SWITCHES_HSS_CONTROL_4_DO_NOTHING_KEEP_CURRENT_STATE = 0, -} bbpdu_set_switches_hss_control_4_e; + MPPT_B_STATUS_MPPT_MODE_FAULT = 6, + MPPT_B_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, + MPPT_B_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_INPUT_VOLTAGE = 0, +} mppt_b_status_mppt_mode_e; typedef enum { - LWS_CONFIG_LWS_CCW_RESETS_CALIBRATION_STATUS = 5, - LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0_ = 3, -} lws_config_lws_ccw_e; + MPPT_B_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, + MPPT_B_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, + MPPT_B_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, + MPPT_B_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, + MPPT_B_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, + MPPT_B_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, + MPPT_B_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, + MPPT_B_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, + MPPT_B_STATUS_MPPT_FAULT_OK = 0, +} mppt_b_status_mppt_fault_e; + +typedef enum { + MPPT_B_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, + MPPT_B_STATUS_MPPT_ENABLED_ENABLED = 1, + MPPT_B_STATUS_MPPT_ENABLED_DISABLED = 0, +} mppt_b_status_mppt_enabled_e; + +typedef enum { + MPPT_B_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, + MPPT_B_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, + MPPT_B_SETMODE_MPPT_SET_ENABLE_DISABLED = 0, +} mppt_b_setmode_mppt_set_enable_e; + +typedef enum { + MPPT_C_STATUS_MPPT_MODE_FAULT = 6, + MPPT_C_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, + MPPT_C_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_INPUT_VOLTAGE = 0, +} mppt_c_status_mppt_mode_e; + +typedef enum { + MPPT_C_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, + MPPT_C_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, + MPPT_C_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, + MPPT_C_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, + MPPT_C_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, + MPPT_C_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, + MPPT_C_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, + MPPT_C_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, + MPPT_C_STATUS_MPPT_FAULT_OK = 0, +} mppt_c_status_mppt_fault_e; + +typedef enum { + MPPT_C_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, + MPPT_C_STATUS_MPPT_ENABLED_ENABLED = 1, + MPPT_C_STATUS_MPPT_ENABLED_DISABLED = 0, +} mppt_c_status_mppt_enabled_e; + +typedef enum { + MPPT_C_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, + MPPT_C_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, + MPPT_C_SETMODE_MPPT_SET_ENABLE_DISABLED = 0, +} mppt_c_setmode_mppt_set_enable_e; + +typedef enum { + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_UNKNOWN_FAULT = 5, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_CURRENT_CHARGE_ = 4, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_CURRENT_DISCHARGE_ = 3, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_VOLTAGE = 2, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_UNDER_VOLTAGE = 1, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OK = 0, +} supp_battery_status_supplemental_battery_fault_e; + +typedef enum { + SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_FAULT = 3, + SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_CHARGING_ = 2, + SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_CHARGE_COMPLETE = 1, + SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_CHARGE_DISABLED = 0, +} supp_battery_charger_status_suppcharger_status_e; + +typedef enum { + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PUMP = 12, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_MPPTS = 9, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_BATTERY = 8, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PEDALS = 5, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_HORN = 2, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_VCU = 0, +} pdu_status_arr_hss_channel_idx_e; + +typedef enum { + PDU_STATUS_ARR_HSS_FAULT_FAULT = 1, + PDU_STATUS_ARR_HSS_FAULT_OK = 0, +} pdu_status_arr_hss_fault_e; + +typedef enum { + PDU_STATUS_ARR_HSS_ENABLED_ENABLED = 1, + PDU_STATUS_ARR_HSS_ENABLED_DISABLED = 0, +} pdu_status_arr_hss_enabled_e; + +typedef enum { + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PUMP = 12, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_MPPTS = 9, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_BATTERY = 8, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PEDALS = 5, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_HORN = 2, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_VCU = 0, +} pdu_set_switch_arr_hss_channel_idx_e; + +typedef enum { + PDU_SET_SWITCH_ARR_HSS_SETSWITCH_TOGGLE_OFF = 2, + PDU_SET_SWITCH_ARR_HSS_SETSWITCH_TOGGLE_ON = 1, + PDU_SET_SWITCH_ARR_HSS_SETSWITCH_DO_NOTHING = 0, +} pdu_set_switch_arr_hss_setswitch_e; + +typedef enum { + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PUMP = 12, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_MPPTS = 9, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_BATTERY = 8, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PEDALS = 5, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_HORN = 2, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_VCU = 0, +} pdu_set_current_limit_arr_hss_channel_idx_e; + +typedef enum { + PUMP_STATUS_PUMP_FAULT_FAULT = 1, + PUMP_STATUS_PUMP_FAULT_OK = 0, +} pump_status_pump_fault_e; + +typedef enum { + LV_CARRIER_STATUS_LTC4421_HVDCDC_SELECTED_SELECTED = 1, + LV_CARRIER_STATUS_LTC4421_HVDCDC_SELECTED__ = 0, +} lv_carrier_status_ltc4421_hvdcdc_selected_e; + +typedef enum { + LV_CARRIER_STATUS_LTC4421_HVDCDC_FAULT_FAULT = 1, + LV_CARRIER_STATUS_LTC4421_HVDCDC_FAULT_OK = 0, +} lv_carrier_status_ltc4421_hvdcdc_fault_e; + +typedef enum { + LV_CARRIER_STATUS_LTC4421_HVDCDC_VALID_OK = 1, + LV_CARRIER_STATUS_LTC4421_HVDCDC_VALID_NOT_OK = 0, +} lv_carrier_status_ltc4421_hvdcdc_valid_e; + +typedef enum { + LV_CARRIER_STATUS_LTC4421_SUPPBATT_SELECTED_SELECTED = 1, + LV_CARRIER_STATUS_LTC4421_SUPPBATT_SELECTED__ = 0, +} lv_carrier_status_ltc4421_suppbatt_selected_e; + +typedef enum { + LV_CARRIER_STATUS_LTC4421_SUPPBATT_FAULT_FAULT = 1, + LV_CARRIER_STATUS_LTC4421_SUPPBATT_FAULT_OK = 0, +} lv_carrier_status_ltc4421_suppbatt_fault_e; + +typedef enum { + LV_CARRIER_STATUS_LTC4421_SUPPBATT_VALID_OK = 1, + LV_CARRIER_STATUS_LTC4421_SUPPBATT_VALID_NOT_OK = 0, +} lv_carrier_status_ltc4421_suppbatt_valid_e; + +typedef enum { + LV_CARRIER_STATUS_LV_EN_SUPPLEMENTALBATTERY_ENABLED = 1, + LV_CARRIER_STATUS_LV_EN_SUPPLEMENTALBATTERY_DISABLED = 0, +} lv_carrier_status_lv_en_supplementalbattery_e; + +typedef enum { + LV_CARRIER_STATUS_LV_EN_POWERSUPPLY_ENABLED = 1, + LV_CARRIER_STATUS_LV_EN_POWERSUPPLY_DISABLED = 0, +} lv_carrier_status_lv_en_powersupply_e; + +typedef enum { + BRAKE_PRESSURE_1_BRAKE_PRESSURE_FAULT_FAULT = 1, + BRAKE_PRESSURE_1_BRAKE_PRESSURE_FAULT_OK = 0, +} brake_pressure_1_brake_pressure_fault_e; + +typedef enum { + BRAKE_PRESSURE_2_BRAKE_PRESSURE_FAULT_FAULT = 1, + BRAKE_PRESSURE_2_BRAKE_PRESSURE_FAULT_OK = 0, +} brake_pressure_2_brake_pressure_fault_e; + +typedef enum { + DISPLAY_STATUS_CAMERA_STATUS_BACKUP_OK = 1, + DISPLAY_STATUS_CAMERA_STATUS_BACKUP_NOT_OK = 0, +} display_status_camera_status_backup_e; + +typedef enum { + DISPLAY_STATUS_CAMERA_STATUS_LEFT_OK = 1, + DISPLAY_STATUS_CAMERA_STATUS_LEFT_NOT_OK = 0, +} display_status_camera_status_left_e; + +typedef enum { + DISPLAY_STATUS_CAMERA_STATUS_RIGHT_OK = 1, + DISPLAY_STATUS_CAMERA_STATUS_RIGHT_NOT_OK = 0, +} display_status_camera_status_right_e; /* ================= Message Structs ================= */ @@ -239,57 +766,103 @@ typedef struct { uint8_t Array_Precharge_Contactor_State; uint32_t Main_Battery_Voltage; int16_t Main_Battery_Avg_Temperature; + uint8_t BPS_Segment0_Status; + int8_t BPS_Segment1_Status; + uint8_t BPS_Segment2_Status; + uint8_t BPS_Segment3_Status; + uint8_t BPS_Segment4_Status; + uint8_t BPS_Segment5_Status; + uint8_t BPS_Segment6_Status; + uint8_t BPS_Segment7_Status; } bps_status_t; typedef struct { uint8_t BPS_Tap_idx; + uint8_t BPS_Tap_Msg_WDog; uint16_t BPS_Voltage_Tap_Data; + uint8_t BPS_Voltage_Tap_Fault; + uint16_t BPS_Voltage_Tap_Age; +} bps_voltage_aggregate_arr_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; -} bps_aggregate_arr_t; + uint16_t BPS_Temperature_Tap_Age; + uint8_t BPS_Temperature_FrameID; +} bps_temperature_aggregate_arr_t; + +typedef struct { + uint8_t BPS_Tap_idx; + uint8_t BPS_Tap_Msg_WDog; + uint16_t BPS_Temperature_Tap_RawV; + uint8_t BPS_Temperature_FrameID; +} bps_temp_rawv_aggregate_arr_t; typedef struct { uint8_t VCU_Fault; uint8_t Motor_Contactor_State; uint8_t Motor_Precharge_Contactor_State; - uint8_t Motor_Ready_To_Drive; + uint8_t Motor_Ready; uint8_t VCU_Driver_Input_OK; uint8_t VCU_Pedals_OK; uint8_t VCU_Regen_OK; uint8_t VCU_Regen_Active; uint8_t VCU_Steering_Angle_OK; uint8_t VCU_FSM_State; - uint16_t VCU_FSM_Inputs; + uint8_t VCU_FSM_IN_PCHG_OK; + uint8_t VCU_FSM_IN_BRAKE; + uint8_t VCU_FSM_IN_FORWARD; + uint8_t VCU_FSM_IN_NEUTRAL; + uint8_t VCU_FSM_IN_REVERSE; + uint8_t VCU_FSM_IN_REGEN_RDY; + uint8_t VCU_FSM_IN_REGEN_ENABLE; + uint8_t VCU_FSM_IN_CRUISE_REQ; + uint8_t VCU_FSM_IN_REGEN_REQ; } vcu_status_t; typedef struct { uint8_t Controls_Leader_Fault; - uint16_t Controls_Lighting_Fault; + uint8_t LightingBoard_Front_Status; + uint8_t LightingBoard_Left_Status; + uint8_t LightingBoard_Right_Status; + uint8_t LightingBoard_Rear_Status; + uint8_t LightingBoard_Canopy_Status; } controls_status_t; typedef struct { - uint32_t Precharge_Battery_Voltage; - uint32_t Precharge_Motor_Voltage; + uint32_t BPS_Precharge_Battery_Voltage; + uint32_t BPS_Precharge_Array_Voltage; +} bps_precharge_voltages_t; + +typedef struct { + uint32_t VCU_Precharge_Battery_Voltage; + uint32_t VCU_Precharge_Motor_Voltage; } vcu_precharge_voltages_t; typedef struct { - uint8_t Accel_Pos_Main; - uint8_t Accel_Pos_Redundant; - uint8_t Brake_Pos_Main; - uint8_t Brake_Pos_Redundant; - uint8_t Accel_Pos_Main_Fault; - uint8_t Accel_Pos_Redundant_Fault; - uint8_t Brake_Pos_Main_Fault; - uint8_t Brake_Pos_Redundant_Fault; - uint8_t Brake_Pressure_1_Fault; - uint8_t Brake_Pressure_2_Fault; -} accel_brake_position_t; + uint8_t AccelPedal_Main_Pos; + uint8_t AccelPedal_Redundant_Pos; + uint8_t BrakePedal_Main_Pos; + uint8_t BrakePedal_Redundant_Pos; + uint8_t AccelPedal_Main_Fault; + uint8_t AccelPedal_Redundant_Fault; + uint8_t BrakePedal_Main_Fault; + uint8_t BrakePedal_Redundant_Fault; + uint8_t Pedals_FrameID; +} pedal_status_t; + +typedef struct { + uint16_t AccelPedal_Main_RawV; + uint16_t AccelPedal_Redundant_RawV; + uint8_t Pedals_FrameID; +} pedal_accel_rawv_t; typedef struct { - uint16_t Accel_Pos_Voltage_Main; - uint16_t Accel_Pos_Voltage_Redundant; - uint16_t Brake_Pos_Voltage_Main; - uint16_t Brake_Pos_Voltage_Redundant; -} accel_brake_position_voltage_t; + uint16_t BrakePedal_Main_RawV; + uint16_t BrakePedal_Redundant_RawV; + uint8_t Pedals_FrameID; +} pedal_brake_rawv_t; typedef struct { uint8_t Ignition_Array; @@ -310,11 +883,11 @@ typedef struct { } driver_input_status_t; typedef struct { - int16_t MPPT_Vin; - int16_t MPPT_Iin; - int16_t MPPT_Vout; - int16_t MPPT_Iout; -} mppt_a_power_t; + int16_t MPPT_Input_Voltage; + int16_t MPPT_Input_Current; + int16_t MPPT_Output_Voltage; + int16_t MPPT_Output_Current; +} mppt_a_powermeasurements_t; typedef struct { uint8_t MPPT_Mode; @@ -325,15 +898,35 @@ typedef struct { } mppt_a_status_t; typedef struct { - uint8_t Boost_Enable; + uint8_t MPPT_Sweep_Data_cnt; + int16_t MPPT_Sweep_Data_Current; + int16_t MPPT_Sweep_Data_Voltage; +} mppt_a_sweepmeasurements_t; + +typedef struct { + uint8_t MPPT_Set_Enable; } mppt_a_setmode_t; typedef struct { - int16_t MPPT_Vin; - int16_t MPPT_Iin; - int16_t MPPT_Vout; - int16_t MPPT_Iout; -} mppt_b_power_t; + int16_t MPPT_Set_Sweep_Start; + int16_t MPPT_Set_Sweep_End; + uint8_t MPPT_Set_Sweep_Size; +} mppt_a_performsweep_t; + +typedef struct { + int16_t MPPT_SetOutputVoltageLimit; +} mppt_a_setoutputvoltagelimit_t; + +typedef struct { + int16_t MPPT_SetOutputCurrentLimit; +} mppt_a_setoutputcurrentlimit_t; + +typedef struct { + int16_t MPPT_Input_Voltage; + int16_t MPPT_Input_Current; + int16_t MPPT_Output_Voltage; + int16_t MPPT_Output_Current; +} mppt_b_powermeasurements_t; typedef struct { uint8_t MPPT_Mode; @@ -344,15 +937,35 @@ typedef struct { } mppt_b_status_t; typedef struct { - uint8_t Boost_Enable; + uint8_t MPPT_Sweep_Data_cnt; + int16_t MPPT_Sweep_Data_Current; + int16_t MPPT_Sweep_Data_Voltage; +} mppt_b_sweepmeasurements_t; + +typedef struct { + uint8_t MPPT_Set_Enable; } mppt_b_setmode_t; typedef struct { - int16_t MPPT_Vin; - int16_t MPPT_Iin; - int16_t MPPT_Vout; - int16_t MPPT_Iout; -} mppt_c_power_t; + int16_t MPPT_Set_Sweep_Start; + int16_t MPPT_Set_Sweep_End; + uint8_t MPPT_Set_Sweep_Size; +} mppt_b_performsweep_t; + +typedef struct { + int16_t MPPT_SetOutputVoltageLimit; +} mppt_b_setoutputvoltagelimit_t; + +typedef struct { + int16_t MPPT_SetOutputCurrentLimit; +} mppt_b_setoutputcurrentlimit_t; + +typedef struct { + int16_t MPPT_Input_Voltage; + int16_t MPPT_Input_Current; + int16_t MPPT_Output_Voltage; + int16_t MPPT_Output_Current; +} mppt_c_powermeasurements_t; typedef struct { uint8_t MPPT_Mode; @@ -363,66 +976,65 @@ typedef struct { } mppt_c_status_t; typedef struct { - uint8_t Boost_Enable; + uint8_t MPPT_Sweep_Data_cnt; + int16_t MPPT_Sweep_Data_Current; + int16_t MPPT_Sweep_Data_Voltage; +} mppt_c_sweepmeasurements_t; + +typedef struct { + uint8_t MPPT_Set_Enable; } mppt_c_setmode_t; typedef struct { - int16_t LWS_Angle; - uint8_t LWS_Speed; - uint8_t LWS_OK; - uint8_t LWS_CAL; - uint8_t LWS_TRIM; -} lws_standard_t; + int16_t MPPT_Set_Sweep_Start; + int16_t MPPT_Set_Sweep_End; + uint8_t MPPT_Set_Sweep_Size; +} mppt_c_performsweep_t; + +typedef struct { + int16_t MPPT_SetOutputVoltageLimit; +} mppt_c_setoutputvoltagelimit_t; typedef struct { + int16_t MPPT_SetOutputCurrentLimit; +} mppt_c_setoutputcurrentlimit_t; + +typedef struct { + uint8_t Supplemental_Battery_Fault; uint16_t Supplemental_Battery_Voltage; + int16_t Supplemental_Battery_Current; } supp_battery_status_t; typedef struct { uint8_t SuppCharger_Status; - int16_t Supplemental_Battery_Current; uint16_t Supplemental_DCDC_Voltage; int16_t Supplemental_DCDC_Current; } supp_battery_charger_status_t; typedef struct { - uint8_t HSS_Channel; + uint8_t HSS_Channel_idx; uint8_t HSS_Fault; uint8_t HSS_Enabled; uint16_t HSS_Measured_Voltage; uint16_t HSS_Measured_Current; -} bbpdu_status_t; - -typedef struct { - uint8_t HSS_Control_13; - uint8_t HSS_Control_14; - uint8_t HSS_Control_15; - uint8_t HSS_Control_16; - uint8_t HSS_Control_9; - uint8_t HSS_Control_10; - uint8_t HSS_Control_11; - uint8_t HSS_Control_12; - uint8_t HSS_Control_5; - uint8_t HSS_Control_6; - uint8_t HSS_Control_7; - uint8_t HSS_Control_8; - uint8_t HSS_Control_1; - uint8_t HSS_Control_2; - uint8_t HSS_Control_3; - uint8_t HSS_Control_4; -} bbpdu_set_switches_t; - -typedef struct { - uint8_t HSS_Channel; +} pdu_status_arr_t; + +typedef struct { + uint8_t HSS_Channel_idx; + uint8_t HSS_SetSwitch; +} pdu_set_switch_arr_t; + +typedef struct { + uint8_t HSS_Channel_idx; uint16_t HSS_Current_Limit; -} bbpdu_set_current_limit_t; +} pdu_set_current_limit_arr_t; typedef struct { uint8_t Pump_DutyCycle; uint8_t Pump_Fault; uint16_t FlowRate_1; uint16_t FlowRate_2; -} pump_status_flowrate_t; +} pump_status_t; typedef struct { int16_t Coolant_Temperature_1; @@ -448,23 +1060,26 @@ typedef struct { } lv_carrier_status_t; typedef struct { - uint16_t Brake_Pressure_1; - uint16_t Brake_Pressure_1_Voltage; - uint16_t Brake_Pressure_2; - uint16_t Brake_Pressure_2_Voltage; -} brake_pressure_t; + uint16_t Brake_Pressure; + uint16_t Brake_Pressure_RawV; + uint8_t Brake_Pressure_Fault; + uint8_t Pedals_FrameID; +} brake_pressure_1_t; + +typedef struct { + uint16_t Brake_Pressure; + uint16_t Brake_Pressure_RawV; + uint8_t Brake_Pressure_Fault; + uint8_t Pedals_FrameID; +} brake_pressure_2_t; typedef struct { uint8_t Display_FrameRate; uint8_t Camera_Status_Backup; uint8_t Camera_Status_Left; uint8_t Camera_Status_Right; -} display_cameras_status_t; +} display_status_t; typedef struct { } telemetry_status_t; -typedef struct { - uint8_t LWS_CCW; -} lws_config_t; - diff --git a/Firmware/config/Inc/MotorCAN_can_msgs.h b/Firmware/config/Inc/MotorCAN_can_msgs.h index 0c5c5466..fb03a22d 100644 --- a/Firmware/config/Inc/MotorCAN_can_msgs.h +++ b/Firmware/config/Inc/MotorCAN_can_msgs.h @@ -15,8 +15,8 @@ #define CAN_ID_MC_MOTORVOLTAGEVECTORMEASUREMENT 0x425 #define CAN_ID_MC_MOTORCURRENTVECTORMEASUREMENT 0x426 #define CAN_ID_MC_BACKEMFMEASUREMENTPREDICTION 0x427 -#define CAN_ID_MC_15VRAILMEASUREMENT 0x428 -#define CAN_ID_MC_3V319VRAILMEASUREMENT 0x429 +#define CAN_ID_MC_15V_RAILMEASUREMENT 0x428 +#define CAN_ID_MC_3V3_19V_RAILMEASUREMENT 0x429 #define CAN_ID_MC_MOTOR_TEMPMEASUREMENT 0x42B #define CAN_ID_MC_DSPBOARDTEMPMEASUREMENT 0x42C #define CAN_ID_MC_ODOMETERBUSAHMEASUREMENT 0x42E @@ -35,14 +35,106 @@ #define CAN_DLC_MC_MOTORVOLTAGEVECTORMEASUREMENT 8 #define CAN_DLC_MC_MOTORCURRENTVECTORMEASUREMENT 8 #define CAN_DLC_MC_BACKEMFMEASUREMENTPREDICTION 8 -#define CAN_DLC_MC_15VRAILMEASUREMENT 8 -#define CAN_DLC_MC_3V319VRAILMEASUREMENT 8 +#define CAN_DLC_MC_15V_RAILMEASUREMENT 8 +#define CAN_DLC_MC_3V3_19V_RAILMEASUREMENT 8 #define CAN_DLC_MC_MOTOR_TEMPMEASUREMENT 8 #define CAN_DLC_MC_DSPBOARDTEMPMEASUREMENT 8 #define CAN_DLC_MC_ODOMETERBUSAHMEASUREMENT 8 #define CAN_DLC_MC_SLIPSPEEDMEASUREMENT 8 +/* ================= Value Table Enums ================= */ + +typedef enum { + MC_STATUS_MC_LIMIT_OUTPUTVOLTAGEPWM_LIMIT = 1, + MC_STATUS_MC_LIMIT_OUTPUTVOLTAGEPWM_OK = 0, +} mc_status_mc_limit_outputvoltagepwm_e; + +typedef enum { + MC_STATUS_MC_LIMIT_MOTORCURRENT_LIMIT = 1, + MC_STATUS_MC_LIMIT_MOTORCURRENT_OK = 0, +} mc_status_mc_limit_motorcurrent_e; + +typedef enum { + MC_STATUS_MC_LIMIT_VELOCITY_LIMIT = 1, + MC_STATUS_MC_LIMIT_VELOCITY_OK = 0, +} mc_status_mc_limit_velocity_e; + +typedef enum { + MC_STATUS_MC_LIMIT_BUSCURRENT_LIMIT = 1, + MC_STATUS_MC_LIMIT_BUSCURRENT_OK = 0, +} mc_status_mc_limit_buscurrent_e; + +typedef enum { + MC_STATUS_MC_LIMIT_BUSVOLTAGEUPPER_LIMIT = 1, + MC_STATUS_MC_LIMIT_BUSVOLTAGEUPPER_OK = 0, +} mc_status_mc_limit_busvoltageupper_e; + +typedef enum { + MC_STATUS_MC_LIMIT_BUSVOLTAGELOWER_LIMIT = 1, + MC_STATUS_MC_LIMIT_BUSVOLTAGELOWER_OK = 0, +} mc_status_mc_limit_busvoltagelower_e; + +typedef enum { + MC_STATUS_MC_LIMIT_MOTORTEMP_LIMIT = 1, + MC_STATUS_MC_LIMIT_MOTORTEMP_OK = 0, +} mc_status_mc_limit_motortemp_e; + +typedef enum { + MC_STATUS_MC_LIMIT_RESERVED_LIMIT = 1, + MC_STATUS_MC_LIMIT_RESERVED_OK = 0, +} mc_status_mc_limit_reserved_e; + +typedef enum { + MC_STATUS_MC_FAULT_HARDWAREOVERCURRENT_FAULT = 1, + MC_STATUS_MC_FAULT_HARDWAREOVERCURRENT_OK = 0, +} mc_status_mc_fault_hardwareovercurrent_e; + +typedef enum { + MC_STATUS_MC_FAULT_SOFTWAREOVERCURRENT_FAULT = 1, + MC_STATUS_MC_FAULT_SOFTWAREOVERCURRENT_OK = 0, +} mc_status_mc_fault_softwareovercurrent_e; + +typedef enum { + MC_STATUS_MC_FAULT_DCBUSOVERVOLTAGE_FAULT = 1, + MC_STATUS_MC_FAULT_DCBUSOVERVOLTAGE_OK = 0, +} mc_status_mc_fault_dcbusovervoltage_e; + +typedef enum { + MC_STATUS_MC_FAULT_BADMOTORPOSITIONHALLSEQ_FAULT = 1, + MC_STATUS_MC_FAULT_BADMOTORPOSITIONHALLSEQ_OK = 0, +} mc_status_mc_fault_badmotorpositionhallseq_e; + +typedef enum { + MC_STATUS_MC_FAULT_WATCHDOGCAUSEDLASTRESET_FAULT = 1, + MC_STATUS_MC_FAULT_WATCHDOGCAUSEDLASTRESET_OK = 0, +} mc_status_mc_fault_watchdogcausedlastreset_e; + +typedef enum { + MC_STATUS_MC_FAULT_CONFIGREAD_FAULT = 1, + MC_STATUS_MC_FAULT_CONFIGREAD_OK = 0, +} mc_status_mc_fault_configread_e; + +typedef enum { + MC_STATUS_MC_FAULT_15VRAILUNDERVOLTAGE_FAULT = 1, + MC_STATUS_MC_FAULT_15VRAILUNDERVOLTAGE_OK = 0, +} mc_status_mc_fault_15vrailundervoltage_e; + +typedef enum { + MC_STATUS_MC_FAULT_DESATURATIONFAULT_FAULT = 1, + MC_STATUS_MC_FAULT_DESATURATIONFAULT_OK = 0, +} mc_status_mc_fault_desaturationfault_e; + +typedef enum { + MC_STATUS_MC_FAULT_MOTOROVERSPEED_FAULT = 1, + MC_STATUS_MC_FAULT_MOTOROVERSPEED_OK = 0, +} mc_status_mc_fault_motoroverspeed_e; + +typedef enum { + MC_STATUS_MC_FAULT_RESERVED_FAULT = 1, + MC_STATUS_MC_FAULT_RESERVED_OK = 0, +} mc_status_mc_fault_reserved_e; + /* ================= Message Structs ================= */ typedef struct { @@ -119,12 +211,12 @@ typedef struct { typedef struct { float MC_Supply15V; -} mc_15vrailmeasurement_t; +} mc_15v_railmeasurement_t; typedef struct { float MC_Supply1V9; float MC_Supply3V3; -} mc_3v319vrailmeasurement_t; +} mc_3v3_19v_railmeasurement_t; typedef struct { float MC_MotorTemp; diff --git a/Firmware/config/Inc/SteeringCAN_can_msgs.h b/Firmware/config/Inc/SteeringCAN_can_msgs.h new file mode 100644 index 00000000..9788e492 --- /dev/null +++ b/Firmware/config/Inc/SteeringCAN_can_msgs.h @@ -0,0 +1,55 @@ +#pragma once + +#include + +/* ================= CAN ID Macros ================= */ + +#define CAN_ID_LWS_STANDARD 0x2B0 +#define CAN_ID_LWS_CONFIG 0x7C0 + +/* ================= CAN Length Macros ================= */ + +#define CAN_DLC_LWS_STANDARD 5 +#define CAN_DLC_LWS_CONFIG 2 + + +/* ================= Value Table Enums ================= */ + +typedef enum { + LWS_STANDARD_LWS_FAULT_INTERNAL_FAULT = 1, + LWS_STANDARD_LWS_FAULT_OK = 0, +} lws_standard_lws_fault_e; + +typedef enum { + LWS_STANDARD_LWS_CALIBRATIONSTAUS_SENSOR_CALIBRATED = 1, + LWS_STANDARD_LWS_CALIBRATIONSTAUS_SENSOR_NOT_CALIBRATED = 0, +} lws_standard_lws_calibrationstaus_e; + +typedef enum { + LWS_STANDARD_LWS_TRIMMING_STATUS_SENSOR_TRIMMED = 1, + LWS_STANDARD_LWS_TRIMMING_STATUS_FAULT_SENSOR_NOT_TRIMMED = 0, +} lws_standard_lws_trimming_status_e; + +typedef enum { + LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0_ = 3, + LWS_CONFIG_LWS_CCW_RESETS_CALIBRATION_STATUS = 5, +} lws_config_lws_ccw_e; + +/* ================= Message Structs ================= */ + +typedef struct { + int16_t LWS_Angle; + uint8_t LWS_Speed; + uint8_t LWS_Fault; + uint8_t LWS_CalibrationStaus; + uint8_t LWS_Trimming_Status; + uint8_t LWS_SF1_5; + uint8_t LWS_MSG_CNT; + uint8_t LWS_CHK_SUM; +} lws_standard_t; + +typedef struct { + uint8_t LWS_CCW; + uint16_t LWS_RES; +} lws_config_t; + From f74c1c4fa4c47cca353083d2bf3439b70f86c032 Mon Sep 17 00:00:00 2001 From: Adiv Padgilwar Date: Thu, 9 Apr 2026 01:55:43 -0500 Subject: [PATCH 05/27] changed carcan stuff to motor can change back --- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSM.h | 6 +- Firmware/Tasks/Inc/InitTask.h | 3 + Firmware/Tasks/Src/FSMTask.c | 11 +- Firmware/Tasks/Src/InitTask.c | 136 +++++++---------- Firmware/Tasks/Src/MotorTelemetryTask.c | 18 +-- Firmware/Tasks/Src/UpdateFSMInputsTask.c | 29 +++- Firmware/Tasks/Src/VCUStatusTask.c | 24 ++- Firmware/config/Inc/can1_recv_entries.h | 10 +- Firmware/tests/fsm_test.c | 1 + Firmware/tests/temp | 167 +++++++++++++++++++++ KiCAD-Bild | 1 + VehicleControlUnitLib/UTSVT-KiCadLibraries | 1 + 13 files changed, 305 insertions(+), 104 deletions(-) create mode 100644 Firmware/tests/fsm_test.c create mode 100644 Firmware/tests/temp create mode 160000 KiCAD-Bild create mode 160000 VehicleControlUnitLib/UTSVT-KiCadLibraries diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 7a651473..003be222 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 7a651473f1901789600333fb205b034ab7eb03b9 +Subproject commit 003be222e33208b44442ef74886978349fc971ab diff --git a/Firmware/Tasks/Inc/FSM.h b/Firmware/Tasks/Inc/FSM.h index 131a4b92..0d375c48 100644 --- a/Firmware/Tasks/Inc/FSM.h +++ b/Firmware/Tasks/Inc/FSM.h @@ -68,7 +68,7 @@ typedef struct { } MocoState_t; extern MocoState_t FSM[NUM_STATES]; -extern MocoState_t currentState; +extern MocoState_t current_state; typedef struct { driver_input_status_t driver_input; @@ -92,13 +92,15 @@ void fsm_recover(void); void fsm_set_all_inputs(EventBits_t mask); void fsm_set_input(EventBits_t mask); -void fsm_get_inputs(void); +uint16_t fsm_get_inputs(void); bool fsm_is_over_rollover_speed(void); void Task_UpdateControlStatus(void *args); +void FSM_TaskInit(); void Task_FSM(void *args); void Task_BroadcastVCUStatus(void *args); +void Task_UpdateControlStatus(void *args __attribute__((unused))); float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, uint8_t out_max); diff --git a/Firmware/Tasks/Inc/InitTask.h b/Firmware/Tasks/Inc/InitTask.h index 79c259e0..37ee27db 100644 --- a/Firmware/Tasks/Inc/InitTask.h +++ b/Firmware/Tasks/Inc/InitTask.h @@ -15,6 +15,9 @@ #define MOTOR_TELEMETRY_TASK_STACK_SIZE configMINIMAL_STACK_SIZE #define CAN_TX_TELEMETRY_STACK_SIZE configMINIMAL_STACK_SIZE +#define FSM_TASK_STACK_SIZE configMINIMAL_STACK_SIZE +#define VCU_STATUS_TASK_STACK_SIZE configMINIMAL_STACK_SIZE + extern StaticTask_t FaultHandlerTask_Buffer; extern StackType_t FaultHandlerTask_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 70f01f7a..9ce590b2 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -47,6 +47,11 @@ static void handle_state_disabled(void); // static void rebuild_bitfield(void); static float apply_rollover_limit(float requested_current); +//must be called Before the FSM task gets called +void FSM_TaskInit(){ + fsmInputGroup = xEventGroupCreateStatic(&fsmInputBuffer); +} + void fsm_init(void) { FSM[STATE_INIT].stateHandler = handle_state_init; FSM[FORWARD_DRIVE].stateHandler = handle_state_forward; @@ -81,10 +86,12 @@ void fsm_set_input(EventBits_t mask) { xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); } -void fsm_get_inputs(void) { - xEventGroupGetBits(fsmInputGroup); +uint16_t fsm_get_inputs(void) { + return (uint16_t)xEventGroupGetBits(fsmInputGroup); } + + // goofy ahh logic, uses lut static float apply_rollover_limit(float requested_current) { int deg = abs((int)g_data_read->lws.LWS_Angle) / 10; diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 14725f1f..48295f5b 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -1,4 +1,9 @@ #include "InitTask.h" +#include "FSM.h" +#include "VCUStatusTask.h" +#include "PrechargeTask.h" +#include "StatusLEDs.h" + StaticTask_t FaultHandlerTask_Buffer; StackType_t FaultHandlerTask_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; @@ -24,70 +29,14 @@ StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; StaticTask_t VCUStatus_Task_Buffer; StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; -// void Task_Init() { -// __HAL_RCC_SYSCFG_CLK_ENABLE(); -// __HAL_RCC_PWR_CLK_ENABLE(); - -// Init_UART_Printf(); - -// MotorSafeBits_Init(); - -// MotorCAN_Init(); -// CarCAN_Init(); - - xTaskCreateStatic( - Task_FaultHandler, // Task function - "FaultHandler", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - FAULT_HANDLER_THREAD_PRIO, // Task priority - FaultHandlerTask_Stack, // Task handle - &FaultHandlerTask_Buffer // Static task buffer (optional) - ); - -// hprecharge_task = xTaskCreateStatic( -// Task_Precharge, // Task function -// "Precharge", // Name of the task (for debugging) -// configMINIMAL_STACK_SIZE, // Stack size in words -// NULL, // Task input parameter -// PRECHARGE_THREAD_PRIO, // Task priority -// Precharge_Task_Stack, // Task handle -// &Precharge_Task_Buffer // Static task buffer (optional) -// ); - -// // xTaskCreateStatic( -// // Task_MotorControl, // Task function -// // "Motor Control Thread", // Name of the task (for debugging) -// // configMINIMAL_STACK_SIZE, // Stack size in words -// // NULL, // Task input parameter -// // MOTOR_CONTROL_THREAD_PRIO, // Task priority -// // Motor_Control_Task_Stack, // Task handle -// // &Motor_Control_Task_Buffer // Static task buffer (optional) -// // ); - -// xTaskCreateStatic( -// Task_MotorTelemetry, // Task function -// "Motor Telemetry Thread", // Name of the task (for debugging) -// configMINIMAL_STACK_SIZE, // Stack size in words -// NULL, // Task input parameter -// MOTOR_TELEMETRY_THREAD_PRIO, // Task priority -// Motor_Telemetry_Task_Stack, // Task handle -// &Motor_Telemetry_Task_Buffer // Static task buffer (optional) -// ); - -// // xTaskCreateStatic( -// // Task_CanTxTelemetry, // Task function -// // "Can TX Telemetry Thread", // Name of the task (for debugging) -// // configMINIMAL_STACK_SIZE, // Stack size in words -// // NULL, // Task input parameter -// // CAN_TX_TELEMETRY_THREAD_PRIO, // Task priority -// // Can_Tx_Telemetry_Task_Stack, // Task handle -// // &Can_Tx_Telemetry_Task_Buffer // Static task buffer (optional) -// // ); - -// vTaskDelete(NULL); -// } +StaticTask_t UpdateControlStatus_Task_Buffer; +StackType_t UpdateControlStatus_Task_Stack[FSM_TASK_STACK_SIZE]; +#define FSM_THREAD_PRIO (tskIDLE_PRIORITY + 2) +#define VCU_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 1) +#define FAULT_HANDLER_THREAD_PRIO (tskIDLE_PRIORITY + 4) +#define PRECHARGE_THREAD_PRIO (tskIDLE_PRIORITY + 3) +#define UPDATE_CONTROL_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 2) void Task_Init() { __HAL_RCC_SYSCFG_CLK_ENABLE(); @@ -100,25 +49,31 @@ void Task_Init() { MotorCAN_Init(); CarCAN_Init(); - xTaskCreateStatic( - Task_FaultHandler, // Task function - "FaultHandler", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - FAULT_HANDLER_THREAD_PRIO, // Task priority - FaultHandlerTask_Stack, // Task handle - &FaultHandlerTask_Buffer // Static task buffer (optional) - ); - - xTaskCreateStatic( - Task_Precharge, // Task function - "Precharge", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - PRECHARGE_THREAD_PRIO, // Task priority - Precharge_Task_Stack, // Task handle - &Precharge_Task_Buffer // Static task buffer (optional) - ); + FSM_TaskInit(); + + //These two need to be here when we are only testing vcu status + faults_init(); + Init_PrechargeTask(); + + // xTaskCreateStatic( + // Task_FaultHandler, // Task function + // "FaultHandler", // Name of the task (for debugging) + // configMINIMAL_STACK_SIZE, // Stack size in words + // NULL, // Task input parameter + // FAULT_HANDLER_THREAD_PRIO, // Task priority + // FaultHandlerTask_Stack, // Task handle + // &FaultHandlerTask_Buffer // Static task buffer (optional) + // ); + + // xTaskCreateStatic( + // Task_Precharge, // Task function + // "Precharge", // Name of the task (for debugging) + // configMINIMAL_STACK_SIZE, // Stack size in words + // NULL, // Task input parameter + // PRECHARGE_THREAD_PRIO, // Task priority + // Precharge_Task_Stack, // Task handle + // &Precharge_Task_Buffer // Static task buffer (optional) + // ); xTaskCreateStatic( Task_FSM, // Task function @@ -130,6 +85,8 @@ void Task_Init() { &FSM_Task_Buffer // Static task buffer (optional) ); + + xTaskCreateStatic( Task_BroadcastVCUStatus, // Task function "VCU Status Thread", // Name of the task (for debugging) @@ -140,5 +97,20 @@ void Task_Init() { &VCUStatus_Task_Buffer // Static task buffer (optional) ); + xTaskCreateStatic( + Task_UpdateControlStatus, // Task function + "Update Control Status Thread", // Name of the task (for debugging) + configMINIMAL_STACK_SIZE, // Stack size in words + NULL, // Task input parameter + UPDATE_CONTROL_STATUS_THREAD_PRIO, // Task priority + UpdateControlStatus_Task_Stack, // Task handle + &UpdateControlStatus_Task_Buffer // Static task buffer (optional) + ); + + // while(1){ + // LED_toggle(HB); + // HAL_Delay(100); + // } + vTaskDelete(NULL); } \ No newline at end of file diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index 15cb5af0..bdd2cdfc 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -38,17 +38,17 @@ void MotorTelemetryTask_Init(void) { } } -void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, - can_rx_payload_t recv_payload) { - // only forward motorCAN messages to CarCAN - if (motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance) { +// void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, +// can_rx_payload_t recv_payload) { +// // only forward motorCAN messages to CarCAN +// if (motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance) { - BaseType_t higherPriorityTaskWoken = pdFALSE; +// BaseType_t higherPriorityTaskWoken = pdFALSE; - xQueueSendFromISR(motorTelemetryQueue, &recv_payload, &higherPriorityTaskWoken); - // don't yield at the end of this since the rest of the ISR needs to run - } -} +// xQueueSendFromISR(motorTelemetryQueue, &recv_payload, &higherPriorityTaskWoken); +// // don't yield at the end of this since the rest of the ISR needs to run +// } +// } void Task_MotorTelemetry() { diff --git a/Firmware/Tasks/Src/UpdateFSMInputsTask.c b/Firmware/Tasks/Src/UpdateFSMInputsTask.c index c10f454e..9785e85d 100644 --- a/Firmware/Tasks/Src/UpdateFSMInputsTask.c +++ b/Firmware/Tasks/Src/UpdateFSMInputsTask.c @@ -33,17 +33,39 @@ static void rebuild_inputs(void) { void Task_UpdateControlStatus(void *args __attribute__((unused))) { TickType_t last = xTaskGetTickCount(); + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = 0x123; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = FDCAN_DLC_BYTES_8; + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + tx_header.MessageMarker = 0; + uint8_t buf[8] = {0}; + + while (1) { // update from can FSMDataIn_t *update = g_data_write; MotorCAN_Recv_Status(&update->motor_status, 0); MotorCAN_Recv_Velocity(&update->motor_velocity, 0); + + //making these motor can should be CARCAN + CarCAN_Recv_BPS_Status(&update->bps_status, 0); CarCAN_Recv_Pedals_Position(&update->accel_brake, 0); CarCAN_Recv_Controls_Status(&update->controls_status, 0); - CarCAN_Recv_Driver_Input(&update->driver_input, 0); + if (CarCAN_Recv_Driver_Input(&update->driver_input, 0) == CAN_OK) { + // Handle driver input + buf[0] = update->driver_input.Gear_Forward; + tx_header.Identifier = 0x123; + CarCAN_Send(&tx_header, buf, sizeof(buf)); + } CarCAN_Recv_LWS(&update->lws, 0); + FSMDataIn_t *tmp; taskENTER_CRITICAL(); tmp = g_data_read; @@ -51,6 +73,11 @@ void Task_UpdateControlStatus(void *args __attribute__((unused))) { g_data_write = tmp; taskEXIT_CRITICAL(); + + buf[0] = g_data_read->driver_input.Gear_Forward; + tx_header.Identifier = 0x321; + CarCAN_Send(&tx_header, buf, sizeof(buf)); + rebuild_inputs(); vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); } diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index e6ed1d10..6aadb948 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -5,11 +5,13 @@ #include "Contactors.h" #include "FSM.h" #include "Watchdogs.h" +#include "StatusLEDs.h" // VCU_Status 0x10 3 bytes 100ms void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { uint8_t buf[3]; + while (1) { // Byte 0: VCU_Fault — map internal faults to DBC enum uint8_t vcu_fault = VCU_STATUS_VCU_FAULT_NO_FAULT; @@ -34,6 +36,8 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { buf[0] = vcu_fault; + + // Byte 1: status bits per DBC positions 8-14 bool pedals_ok = !g_data_read->accel_brake.AccelPedal_Main_Fault && !g_data_read->accel_brake.AccelPedal_Redundant_Fault && @@ -45,20 +49,26 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { bool steering_angle_ok = g_data_read->lws.LWS_Fault == 0; + // while(1){ + // LED_toggle(HB); + // vTaskDelay(pdMS_TO_TICKS(100)); + + // } buf[1] = ((uint8_t)contactor_get_sense(MOTOR_CONTACTOR) << 0) | // Motor_Contactor_State ((uint8_t)contactor_get_sense(MOTOR_PRE_CONTACTOR) << 1) | // Motor_Precharge_Contactor_State ((uint8_t) (contactor_get_sense(MOTOR_PRE_CONTACTOR) && vcu_fault == 0) << 2) | // Motor_Ready_To_Drive ((uint8_t)driver_input_ok << 3) | // VCU_Driver_Input_OK ((uint8_t)pedals_ok << 4) | // VCU_Pedals_OK - ((uint8_t)!!(fsm_get_car_status() & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK - ((uint8_t)(currentState.stateName == REGEN) << 6) | // VCU_Regen_Active + ((uint8_t)!!(fsm_get_inputs() & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK + ((uint8_t)(current_state.stateName == REGEN) << 6) | // VCU_Regen_Active ((uint8_t)steering_angle_ok << 7); // VCU_Steering_Angle_OK (not implemented, set to OK) // Byte 2: VCU_FSM_State bits [3:0] - buf[2] = (uint8_t)(currentState.stateName & 0x0FU); - - buf[3] = fsm_get_car_status; //this supposed to have fsm states as well but stateName covers it for now + buf[2] = (uint8_t)(current_state.stateName & 0x0FU); + buf[3] = fsm_get_inputs() ; //this supposed to have fsm states as well but stateName covers it for now + + FDCAN_TxHeaderTypeDef tx_header = {0}; tx_header.Identifier = CAN_ID_VCU_STATUS; tx_header.IdType = FDCAN_STANDARD_ID; @@ -70,7 +80,9 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; tx_header.MessageMarker = 0; - CarCAN_Send(&tx_header, buf, sizeof(buf)); + MotorCAN_Send(&tx_header, buf, sizeof(buf)); + + LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(100)); } } \ No newline at end of file diff --git a/Firmware/config/Inc/can1_recv_entries.h b/Firmware/config/Inc/can1_recv_entries.h index 428780ed..6c12fe62 100644 --- a/Firmware/config/Inc/can1_recv_entries.h +++ b/Firmware/config/Inc/can1_recv_entries.h @@ -1,3 +1,11 @@ // CAN_RECV_ENTRY(ID, SIZE, CIRCULAR) -CAN_RECV_ENTRY(0x421, 5, true) \ No newline at end of file +CAN_RECV_ENTRY(0x321, 8, true) // 801 - test +CAN_RECV_ENTRY(0x001, 8, true) // BPS_STATUS +CAN_RECV_ENTRY(0x650, 8, true) // BRAKE_PRESSURE +CAN_RECV_ENTRY(0x600, 8, true) // LV_CARRIER_STATUS +CAN_RECV_ENTRY(0x2B0, 8, true) // LWS_STANDARD +CAN_RECV_ENTRY(0x060, 8, true) // DRIVER_INPUT_STATUS +CAN_RECV_ENTRY(0x050, 8, true) // ACCEL_BRAKE_POSITION +CAN_RECV_ENTRY(0x021, 8, true) // PRECHARGE_VOLTAGES +CAN_RECV_ENTRY(0x015, 8, true) // CONTROLS_STATUS diff --git a/Firmware/tests/fsm_test.c b/Firmware/tests/fsm_test.c new file mode 100644 index 00000000..1eb3893b --- /dev/null +++ b/Firmware/tests/fsm_test.c @@ -0,0 +1 @@ +//this'll test the actual FSM implementation and also flash the appropriate LEDs for the VCU status diff --git a/Firmware/tests/temp b/Firmware/tests/temp new file mode 100644 index 00000000..f9669276 --- /dev/null +++ b/Firmware/tests/temp @@ -0,0 +1,167 @@ +// #include "CANbus.h" +#include "stm32xx_hal.h" +// #include "inits.h" +// #include "StatusLEDs.h" +#include "pinDefs.h" +#include "can_utils.h" + +StaticTask_t task_buffer; +StackType_t task_stack[512]; + +static void task(void *pvParameters){ + + int test_id = 0x321; + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = test_id; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = FDCAN_DLC_BYTES_8; + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + tx_header.MessageMarker = 0; + + FDCAN_RxHeaderTypeDef rx_header; + uint8_t rx_data[64]; + + + // carcan for receiving + hfdcan3->Instance = FDCAN3; + hfdcan3->Init.ClockDivider = FDCAN_CLOCK_DIV1; + hfdcan3->Init.FrameFormat = FDCAN_FRAME_CLASSIC; + hfdcan3->Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; + hfdcan3->Init.AutoRetransmission = DISABLE; + hfdcan3->Init.TransmitPause = DISABLE; + hfdcan3->Init.ProtocolException = DISABLE; + hfdcan3->Init.NominalPrescaler = 20; + hfdcan3->Init.NominalSyncJumpWidth = 1; + hfdcan3->Init.NominalTimeSeg1 = 13; + hfdcan3->Init.NominalTimeSeg2 = 2; + hfdcan3->Init.DataPrescaler = 1; + hfdcan3->Init.DataSyncJumpWidth = 1; + hfdcan3->Init.DataTimeSeg1 = 1; + hfdcan3->Init.DataTimeSeg2 = 1; + hfdcan3->Init.StdFiltersNbr = 1; + hfdcan3->Init.ExtFiltersNbr = 0; + hfdcan3->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; + + FDCAN_FilterTypeDef carcan_filter_config = {0}; + carcan_filter_config.IdType = FDCAN_STANDARD_ID; + carcan_filter_config.FilterIndex = 0; + carcan_filter_config.FilterType = FDCAN_FILTER_MASK; + carcan_filter_config.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; + carcan_filter_config.FilterID1 = 0x000; + carcan_filter_config.FilterID2 = 0x000; + + can_fd_init(hfdcan3, &carcan_filter_config); + can_fd_start(hfdcan3); + + + // send x1234 to 0x11 + uint8_t tx_data[8] = {0}; + tx_data[0] = 0x12; + tx_data[1] = 0x34; + tx_data[2] = 0x56; + tx_data[3] = 0x78; + tx_data[4] = 0x9A; + tx_data[5] = 0xBC; + tx_data[6] = 0xDE; + tx_data[7] = 0xFF; + + while(1){ + + + HAL_GPIO_WritePin(HB_LED_PORT, HB_LED_PIN, GPIO_PIN_RESET); + if (can_fd_send(hfdcan3, &tx_header, tx_data, portMAX_DELAY) == CAN_ERR){ + Error_Handler(); + } + + vTaskDelay(pdMS_TO_TICKS(500)); + + if(can_fd_recv(hfdcan3, test_id, &rx_header, rx_data, portMAX_DELAY) != CAN_ERR){ + HAL_GPIO_WritePin(HB_LED_PORT, HB_LED_PIN, GPIO_PIN_SET); + vTaskDelay(pdMS_TO_TICKS(1000)); + + if(rx_data[0] == 0x12){ + for(int i = 0; i < 50; i++){ + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + vTaskDelay(pdMS_TO_TICKS(100)); + } + } + } + + HAL_GPIO_WritePin(HB_LED_PORT, HB_LED_PIN, GPIO_PIN_RESET); + vTaskDelay(pdMS_TO_TICKS(1000)); + + // TODO: add status LED + // HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + // vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +void can_error_handler(){ + while(1){ + // LED_set(MOTOR_FAULT, GPIO_PIN_SET); + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + vTaskDelay(pdMS_TO_TICKS(200)); + } +} + +// Initialize clock for heartbeat LED port +void Heartbeat_Clock_Init() { + switch ((uint32_t)HB_LED_PORT) { + case (uint32_t)GPIOA: + __HAL_RCC_GPIOA_CLK_ENABLE(); + break; + case (uint32_t)GPIOB: + __HAL_RCC_GPIOB_CLK_ENABLE(); + break; + case (uint32_t)GPIOC: + __HAL_RCC_GPIOC_CLK_ENABLE(); + break; + } +} + +int main(){ + HAL_Init(); + + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + // LEDs_init(); + + // Heartbeat LED on VCU is PB14 + GPIO_InitTypeDef led_config = { + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL, + .Pin = HB_LED_PIN + }; + + Heartbeat_Clock_Init(); // enable clock for HB_LED_PORT + HAL_GPIO_Init(HB_LED_PORT, &led_config); // initialize HB_LED_PORT with led_config + + + + // if(Motor_CANBus_Init() != CAN_OK){ + // can_error_handler(); + // } + + + xTaskCreateStatic( + task, + "task", + 512, + NULL, + tskIDLE_PRIORITY + 2, + task_stack, + &task_buffer); + + + vTaskStartScheduler(); + + while(1){ + + } +} \ No newline at end of file diff --git a/KiCAD-Bild b/KiCAD-Bild new file mode 160000 index 00000000..c4713377 --- /dev/null +++ b/KiCAD-Bild @@ -0,0 +1 @@ +Subproject commit c471337769c733b3db7bfcbf68b52eb2a727f807 diff --git a/VehicleControlUnitLib/UTSVT-KiCadLibraries b/VehicleControlUnitLib/UTSVT-KiCadLibraries new file mode 160000 index 00000000..6eca31ff --- /dev/null +++ b/VehicleControlUnitLib/UTSVT-KiCadLibraries @@ -0,0 +1 @@ +Subproject commit 6eca31ff4859b771102042364b7d2128e8f0f684 From 2f29cb48b4ff468caca92846869feb76f751f3fe Mon Sep 17 00:00:00 2001 From: Adiv Padgilwar Date: Thu, 9 Apr 2026 02:00:22 -0500 Subject: [PATCH 06/27] tony a bum --- Firmware/Drivers/Src/CANbus.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 2956b901..afa73eb4 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -195,12 +195,12 @@ can_status_t CarCAN_Init(void) { } can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { - return can_fd_send(carfdcan, header, data, delay_ticks); + return can_fd_send(motorfdcan, header, data, delay_ticks); } can_status_t CarCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { - return can_fd_recv(carfdcan, id, header, data, delay_ticks); + return can_fd_recv(motorfdcan, id, header, data, delay_ticks); } can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { @@ -210,7 +210,7 @@ can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { uint8_t bps_status_rx_data[CAN_DLC_BPS_STATUS] = {0}; can_status_t result = - can_fd_recv(carfdcan, CAN_ID_BPS_STATUS, &header, bps_status_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_BPS_STATUS, &header, bps_status_rx_data, delay); if (result == CAN_OK) { out->BPS_Fault = bps_status_rx_data[0]; @@ -236,7 +236,7 @@ can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t dela uint8_t controls_status_rx_data[CAN_DLC_CONTROLS_STATUS] = {0}; can_status_t result = - can_fd_recv(carfdcan, CAN_ID_CONTROLS_STATUS, &header, controls_status_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_CONTROLS_STATUS, &header, controls_status_rx_data, delay); if (result == CAN_OK) { out->Controls_Leader_Fault = controls_status_rx_data[0]; @@ -253,7 +253,7 @@ can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay) { uint8_t steering_angle_rx_data[CAN_DLC_LWS_STANDARD] = {0}; can_status_t result = - can_fd_recv(carfdcan, CAN_ID_LWS_STANDARD, &header, steering_angle_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_LWS_STANDARD, &header, steering_angle_rx_data, delay); if (result == CAN_OK) { // Angle: Byte0 (LSB), Byte1 (MSB) @@ -280,7 +280,7 @@ can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t del uint8_t driver_input_rx_data[CAN_DLC_DRIVER_INPUT_STATUS] = {0}; can_status_t result = - can_fd_recv(carfdcan, CAN_ID_DRIVER_INPUT_STATUS, &header, driver_input_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_DRIVER_INPUT_STATUS, &header, driver_input_rx_data, delay); if (result == CAN_OK) { out->Ignition_Array = driver_input_rx_data[0] & (0x01); @@ -311,7 +311,7 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) uint8_t pedals_pos_rx_data[CAN_DLC_PEDAL_STATUS] = {0}; can_status_t result = - can_fd_recv(carfdcan, CAN_ID_PEDAL_STATUS, &header, pedals_pos_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_PEDAL_STATUS, &header, pedals_pos_rx_data, delay); if (result == CAN_OK) { out->AccelPedal_Main_Pos = pedals_pos_rx_data[0]; @@ -348,7 +348,7 @@ can_status_t CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { // TODO: actually pack ts can_status_t result = - can_fd_send(carfdcan, &header, vcu_status_tx_data, delay); + can_fd_send(motorfdcan, &header, vcu_status_tx_data, delay); return result; } From e13ce68a7c1ec8ac5bf0225bf2a6e5d71be46bf0 Mon Sep 17 00:00:00 2001 From: Adiv Padgilwar Date: Thu, 9 Apr 2026 14:28:02 -0500 Subject: [PATCH 07/27] less goonery --- Firmware/Drivers/Src/CANbus.c | 16 ++++++++-------- Firmware/Embedded-Sharepoint | 2 +- Firmware/config/Inc/can3_recv_entries.h | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index afa73eb4..2956b901 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -195,12 +195,12 @@ can_status_t CarCAN_Init(void) { } can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { - return can_fd_send(motorfdcan, header, data, delay_ticks); + return can_fd_send(carfdcan, header, data, delay_ticks); } can_status_t CarCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks) { - return can_fd_recv(motorfdcan, id, header, data, delay_ticks); + return can_fd_recv(carfdcan, id, header, data, delay_ticks); } can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { @@ -210,7 +210,7 @@ can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { uint8_t bps_status_rx_data[CAN_DLC_BPS_STATUS] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_BPS_STATUS, &header, bps_status_rx_data, delay); + can_fd_recv(carfdcan, CAN_ID_BPS_STATUS, &header, bps_status_rx_data, delay); if (result == CAN_OK) { out->BPS_Fault = bps_status_rx_data[0]; @@ -236,7 +236,7 @@ can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t dela uint8_t controls_status_rx_data[CAN_DLC_CONTROLS_STATUS] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_CONTROLS_STATUS, &header, controls_status_rx_data, delay); + can_fd_recv(carfdcan, CAN_ID_CONTROLS_STATUS, &header, controls_status_rx_data, delay); if (result == CAN_OK) { out->Controls_Leader_Fault = controls_status_rx_data[0]; @@ -253,7 +253,7 @@ can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay) { uint8_t steering_angle_rx_data[CAN_DLC_LWS_STANDARD] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_LWS_STANDARD, &header, steering_angle_rx_data, delay); + can_fd_recv(carfdcan, CAN_ID_LWS_STANDARD, &header, steering_angle_rx_data, delay); if (result == CAN_OK) { // Angle: Byte0 (LSB), Byte1 (MSB) @@ -280,7 +280,7 @@ can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t del uint8_t driver_input_rx_data[CAN_DLC_DRIVER_INPUT_STATUS] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_DRIVER_INPUT_STATUS, &header, driver_input_rx_data, delay); + can_fd_recv(carfdcan, CAN_ID_DRIVER_INPUT_STATUS, &header, driver_input_rx_data, delay); if (result == CAN_OK) { out->Ignition_Array = driver_input_rx_data[0] & (0x01); @@ -311,7 +311,7 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) uint8_t pedals_pos_rx_data[CAN_DLC_PEDAL_STATUS] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_PEDAL_STATUS, &header, pedals_pos_rx_data, delay); + can_fd_recv(carfdcan, CAN_ID_PEDAL_STATUS, &header, pedals_pos_rx_data, delay); if (result == CAN_OK) { out->AccelPedal_Main_Pos = pedals_pos_rx_data[0]; @@ -348,7 +348,7 @@ can_status_t CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { // TODO: actually pack ts can_status_t result = - can_fd_send(motorfdcan, &header, vcu_status_tx_data, delay); + can_fd_send(carfdcan, &header, vcu_status_tx_data, delay); return result; } diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 003be222..19f05990 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 003be222e33208b44442ef74886978349fc971ab +Subproject commit 19f0599068ca94bbb29c3fbf5aee6aa8deff0dbe diff --git a/Firmware/config/Inc/can3_recv_entries.h b/Firmware/config/Inc/can3_recv_entries.h index ed6347ad..aa976b5e 100644 --- a/Firmware/config/Inc/can3_recv_entries.h +++ b/Firmware/config/Inc/can3_recv_entries.h @@ -1,5 +1,17 @@ // CAN_RECV_ENTRY(ID, SIZE, CIRCULAR) -CAN_RECV_ENTRY(0x001, 5, false) -CAN_RECV_ENTRY(0x002, 8, false) -CAN_RECV_ENTRY(0x003, 3, false) +// CAN_RECV_ENTRY(0x001, 5, false) +// CAN_RECV_ENTRY(0x002, 8, false) +// CAN_RECV_ENTRY(0x003, 3, false) + + +CAN_RECV_ENTRY(0x321, 8, true) // 801 - test +CAN_RECV_ENTRY(0x001, 8, true) // BPS_STATUS +CAN_RECV_ENTRY(0x650, 8, true) // BRAKE_PRESSURE +CAN_RECV_ENTRY(0x600, 8, true) // LV_CARRIER_STATUS +CAN_RECV_ENTRY(0x2B0, 8, true) // LWS_STANDARD +CAN_RECV_ENTRY(0x060, 8, true) // DRIVER_INPUT_STATUS +CAN_RECV_ENTRY(0x050, 8, true) // ACCEL_BRAKE_POSITION +CAN_RECV_ENTRY(0x021, 8, true) // PRECHARGE_VOLTAGES +CAN_RECV_ENTRY(0x015, 8, true) // CONTROLS_STATUS + From 7ab0d8e4b191f60646be29d1c4aee87d9b041efa Mon Sep 17 00:00:00 2001 From: Akshay Date: Fri, 10 Apr 2026 03:14:19 -0500 Subject: [PATCH 08/27] can stuff fixed + wrote tests, vcu status works --- Firmware/Drivers/Inc/FaultBits.h | 75 ---------- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/InitTask.h | 54 ++++--- Firmware/Tasks/Inc/UpdateFSMInputsTask.h | 2 +- Firmware/Tasks/Src/FaultHandlerTask.c | 132 ------------------ Firmware/Tasks/Src/InitTask.c | 114 ++++++++------- Firmware/Tasks/Src/UpdateFSMInputsTask.c | 31 ++-- Firmware/Tasks/Src/VCUStatusTask.c | 7 +- Firmware/config/Inc/can1_recv_entries.h | 16 +-- Firmware/config/Inc/can3_recv_entries.h | 26 ++-- Firmware/tests/carcan_test.c | 110 +++++++++++++++ Firmware/tests/fsminputs_test | 69 +++++++++ .../tests/{canbus_test.c => motorcan_test.c} | 36 ++++- Firmware/tests/vcustatus_test.c | 59 ++++++++ 14 files changed, 399 insertions(+), 334 deletions(-) create mode 100644 Firmware/tests/carcan_test.c create mode 100644 Firmware/tests/fsminputs_test rename Firmware/tests/{canbus_test.c => motorcan_test.c} (71%) create mode 100644 Firmware/tests/vcustatus_test.c diff --git a/Firmware/Drivers/Inc/FaultBits.h b/Firmware/Drivers/Inc/FaultBits.h index 6431b6b7..51c36edc 100644 --- a/Firmware/Drivers/Inc/FaultBits.h +++ b/Firmware/Drivers/Inc/FaultBits.h @@ -1,78 +1,3 @@ -// #pragma once - -// #include "inits.h" -// #include -// #include - -// #define ALL_FAULT_BITS ((1UL << NUM_FAULTS) - 1UL) - -// // The max number of fault bits is dependent on the configUSE_16_BIT_TICKS defined in FreeRTOS.h -// #if (configUSE_16_BIT_TICKS == 0) -// #define MAX_FAULT_BITS 24U -// #else -// #define MAX_FAULT_BITS 8U -// #endif - -// typedef enum -// { -// MOTOR_GREATER_THAN_BATTERY_FAULT, // Motor voltage is greater than battery voltage -// BATTERY_OVERVOLTAGE_FAULT, // Battery voltage is greater than OVERVOLTAGE_THRESHOLD_MV -// BATTERY_UNDERVOLTAGE_FAULT, // Battery voltage is less than UNDERVOLTAGE_THRESHOLD_MV -// MOTOR_SENSE_TIMEOUT_FAULT, // Motor contactor didn't close within expected time -// PRECHARGE_SENSE_TIMEOUT_FAULT, // Precharge contactor didn't close within expected time -// PRECHARGE_TIMEOUT_FAULT, // Precharge sequence took too long -// CALLBACK_FAULT, // Contactor state did not match expected state after being set -// MOTOR_SENSE_MISMATCH_FAULT, // Motor contactor sense pin reading does not match contactor state -// PRECHARGE_SENSE_MISMATCH_FAULT, // Precharge contactor sense pin reading does not match contactor state -// NUM_FAULTS -// } fault_bit_t; - -// /* Convert enum to bitmask */ -// #define FAULT_BIT(fault) (1UL << (fault)) - -// /* Mask containing only the actual fault bits (exclude precharge state bits) -// Precharge state enum values are the first entries, so keep bits from -// MOTOR_GREATER_THAN_BATTERY_FAULT upwards. */ -// #define FAULTS_ONLY_MASK ((EventBits_t)(ALL_FAULT_BITS & ~((1UL << (MOTOR_GREATER_THAN_BATTERY_FAULT)) - 1UL))) - -// /* Legacy name kept for callers that expect a mask of fault bits */ -// #define FAULT_BITMASK (FAULTS_ONLY_MASK) - -// _Static_assert(NUM_FAULTS <= MAX_FAULT_BITS, "Too many fault bits for EventGroup"); - -// /** -// * @brief Initializes fault bitmap -// * -// * @param none -// * @return 0 on failure, 1 on success -// */ -// uint8_t faultBits_init(void); - -// /** -// * @brief Set a fault in the fault bitmap -// * -// * @param bit which fault is being set -// * @return none -// */ -// void set_faultBit(fault_bit_t bit); - -// /** -// * @brief Wait for a fault to be set -// * -// * @param bit which fault to wait for, pass NUM_FAULTS if waiting for any fault -// * @param xTicksToWait delay when waiting -// * @return the event bit that was set -// */ -// EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait); - -// /** -// * @brief Set a fault in the fault bitmap from an ISR -// * -// * @param bit which fault is being set -// * @return none -// */ -// void set_faultBitFromISR(fault_bit_t bit); - #pragma once #include "FreeRTOS.h" diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 19f05990..6a0b60dc 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 19f0599068ca94bbb29c3fbf5aee6aa8deff0dbe +Subproject commit 6a0b60dc497015a0b2b069ec8af1a29375bc290a diff --git a/Firmware/Tasks/Inc/InitTask.h b/Firmware/Tasks/Inc/InitTask.h index 37ee27db..01e7bbc7 100644 --- a/Firmware/Tasks/Inc/InitTask.h +++ b/Firmware/Tasks/Inc/InitTask.h @@ -9,14 +9,15 @@ #include "CANbus.h" #define INIT_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -#define FAULT_HANDLER_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -#define PRECHARGE_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -#define MOTOR_CONTROL_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -#define MOTOR_TELEMETRY_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -#define CAN_TX_TELEMETRY_STACK_SIZE configMINIMAL_STACK_SIZE +#define FAULT_HANDLER_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 +#define PRECHARGE_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 +#define FSM_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 +#define VCU_STATUS_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 +#define UPDATE_FSM_INPUTS_STACK_SIZE configMINIMAL_STACK_SIZE * 2 -#define FSM_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -#define VCU_STATUS_TASK_STACK_SIZE configMINIMAL_STACK_SIZE +// #define MOTOR_CONTROL_TASK_STACK_SIZE configMINIMAL_STACK_SIZE +// #define MOTOR_TELEMETRY_TASK_STACK_SIZE configMINIMAL_STACK_SIZE +// #define CAN_TX_TELEMETRY_STACK_SIZE configMINIMAL_STACK_SIZE extern StaticTask_t FaultHandlerTask_Buffer; @@ -28,20 +29,37 @@ extern StackType_t Precharge_Task_Stack[PRECHARGE_TASK_STACK_SIZE]; extern StaticTask_t Init_Task_Buffer; extern StackType_t Init_Task_Stack[INIT_TASK_STACK_SIZE]; -extern StaticTask_t Motor_Control_Task_Buffer; -extern StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; +extern StaticTask_t FSM_Task_Buffer; +extern StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; -extern StaticTask_t Motor_Telemetry_Task_Buffer; -extern StackType_t Motor_Telemetry_Task_Stack[MOTOR_TELEMETRY_TASK_STACK_SIZE]; +extern StaticTask_t VCUStatus_Task_Buffer; +extern StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; -extern StaticTask_t Can_Tx_Telemetry_Task_Buffer; -extern StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; +extern StaticTask_t UpdateFSMInputs_Task_Buffer; +extern StackType_t UpdateFSMInputs_Task_Stack[FSM_TASK_STACK_SIZE]; + +// extern StaticTask_t Motor_Control_Task_Buffer; +// extern StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; + +// extern StaticTask_t Motor_Telemetry_Task_Buffer; +// extern StackType_t Motor_Telemetry_Task_Stack[MOTOR_TELEMETRY_TASK_STACK_SIZE]; + +// extern StaticTask_t Can_Tx_Telemetry_Task_Buffer; +// extern StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; + + +#define FAULT_HANDLER_THREAD_PRIO (tskIDLE_PRIORITY + 4) +#define PRECHARGE_THREAD_PRIO (tskIDLE_PRIORITY + 3) +#define UPDATE_FSM_INPUTS_THREAD_PRIO (tskIDLE_PRIORITY + 2) +#define FSM_THREAD_PRIO (tskIDLE_PRIORITY + 2) +#define UPDATE_CONTROL_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 2) +#define VCU_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 1) + + +// #define MOTOR_CONTROL_THREAD_PRIO (tskIDLE_PRIORITY + 2) +// #define MOTOR_TELEMETRY_THREAD_PRIO (tskIDLE_PRIORITY + 1) +// #define CAN_TX_TELEMETRY_THREAD_PRIO (tskIDLE_PRIORITY + 1) -#define FAULT_HANDLER_THREAD_PRIO (tskIDLE_PRIORITY + 4) -#define PRECHARGE_THREAD_PRIO (tskIDLE_PRIORITY + 3) -#define MOTOR_CONTROL_THREAD_PRIO (tskIDLE_PRIORITY + 2) -#define MOTOR_TELEMETRY_THREAD_PRIO (tskIDLE_PRIORITY + 1) -#define CAN_TX_TELEMETRY_THREAD_PRIO (tskIDLE_PRIORITY + 1) // Period the fault thread runs at (once a fault is active) #define FAULT_LOOP_PERIOD_MS 500 diff --git a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h index 92f7517e..cd396435 100644 --- a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h +++ b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h @@ -7,4 +7,4 @@ #define BRAKE_THRESH 42.0f // percent #define BRAKE_THRESH_HYST 30.0f // percent -void Task_UpdateFSMInputs(); +void Task_UpdateFSMInputs(void *args __attribute__((unused))); diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index 808f2b88..36abb93e 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -1,135 +1,3 @@ -// #include "FaultHandlerTask.h" -// #include "PrechargeTask.h" // for hprecharge_task handle - -// #define FAULT_LOOP_PRINTF_DELAY_MS 10000 - -// #define FAULT_PRINTF_COUNTER (FAULT_LOOP_PRINTF_DELAY_MS / FAULT_LOOP_PERIOD_MS) - -// EventBits_t fault_bits = 0; - -// void Init_FaultHandlerTask() { -// if (!faults_init()) { -// // Fault bit initialization failed -// Error_Handler(); -// } -// } - -// void Kill_Precharge_Task() { -// if (hprecharge_task != NULL) { -// vTaskDelete(hprecharge_task); -// } -// } - -// static void print_fault() { -// switch (fault_bits) // compare against individual bitmasks -// { -// case FAULT_BIT(FAULT_ID_MOTOR_GT_BATTERY): -// printf("Fault: Motor Voltage Greater Than Battery Voltage\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_BATTERY_OVERVOLTAGE): -// printf("Fault: Battery Overvoltage\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_BATTERY_UNDERVOLTAGE): -// printf("Fault: Battery Undervoltage\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_TIMEOUT): -// printf("Fault: Motor Sense Timeout\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_TIMEOUT): -// printf("Fault: Precharge Sense Timeout\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_PRECHARGE_TIMEOUT): -// printf("Fault: Precharge Sequence Timeout\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK): -// printf("Fault: Contactor Sense Fault\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_MISMATCH): -// printf("Fault: Motor Sense Mismatch\r\n"); -// break; -// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_MISMATCH): -// printf("Fault: Precharge Sense Mismatch\r\n"); -// break; -// default: -// printf("Fault: Unknown\r\n"); -// break; -// } -// } - -// void Fault_Loop() { -// uint32_t fault_printf_debug_counter = 0; -// while (1) { -// fault_printf_debug_counter++; - -// if (fault_printf_debug_counter >= FAULT_PRINTF_COUNTER) { -// print_fault(); -// fault_printf_debug_counter = 0; -// } - -// LED_toggle(HB); -// vTaskDelay(FAULT_LOOP_PERIOD_MS); -// } -// } - -// void Set_Fault_LED() { -// switch (fault_bits) // compare against individual bitmasks -// { -// case FAULT_BIT(FAULT_ID_MOTOR_GT_BATTERY): -// LED_set(CAR_BPSFAULT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_BATTERY_OVERVOLTAGE): -// LED_set(CAR_BPSFAULT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_BATTERY_UNDERVOLTAGE): -// LED_set(CAR_BPSFAULT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_TIMEOUT): -// LED_set(MOTOR_SENSE_TIMEOUT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_TIMEOUT): -// LED_set(PRECHARGE_SENSE_TIMEOUT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_PRECHARGE_TIMEOUT): -// LED_set(PRECHARGE_TIMEOUT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK): -// LED_set(CAR_BPSFAULT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_MOTOR_SENSE_MISMATCH): -// LED_set(CAR_BPSFAULT, LED_ON); -// break; -// case FAULT_BIT(FAULT_ID_PRECHARGE_SENSE_MISMATCH): -// LED_set(CAR_BPSFAULT, LED_ON); -// break; -// default: -// break; -// } -// } - -// void Task_FaultHandler() { -// Init_FaultHandlerTask(); - -// while (true) { -// fault_bits = faults_wait(FAULT_ID_COUNT, portMAX_DELAY); - -// if (fault_bits != 0) { -// Kill_Precharge_Task(); -// contactor_emergency_open_all(); - -// // prevents the motor from running -// clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); -// clear_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); - -// printf("Fault Handler triggered with bitmask: 0x%02lX\r\n", fault_bits); - -// Set_Fault_LED(); -// Fault_Loop(); -// } - -// vTaskDelay(1000); -// } -// } - #include "FaultHandlerTask.h" #include "PrechargeTask.h" // for hprecharge_task handle #include "Watchdogs.h" diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 48295f5b..61092935 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -2,9 +2,14 @@ #include "FSM.h" #include "VCUStatusTask.h" #include "PrechargeTask.h" +#include "UpdateFSMInputsTask.h" #include "StatusLEDs.h" +/* ===================== Stack Size Definitions ===================== */ + + +/* ===================== Static Task Buffers ===================== */ StaticTask_t FaultHandlerTask_Buffer; StackType_t FaultHandlerTask_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; @@ -14,6 +19,15 @@ StackType_t Precharge_Task_Stack[PRECHARGE_TASK_STACK_SIZE]; StaticTask_t Init_Task_Buffer; StackType_t Init_Task_Stack[INIT_TASK_STACK_SIZE]; +StaticTask_t FSM_Task_Buffer; +StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; + +StaticTask_t VCUStatus_Task_Buffer; +StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; + +StaticTask_t UpdateFSMInputs_Task_Buffer; +StackType_t UpdateFSMInputs_Task_Stack[UPDATE_FSM_INPUTS_STACK_SIZE]; + // StaticTask_t Motor_Control_Task_Buffer; // StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; @@ -23,22 +37,8 @@ StackType_t Init_Task_Stack[INIT_TASK_STACK_SIZE]; // StaticTask_t Can_Tx_Telemetry_Task_Buffer; // StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; -StaticTask_t FSM_Task_Buffer; -StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; - -StaticTask_t VCUStatus_Task_Buffer; -StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; - -StaticTask_t UpdateControlStatus_Task_Buffer; -StackType_t UpdateControlStatus_Task_Stack[FSM_TASK_STACK_SIZE]; -#define FSM_THREAD_PRIO (tskIDLE_PRIORITY + 2) -#define VCU_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 1) -#define FAULT_HANDLER_THREAD_PRIO (tskIDLE_PRIORITY + 4) -#define PRECHARGE_THREAD_PRIO (tskIDLE_PRIORITY + 3) -#define UPDATE_CONTROL_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 2) - -void Task_Init() { +void Task_Init(void) { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); @@ -51,63 +51,61 @@ void Task_Init() { FSM_TaskInit(); - //These two need to be here when we are only testing vcu status + // Required for VCU status testing faults_init(); Init_PrechargeTask(); - // xTaskCreateStatic( - // Task_FaultHandler, // Task function - // "FaultHandler", // Name of the task (for debugging) - // configMINIMAL_STACK_SIZE, // Stack size in words - // NULL, // Task input parameter - // FAULT_HANDLER_THREAD_PRIO, // Task priority - // FaultHandlerTask_Stack, // Task handle - // &FaultHandlerTask_Buffer // Static task buffer (optional) - // ); - - // xTaskCreateStatic( - // Task_Precharge, // Task function - // "Precharge", // Name of the task (for debugging) - // configMINIMAL_STACK_SIZE, // Stack size in words - // NULL, // Task input parameter - // PRECHARGE_THREAD_PRIO, // Task priority - // Precharge_Task_Stack, // Task handle - // &Precharge_Task_Buffer // Static task buffer (optional) - // ); + xTaskCreateStatic( + Task_FaultHandler, + "FaultHandler", + FAULT_HANDLER_TASK_STACK_SIZE, + NULL, + FAULT_HANDLER_THREAD_PRIO, + FaultHandlerTask_Stack, + &FaultHandlerTask_Buffer + ); xTaskCreateStatic( - Task_FSM, // Task function - "FSM Thread", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - FSM_THREAD_PRIO, // Task priority - FSM_Task_Stack, // Task handle - &FSM_Task_Buffer // Static task buffer (optional) + Task_Precharge, + "Precharge", + PRECHARGE_TASK_STACK_SIZE, + NULL, + PRECHARGE_THREAD_PRIO, + Precharge_Task_Stack, + &Precharge_Task_Buffer ); - + xTaskCreateStatic( + Task_FSM, + "FSM Thread", + FSM_TASK_STACK_SIZE, + NULL, + FSM_THREAD_PRIO, + FSM_Task_Stack, + &FSM_Task_Buffer + ); xTaskCreateStatic( - Task_BroadcastVCUStatus, // Task function - "VCU Status Thread", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - VCU_STATUS_THREAD_PRIO, // Task priority - VCUStatus_Task_Stack, // Task handle - &VCUStatus_Task_Buffer // Static task buffer (optional) + Task_BroadcastVCUStatus, + "VCU Status Thread", + VCU_STATUS_TASK_STACK_SIZE, + NULL, + VCU_STATUS_THREAD_PRIO, + VCUStatus_Task_Stack, + &VCUStatus_Task_Buffer ); xTaskCreateStatic( - Task_UpdateControlStatus, // Task function - "Update Control Status Thread", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - UPDATE_CONTROL_STATUS_THREAD_PRIO, // Task priority - UpdateControlStatus_Task_Stack, // Task handle - &UpdateControlStatus_Task_Buffer // Static task buffer (optional) + Task_UpdateFSMInputs, + "Update FSM Inputs Thread", + UPDATE_FSM_INPUTS_STACK_SIZE, + NULL, + UPDATE_FSM_INPUTS_THREAD_PRIO, + UpdateFSMInputs_Task_Stack, + &UpdateFSMInputs_Task_Buffer ); - // while(1){ + // while (1) { // LED_toggle(HB); // HAL_Delay(100); // } diff --git a/Firmware/Tasks/Src/UpdateFSMInputsTask.c b/Firmware/Tasks/Src/UpdateFSMInputsTask.c index 9785e85d..241572fb 100644 --- a/Firmware/Tasks/Src/UpdateFSMInputsTask.c +++ b/Firmware/Tasks/Src/UpdateFSMInputsTask.c @@ -31,29 +31,28 @@ static void rebuild_inputs(void) { fsm_set_all_inputs(s); } -void Task_UpdateControlStatus(void *args __attribute__((unused))) { +void Task_UpdateFSMInputs(void *args __attribute__((unused))) { TickType_t last = xTaskGetTickCount(); - FDCAN_TxHeaderTypeDef tx_header = {0}; - tx_header.Identifier = 0x123; - tx_header.IdType = FDCAN_STANDARD_ID; - tx_header.TxFrameType = FDCAN_DATA_FRAME; - tx_header.DataLength = FDCAN_DLC_BYTES_8; - tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header.BitRateSwitch = FDCAN_BRS_OFF; - tx_header.FDFormat = FDCAN_CLASSIC_CAN; - tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header.MessageMarker = 0; + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = 0x123; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = FDCAN_DLC_BYTES_8; + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + tx_header.MessageMarker = 0; uint8_t buf[8] = {0}; - while (1) { // update from can FSMDataIn_t *update = g_data_write; MotorCAN_Recv_Status(&update->motor_status, 0); MotorCAN_Recv_Velocity(&update->motor_velocity, 0); - //making these motor can should be CARCAN - + // making these motor can should be CARCAN + CarCAN_Recv_BPS_Status(&update->bps_status, 0); CarCAN_Recv_Pedals_Position(&update->accel_brake, 0); CarCAN_Recv_Controls_Status(&update->controls_status, 0); @@ -65,7 +64,6 @@ void Task_UpdateControlStatus(void *args __attribute__((unused))) { } CarCAN_Recv_LWS(&update->lws, 0); - FSMDataIn_t *tmp; taskENTER_CRITICAL(); tmp = g_data_read; @@ -73,11 +71,10 @@ void Task_UpdateControlStatus(void *args __attribute__((unused))) { g_data_write = tmp; taskEXIT_CRITICAL(); - buf[0] = g_data_read->driver_input.Gear_Forward; tx_header.Identifier = 0x321; CarCAN_Send(&tx_header, buf, sizeof(buf)); - + rebuild_inputs(); vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); } diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 6aadb948..bd563e0a 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -9,8 +9,7 @@ // VCU_Status 0x10 3 bytes 100ms void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { - uint8_t buf[3]; - + uint8_t buf[CAN_DLC_VCU_STATUS]; while (1) { // Byte 0: VCU_Fault — map internal faults to DBC enum @@ -77,10 +76,10 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; tx_header.BitRateSwitch = FDCAN_BRS_OFF; tx_header.FDFormat = FDCAN_CLASSIC_CAN; - tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; tx_header.MessageMarker = 0; - MotorCAN_Send(&tx_header, buf, sizeof(buf)); + CarCAN_Send(&tx_header, buf, sizeof(buf)); LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(100)); diff --git a/Firmware/config/Inc/can1_recv_entries.h b/Firmware/config/Inc/can1_recv_entries.h index 6c12fe62..e82b2ee7 100644 --- a/Firmware/config/Inc/can1_recv_entries.h +++ b/Firmware/config/Inc/can1_recv_entries.h @@ -1,11 +1,9 @@ // CAN_RECV_ENTRY(ID, SIZE, CIRCULAR) +// motorcan +#include "MotorCAN_can_msgs.h" -CAN_RECV_ENTRY(0x321, 8, true) // 801 - test -CAN_RECV_ENTRY(0x001, 8, true) // BPS_STATUS -CAN_RECV_ENTRY(0x650, 8, true) // BRAKE_PRESSURE -CAN_RECV_ENTRY(0x600, 8, true) // LV_CARRIER_STATUS -CAN_RECV_ENTRY(0x2B0, 8, true) // LWS_STANDARD -CAN_RECV_ENTRY(0x060, 8, true) // DRIVER_INPUT_STATUS -CAN_RECV_ENTRY(0x050, 8, true) // ACCEL_BRAKE_POSITION -CAN_RECV_ENTRY(0x021, 8, true) // PRECHARGE_VOLTAGES -CAN_RECV_ENTRY(0x015, 8, true) // CONTROLS_STATUS +CAN_RECV_ENTRY(0x123, 8, true) // testing only comment later +CAN_RECV_ENTRY(CAN_ID_MC_INFO, 2, true) +CAN_RECV_ENTRY(CAN_ID_MC_STATUS, 2, true) +CAN_RECV_ENTRY(CAN_ID_MC_BUSMEASUREMENT, 2, true) +CAN_RECV_ENTRY(CAN_ID_MC_VELOCITYMEASUREMENT, 2, true) \ No newline at end of file diff --git a/Firmware/config/Inc/can3_recv_entries.h b/Firmware/config/Inc/can3_recv_entries.h index aa976b5e..69d6f80f 100644 --- a/Firmware/config/Inc/can3_recv_entries.h +++ b/Firmware/config/Inc/can3_recv_entries.h @@ -1,17 +1,17 @@ // CAN_RECV_ENTRY(ID, SIZE, CIRCULAR) +// carcan -// CAN_RECV_ENTRY(0x001, 5, false) -// CAN_RECV_ENTRY(0x002, 8, false) -// CAN_RECV_ENTRY(0x003, 3, false) +#include "CarCAN_can_msgs.h" +#include "SteeringCAN_can_msgs.h" +#include "ControlsCAN_can_msgs.h" +#include "BPSCAN_can_msgs.h" - -CAN_RECV_ENTRY(0x321, 8, true) // 801 - test -CAN_RECV_ENTRY(0x001, 8, true) // BPS_STATUS -CAN_RECV_ENTRY(0x650, 8, true) // BRAKE_PRESSURE -CAN_RECV_ENTRY(0x600, 8, true) // LV_CARRIER_STATUS -CAN_RECV_ENTRY(0x2B0, 8, true) // LWS_STANDARD -CAN_RECV_ENTRY(0x060, 8, true) // DRIVER_INPUT_STATUS -CAN_RECV_ENTRY(0x050, 8, true) // ACCEL_BRAKE_POSITION -CAN_RECV_ENTRY(0x021, 8, true) // PRECHARGE_VOLTAGES -CAN_RECV_ENTRY(0x015, 8, true) // CONTROLS_STATUS +CAN_RECV_ENTRY(0x123, 8, true) // testing only, comment later +CAN_RECV_ENTRY(CAN_ID_BPS_STATUS, 8, true) +CAN_RECV_ENTRY(CAN_ID_PEDAL_STATUS, 8, true) +CAN_RECV_ENTRY(CAN_ID_LV_CARRIER_STATUS, 8, true) +CAN_RECV_ENTRY(CAN_ID_LWS_STANDARD, 8, true) +CAN_RECV_ENTRY(CAN_ID_DRIVER_INPUT_STATUS, 8, true) +CAN_RECV_ENTRY(CAN_ID_BPS_PRECHARGE_VOLTAGES, 8, true) +CAN_RECV_ENTRY(CAN_ID_CONTROLS_STATUS, 8, true) diff --git a/Firmware/tests/carcan_test.c b/Firmware/tests/carcan_test.c new file mode 100644 index 00000000..74981502 --- /dev/null +++ b/Firmware/tests/carcan_test.c @@ -0,0 +1,110 @@ +/** + * canbus test!! + * + * Sends and receives as 2 different tasks. + * For rx: send data from candapter at ID 0x123 to see an led blink + * For tx: use candapter to see if 123456789ABCDEFF is being received at 0x321 + * + */ + +#include "CANbus.h" +#include "StatusLEDs.h" +#include "inits.h" +#include "pinDefs.h" +#include "stm32xx_hal.h" + +#define TESTING_STACK_SIZE (configMINIMAL_STACK_SIZE * 8) + +StaticTask_t rx_task_buffer; +StackType_t rx_task_stack[TESTING_STACK_SIZE]; + +StaticTask_t tx_task_buffer; +StackType_t tx_task_stack[TESTING_STACK_SIZE]; + +#define TEST_CAN_ID_RX 0x123 +#define TEST_CAN_ID_TX 0x321 +#define TEST_CAN_DATA_TX {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF} +#define TEST_CAN_DATA_LENGTH 8 + +void can_error_handler() { + while (1) { + LED_set(MOTOR_FAULT, LED_ON); + } +} + +static void rx_task(void *pvParameters) { + FDCAN_RxHeaderTypeDef rx_header = {0}; + uint8_t rx_data[TEST_CAN_DATA_LENGTH] = {0}; + while (1) { + if (CarCAN_Recv(TEST_CAN_ID_RX, &rx_header, rx_data, portMAX_DELAY) == CAN_ERR) { + can_error_handler(); + } + + LED_toggle(PRECHARGE_COMPLETE); + + // Optional delay if the can recv isnt blocking + // vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +static void tx_task(void *pvParameters) { + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = TEST_CAN_ID_TX; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = FDCAN_DLC_BYTES_8; + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; + tx_header.MessageMarker = 0; + + uint8_t tx_data[TEST_CAN_DATA_LENGTH] = TEST_CAN_DATA_TX; + while (1) { + if (CarCAN_Send(&tx_header, tx_data, portMAX_DELAY) == CAN_ERR) { + can_error_handler(); + } + + LED_toggle(HB); + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +int main() { + HAL_Init(); + + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + LED_init(); + + if (CarCAN_Init() != CAN_OK) { + can_error_handler(); + } + + xTaskCreateStatic( + tx_task, + "tx_task", + TESTING_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + tx_task_stack, + &tx_task_buffer + ); + + xTaskCreateStatic( + rx_task, + "rx_task", + TESTING_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 1, + rx_task_stack, + &rx_task_buffer + ); + + vTaskStartScheduler(); + + while (1) { + } +} \ No newline at end of file diff --git a/Firmware/tests/fsminputs_test b/Firmware/tests/fsminputs_test new file mode 100644 index 00000000..cd1b41bc --- /dev/null +++ b/Firmware/tests/fsminputs_test @@ -0,0 +1,69 @@ +/** + * VCU fsm inputs test. + * + * Enables vcu status task + update fsm inputs task. This basically tests if the + * inputs task is properly updating inputs as well as if the vcu status is + * properly updating too. + * + */ + +#include "VCUStatusTask.h" +#include "UpdateFSMInputsTask.h" +#include "inits.h" +#include "InitTask.h" +#include "FSM.h" + +#define PRINTF_DEBUG + +void can_error_handler() { + while (1) { + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + HAL_Delay(500); + } +} + +int main() { + HAL_Init(); + + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + LED_init(); + + if (CarCAN_Init() != CAN_OK) { + can_error_handler(); + } + + Init_UART_Printf(); + + faults_init(); + contactor_init(); + FSM_TaskInit(); + fsm_init(); + + xTaskCreateStatic( + Task_BroadcastVCUStatus, + "VCU status", + VCU_STATUS_TASK_STACK_SIZE, + NULL, + VCU_STATUS_THREAD_PRIO, + VCUStatus_Task_Stack, + &VCUStatus_Task_Buffer + ); + + xTaskCreateStatic( + Task_UpdateFSMInputs, + "Update FSM Inputs Thread", + UPDATE_FSM_INPUTS_STACK_SIZE, + NULL, + UPDATE_FSM_INPUTS_THREAD_PRIO, + UpdateFSMInputs_Task_Stack, + &UpdateFSMInputs_Task_Buffer + ); + + vTaskStartScheduler(); + + while (1) { + } +} diff --git a/Firmware/tests/canbus_test.c b/Firmware/tests/motorcan_test.c similarity index 71% rename from Firmware/tests/canbus_test.c rename to Firmware/tests/motorcan_test.c index 2151bef6..b5b6fb51 100644 --- a/Firmware/tests/canbus_test.c +++ b/Firmware/tests/motorcan_test.c @@ -13,8 +13,13 @@ #include "pinDefs.h" #include "stm32xx_hal.h" -StaticTask_t task_buffer; -StackType_t task_stack[512]; +#define TESTING_STACK_SIZE (configMINIMAL_STACK_SIZE * 8) + +StaticTask_t rx_task_buffer; +StackType_t rx_task_stack[TESTING_STACK_SIZE]; + +StaticTask_t tx_task_buffer; +StackType_t tx_task_stack[TESTING_STACK_SIZE]; #define TEST_CAN_ID_RX 0x123 #define TEST_CAN_ID_TX 0x321 @@ -36,7 +41,9 @@ static void rx_task(void *pvParameters) { } LED_toggle(PRECHARGE_COMPLETE); - vTaskDelay(pdMS_TO_TICKS(1000)); + + // Optional delay if the can recv isnt blocking + // vTaskDelay(pdMS_TO_TICKS(1000)); } } @@ -49,7 +56,7 @@ static void tx_task(void *pvParameters) { tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; tx_header.BitRateSwitch = FDCAN_BRS_OFF; tx_header.FDFormat = FDCAN_CLASSIC_CAN; - tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; tx_header.MessageMarker = 0; uint8_t tx_data[TEST_CAN_DATA_LENGTH] = TEST_CAN_DATA_TX; @@ -76,8 +83,25 @@ int main() { can_error_handler(); } - xTaskCreateStatic(tx_task, "tx_task", 512, NULL, tskIDLE_PRIORITY + 2, task_stack, &task_buffer); - xTaskCreateStatic(rx_task, "rx_task", 512, NULL, tskIDLE_PRIORITY + 1, task_stack, &task_buffer); + xTaskCreateStatic( + tx_task, + "tx_task", + TESTING_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + tx_task_stack, + &tx_task_buffer + ); + + xTaskCreateStatic( + rx_task, + "rx_task", + TESTING_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 1, + rx_task_stack, + &rx_task_buffer + ); vTaskStartScheduler(); diff --git a/Firmware/tests/vcustatus_test.c b/Firmware/tests/vcustatus_test.c new file mode 100644 index 00000000..a36e8f8a --- /dev/null +++ b/Firmware/tests/vcustatus_test.c @@ -0,0 +1,59 @@ +/** + * VCU status test. + * + * Only enables vcu status task. This basically tests if the msg works (not + * really its interaction with other stuff). + * + * + */ + +#include "VCUStatusTask.h" +#include "inits.h" +#include "InitTask.h" +#include "FSM.h" +// #include "" + +#define PRINTF_DEBUG + +void can_error_handler() { + while (1) { + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + HAL_Delay(500); + } +} + +int main() { + HAL_Init(); + + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + LED_init(); + + if (CarCAN_Init() != CAN_OK) { + can_error_handler(); + } + + Init_UART_Printf(); + + faults_init(); + contactor_init(); + FSM_TaskInit(); + fsm_init(); + + xTaskCreateStatic( + Task_BroadcastVCUStatus, + "VCU status tx", + VCU_STATUS_TASK_STACK_SIZE, + NULL, + VCU_STATUS_THREAD_PRIO, + VCUStatus_Task_Stack, + &VCUStatus_Task_Buffer + ); + + vTaskStartScheduler(); + + while (1) { + } +} From 43aed170ce8c8f6f0626c76837ec6134401ec85d Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 11 Apr 2026 01:25:59 -0500 Subject: [PATCH 09/27] computer gonna die --- Firmware/Drivers/Src/CANbus.c | 79 ++++++++--------------- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSM.h | 4 +- Firmware/Tasks/Inc/UpdateFSMInputsTask.h | 2 + Firmware/Tasks/Src/FSMTask.c | 10 +-- Firmware/Tasks/Src/UpdateFSMInputsTask.c | 78 ++++++++++++++++------- Firmware/Tasks/Src/VCUStatusTask.c | 3 +- Firmware/tests/fsm_test.c | 1 - Firmware/tests/fsm_transition_test.c | 80 ++++++++++++++++++++++++ Firmware/tests/fsminputs_test.c | 70 +++++++++++++++++++++ 10 files changed, 243 insertions(+), 86 deletions(-) delete mode 100644 Firmware/tests/fsm_test.c create mode 100644 Firmware/tests/fsm_transition_test.c create mode 100644 Firmware/tests/fsminputs_test.c diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 2956b901..4ef0d3ab 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -128,7 +128,7 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d .Identifier = CAN_ID_MC_DRIVECOMMAND, .IdType = FDCAN_STANDARD_ID, .TxFrameType = FDCAN_DATA_FRAME, - .DataLength = CAN_DLC_MC_DRIVECOMMAND, + .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), .ErrorStateIndicator = FDCAN_ESI_ACTIVE, .BitRateSwitch = FDCAN_BRS_OFF, .FDFormat = FDCAN_CLASSIC_CAN, @@ -142,7 +142,7 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); can_status_t result = - can_fd_send(motorfdcan, &header, moco_drive_tx_data, delay); + can_fd_send(carfdcan, &header, moco_drive_tx_data, delay); return result; } @@ -283,22 +283,22 @@ can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t del can_fd_recv(carfdcan, CAN_ID_DRIVER_INPUT_STATUS, &header, driver_input_rx_data, delay); if (result == CAN_OK) { - out->Ignition_Array = driver_input_rx_data[0] & (0x01); - out->Ignition_Motor = driver_input_rx_data[0] & (0x01 << 1); - out->Ignition_Off = driver_input_rx_data[0] & (0x01 << 2); - out->Cruise_Enable = driver_input_rx_data[0] & (0x01 << 3); - out->Cruise_Set = driver_input_rx_data[0] & (0x01 << 4); - out->Gear_Forward = driver_input_rx_data[0] & (0x01 << 5); - out->Gear_Neutral = driver_input_rx_data[0] & (0x01 << 6); - out->Gear_Reverse = driver_input_rx_data[0] & (0x01 << 7); - - out->Hazard_Pressed = driver_input_rx_data[1] & (0x01); - out->Horn_Pressed = driver_input_rx_data[1] & (0x01 << 1); - out->Blinker_Left = driver_input_rx_data[1] & (0x01 << 2); - out->Blinker_Right = driver_input_rx_data[1] & (0x01 << 3); - out->PushToTalk_Pressed = driver_input_rx_data[1] & (0x01 << 4); - out->Regen_Activate = driver_input_rx_data[1] & (0x01 << 5); - out->Regen_Enable = driver_input_rx_data[1] & (0x01 << 6); + out->Ignition_Array = !!(driver_input_rx_data[0] & (1U << 0)); + out->Ignition_Motor = !!(driver_input_rx_data[0] & (1U << 1)); + out->Ignition_Off = !!(driver_input_rx_data[0] & (1U << 2)); + out->Cruise_Enable = !!(driver_input_rx_data[0] & (1U << 3)); + out->Cruise_Set = !!(driver_input_rx_data[0] & (1U << 4)); + out->Gear_Forward = !!(driver_input_rx_data[0] & (1U << 5)); + out->Gear_Neutral = !!(driver_input_rx_data[0] & (1U << 6)); + out->Gear_Reverse = !!(driver_input_rx_data[0] & (1U << 7)); + + out->Hazard_Pressed = !!(driver_input_rx_data[1] & (1U << 0)); + out->Horn_Pressed = !!(driver_input_rx_data[1] & (1U << 1)); + out->Blinker_Left = !!(driver_input_rx_data[1] & (1U << 2)); + out->Blinker_Right = !!(driver_input_rx_data[1] & (1U << 3)); + out->PushToTalk_Pressed = !!(driver_input_rx_data[1] & (1U << 4)); + out->Regen_Activate = !!(driver_input_rx_data[1] & (1U << 5)); + out->Regen_Enable = !!(driver_input_rx_data[1] & (1U << 6)); } return result; @@ -314,46 +314,21 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) can_fd_recv(carfdcan, CAN_ID_PEDAL_STATUS, &header, pedals_pos_rx_data, delay); if (result == CAN_OK) { - out->AccelPedal_Main_Pos = pedals_pos_rx_data[0]; - out->AccelPedal_Redundant_Pos = pedals_pos_rx_data[1]; - out->BrakePedal_Main_Pos = pedals_pos_rx_data[2]; - out->BrakePedal_Redundant_Pos = pedals_pos_rx_data[3]; - out->AccelPedal_Main_Fault = pedals_pos_rx_data[4] & (0x01); - out->AccelPedal_Redundant_Fault = pedals_pos_rx_data[4] & (0x01 << 1); - out->BrakePedal_Main_Fault = pedals_pos_rx_data[4] & (0x01 << 2); - out->BrakePedal_Redundant_Fault = pedals_pos_rx_data[4] & (0x01 << 3); + out->AccelPedal_Main_Pos = pedals_pos_rx_data[0]; + out->AccelPedal_Redundant_Pos = pedals_pos_rx_data[1]; + out->BrakePedal_Main_Pos = pedals_pos_rx_data[2]; + out->BrakePedal_Redundant_Pos = pedals_pos_rx_data[3]; + + out->AccelPedal_Main_Fault = !!(pedals_pos_rx_data[4] & (1U << 0)); + out->AccelPedal_Redundant_Fault = !!(pedals_pos_rx_data[4] & (1U << 1)); + out->BrakePedal_Main_Fault = !!(pedals_pos_rx_data[4] & (1U << 2)); + out->BrakePedal_Redundant_Fault = !!(pedals_pos_rx_data[4] & (1U << 3)); } return result; } -can_status_t CarCAN_Send_VCU_Status(vcu_status_t *out, TickType_t delay) { - if (out == NULL) return CAN_EMPTY; - - FDCAN_TxHeaderTypeDef header = { - .Identifier = CAN_ID_VCU_STATUS, - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .DataLength = CAN_DLC_VCU_STATUS, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, - .BitRateSwitch = FDCAN_BRS_OFF, - .FDFormat = FDCAN_CLASSIC_CAN, - .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, - .MessageMarker = 0, - }; - - uint8_t vcu_status_tx_data[CAN_DLC_VCU_STATUS] = {0}; - - // TODO: actually pack ts - - can_status_t result = - can_fd_send(carfdcan, &header, vcu_status_tx_data, delay); - - return result; -} - - //////// HAL bs static uint32_t HAL_RCC_FDCAN_CLK_ENABLED = 0; diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 6a0b60dc..761bf106 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 6a0b60dc497015a0b2b069ec8af1a29375bc290a +Subproject commit 761bf106dc7be5b5ff1b1cb65972ce54cbd75747 diff --git a/Firmware/Tasks/Inc/FSM.h b/Firmware/Tasks/Inc/FSM.h index 0d375c48..be4ef97f 100644 --- a/Firmware/Tasks/Inc/FSM.h +++ b/Firmware/Tasks/Inc/FSM.h @@ -80,8 +80,8 @@ typedef struct { mc_velocitymeasurement_t motor_velocity; } FSMDataIn_t; -extern FSMDataIn_t *g_data_read; -extern FSMDataIn_t *g_data_write; +extern FSMDataIn_t * volatile g_data_read; +extern FSMDataIn_t * volatile g_data_write; diff --git a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h index cd396435..352d7ffd 100644 --- a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h +++ b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h @@ -7,4 +7,6 @@ #define BRAKE_THRESH 42.0f // percent #define BRAKE_THRESH_HYST 30.0f // percent +#define ACCEPTABLE_PEDAL_DEVIATION 3 // percent + void Task_UpdateFSMInputs(void *args __attribute__((unused))); diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 9ce590b2..546d4c75 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -24,11 +24,11 @@ EventGroupHandle_t fsmInputGroup = {0}; MocoState_t current_state = {0}; -static FSMDataIn_t fsm_input_read = {0}; -static FSMDataIn_t fsm_input_write = {0}; +static FSMDataIn_t fsm_input_a = {0}; +static FSMDataIn_t fsm_input_b = {0}; -FSMDataIn_t *g_data_read = &fsm_input_read; -FSMDataIn_t *g_data_write = &fsm_input_write; +FSMDataIn_t * volatile g_data_read = &fsm_input_a; +FSMDataIn_t * volatile g_data_write = &fsm_input_b; static bool rollover_limit_active = false; static volatile uint16_t fsm_inputs = 0; @@ -78,8 +78,10 @@ uint16_t fsm_get_fsm_inputs(void) { return (uint16_t)fsm_inputs; } bool fsm_is_over_rollover_speed(void) { return rollover_limit_active; } void fsm_set_all_inputs(EventBits_t mask) { + taskENTER_CRITICAL(); xEventGroupClearBits(fsmInputGroup, FSM_INPUTS_MASK_ALL); xEventGroupSetBits(fsmInputGroup, mask & FSM_INPUTS_MASK_ALL); + taskEXIT_CRITICAL(); } void fsm_set_input(EventBits_t mask) { diff --git a/Firmware/Tasks/Src/UpdateFSMInputsTask.c b/Firmware/Tasks/Src/UpdateFSMInputsTask.c index 241572fb..b210010c 100644 --- a/Firmware/Tasks/Src/UpdateFSMInputsTask.c +++ b/Firmware/Tasks/Src/UpdateFSMInputsTask.c @@ -1,6 +1,9 @@ #include "UpdateFSMInputsTask.h" #include "Contactors.h" +#include "FaultBits.h" #include "event_groups.h" +#include +#include static float brake_threshold = BRAKE_THRESH; @@ -18,8 +21,8 @@ static void rebuild_inputs(void) { if (g_data_read->driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; if (g_data_read->driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; if (g_data_read->bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; - if (contactor_get_sense(MOTOR_CONTACTOR) && contactor_get_sense(MOTOR_PRE_CONTACTOR)) - s |= PRECHARGE_COMPLETE_BIT; + // if (contactor_get_sense(MOTOR_CONTACTOR) && contactor_get_sense(MOTOR_PRE_CONTACTOR)) + s |= PRECHARGE_COMPLETE_BIT; if (g_data_read->accel_brake.BrakePedal_Main_Pos >= brake_threshold) { s |= BRAKE_BIT; @@ -31,23 +34,55 @@ static void rebuild_inputs(void) { fsm_set_all_inputs(s); } +void UFI_throw_faults() { + EventBits_t mask = 0; + if (g_data_read->bps_status.BPS_Fault) + mask |= FAULT_BIT(FAULT_ID_BPS_FAULT); + if (g_data_read->controls_status.Controls_Leader_Fault) + mask |= FAULT_BIT(FAULT_ID_CONTROLS_FAULT); + + // Moco faults + if (g_data_read->motor_status.MC_FAULT_HardwareOverCurrent) + mask |= FAULT_BIT(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT); + if (g_data_read->motor_status.MC_FAULT_SoftwareOverCurrent) + mask |= FAULT_BIT(FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT); + if (g_data_read->motor_status.MC_FAULT_DcBusOverVoltage) + mask |= FAULT_BIT(FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE); + if (g_data_read->motor_status.MC_FAULT_BadMotorPositionHallSeq) + mask |= FAULT_BIT(FAULT_ID_MOTOR_BAD_HALL_SEQUENCE); + if (g_data_read->motor_status.MC_FAULT_WatchdogCausedLastReset) + mask |= FAULT_BIT(FAULT_ID_MOTOR_WD_RESET); + if (g_data_read->motor_status.MC_FAULT_ConfigRead) + mask |= FAULT_BIT(FAULT_ID_MOTOR_CONFIG_READ); + if (g_data_read->motor_status.MC_FAULT_15vRailUnderVoltage) + mask |= FAULT_BIT(FAULT_ID_MOTOR_15V_UNDERVOLTAGE); + if (g_data_read->motor_status.MC_FAULT_DesaturationFault) + mask |= FAULT_BIT(FAULT_ID_MOTOR_DESATURATION); + if (g_data_read->motor_status.MC_FAULT_MotorOverSpeed) + mask |= FAULT_BIT(FAULT_ID_MOTOR_OVERSPEED); + + // Pedals faults + if (g_data_read->accel_brake.AccelPedal_Main_Fault || + g_data_read->accel_brake.AccelPedal_Redundant_Fault || + g_data_read->accel_brake.BrakePedal_Main_Fault || + g_data_read->accel_brake.BrakePedal_Redundant_Fault || + fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - + g_data_read->accel_brake.AccelPedal_Redundant_Pos) < ACCEPTABLE_PEDAL_DEVIATION) { + mask |= FAULT_BIT(FAULT_ID_PEDAL_BOARD_FAULT); + } + + if (g_data_read->lws.LWS_Fault) + mask |= FAULT_BIT(FAULT_ID_STEERING_SENSOR_FAULT); + + faults_set_mask(mask); +} + void Task_UpdateFSMInputs(void *args __attribute__((unused))) { TickType_t last = xTaskGetTickCount(); - FDCAN_TxHeaderTypeDef tx_header = {0}; - tx_header.Identifier = 0x123; - tx_header.IdType = FDCAN_STANDARD_ID; - tx_header.TxFrameType = FDCAN_DATA_FRAME; - tx_header.DataLength = FDCAN_DLC_BYTES_8; - tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header.BitRateSwitch = FDCAN_BRS_OFF; - tx_header.FDFormat = FDCAN_CLASSIC_CAN; - tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header.MessageMarker = 0; - uint8_t buf[8] = {0}; while (1) { // update from can - FSMDataIn_t *update = g_data_write; + FSMDataIn_t *volatile update = g_data_write; MotorCAN_Recv_Status(&update->motor_status, 0); MotorCAN_Recv_Velocity(&update->motor_velocity, 0); @@ -56,24 +91,19 @@ void Task_UpdateFSMInputs(void *args __attribute__((unused))) { CarCAN_Recv_BPS_Status(&update->bps_status, 0); CarCAN_Recv_Pedals_Position(&update->accel_brake, 0); CarCAN_Recv_Controls_Status(&update->controls_status, 0); - if (CarCAN_Recv_Driver_Input(&update->driver_input, 0) == CAN_OK) { - // Handle driver input - buf[0] = update->driver_input.Gear_Forward; - tx_header.Identifier = 0x123; - CarCAN_Send(&tx_header, buf, sizeof(buf)); - } + CarCAN_Recv_Driver_Input(&update->driver_input, 0); CarCAN_Recv_LWS(&update->lws, 0); - FSMDataIn_t *tmp; + FSMDataIn_t *volatile tmp; taskENTER_CRITICAL(); tmp = g_data_read; g_data_read = g_data_write; g_data_write = tmp; taskEXIT_CRITICAL(); + memcpy(g_data_write, g_data_read, sizeof(FSMDataIn_t)); - buf[0] = g_data_read->driver_input.Gear_Forward; - tx_header.Identifier = 0x321; - CarCAN_Send(&tx_header, buf, sizeof(buf)); + // Throw relevant faults + UFI_throw_faults(); rebuild_inputs(); vTaskDelayUntil(&last, pdMS_TO_TICKS(50)); diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index bd563e0a..5259ef11 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -7,7 +7,6 @@ #include "Watchdogs.h" #include "StatusLEDs.h" -// VCU_Status 0x10 3 bytes 100ms void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { uint8_t buf[CAN_DLC_VCU_STATUS]; @@ -72,7 +71,7 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { tx_header.Identifier = CAN_ID_VCU_STATUS; tx_header.IdType = FDCAN_STANDARD_ID; tx_header.TxFrameType = FDCAN_DATA_FRAME; - tx_header.DataLength = FDCAN_DLC_BYTES_8; + tx_header.DataLength = FDCAN_DLC_BYTES(CAN_DLC_VCU_STATUS); tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; tx_header.BitRateSwitch = FDCAN_BRS_OFF; tx_header.FDFormat = FDCAN_CLASSIC_CAN; diff --git a/Firmware/tests/fsm_test.c b/Firmware/tests/fsm_test.c deleted file mode 100644 index 1eb3893b..00000000 --- a/Firmware/tests/fsm_test.c +++ /dev/null @@ -1 +0,0 @@ -//this'll test the actual FSM implementation and also flash the appropriate LEDs for the VCU status diff --git a/Firmware/tests/fsm_transition_test.c b/Firmware/tests/fsm_transition_test.c new file mode 100644 index 00000000..199881c0 --- /dev/null +++ b/Firmware/tests/fsm_transition_test.c @@ -0,0 +1,80 @@ +/** + * VCU status test. + * + * Only enables vcu status task. This basically tests if the msg works (not + * really its interaction with other stuff). + * + * + */ + +#include "VCUStatusTask.h" +#include "UpdateFSMInputsTask.h" +#include "inits.h" +#include "InitTask.h" +#include "FSM.h" +// #include "" + +#define PRINTF_DEBUG + +void can_error_handler() { + while (1) { + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + HAL_Delay(500); + } +} + +int main() { + HAL_Init(); + + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + LED_init(); + + if (CarCAN_Init() != CAN_OK) { + can_error_handler(); + } + + Init_UART_Printf(); + + faults_init(); + contactor_init(); + FSM_TaskInit(); + fsm_init(); + + xTaskCreateStatic( + Task_BroadcastVCUStatus, + "VCU status tx", + VCU_STATUS_TASK_STACK_SIZE, + NULL, + VCU_STATUS_THREAD_PRIO, + VCUStatus_Task_Stack, + &VCUStatus_Task_Buffer + ); + + xTaskCreateStatic( + Task_UpdateFSMInputs, + "Update FSM Inputs Thread", + UPDATE_FSM_INPUTS_STACK_SIZE, + NULL, + UPDATE_FSM_INPUTS_THREAD_PRIO, + UpdateFSMInputs_Task_Stack, + &UpdateFSMInputs_Task_Buffer + ); + + xTaskCreateStatic( + Task_FSM, + "FSM Thread", + FSM_TASK_STACK_SIZE, + NULL, + FSM_THREAD_PRIO, + FSM_Task_Stack, + &FSM_Task_Buffer + ); + + vTaskStartScheduler(); + + while (1) { + } +} diff --git a/Firmware/tests/fsminputs_test.c b/Firmware/tests/fsminputs_test.c new file mode 100644 index 00000000..09c439c4 --- /dev/null +++ b/Firmware/tests/fsminputs_test.c @@ -0,0 +1,70 @@ +/** + * VCU status test. + * + * Only enables vcu status task. This basically tests if the msg works (not + * really its interaction with other stuff). + * + * + */ + +#include "VCUStatusTask.h" +#include "UpdateFSMInputsTask.h" +#include "inits.h" +#include "InitTask.h" +#include "FSM.h" +// #include "" + +#define PRINTF_DEBUG + +void can_error_handler() { + while (1) { + HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); + HAL_Delay(500); + } +} + +int main() { + HAL_Init(); + + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + LED_init(); + + if (CarCAN_Init() != CAN_OK) { + can_error_handler(); + } + + Init_UART_Printf(); + + faults_init(); + contactor_init(); + FSM_TaskInit(); + fsm_init(); + + xTaskCreateStatic( + Task_BroadcastVCUStatus, + "VCU status tx", + VCU_STATUS_TASK_STACK_SIZE, + NULL, + VCU_STATUS_THREAD_PRIO, + VCUStatus_Task_Stack, + &VCUStatus_Task_Buffer + ); + + xTaskCreateStatic( + Task_UpdateFSMInputs, + "Update FSM Inputs Thread", + UPDATE_FSM_INPUTS_STACK_SIZE, + NULL, + UPDATE_FSM_INPUTS_THREAD_PRIO, + UpdateFSMInputs_Task_Stack, + &UpdateFSMInputs_Task_Buffer + ); + + vTaskStartScheduler(); + + while (1) { + } +} From ac9986a9aa02ebbce1f7dd086487af14a91c316e Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 11 Apr 2026 01:26:36 -0500 Subject: [PATCH 10/27] switched back car to motor --- Firmware/Drivers/Src/CANbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 4ef0d3ab..e28cad13 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -142,7 +142,7 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); can_status_t result = - can_fd_send(carfdcan, &header, moco_drive_tx_data, delay); + can_fd_send(motorfdcan, &header, moco_drive_tx_data, delay); return result; } From 00648f7aaa88b5f28dadf9125c1b58d28d4af500 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 11 Apr 2026 22:50:31 -0500 Subject: [PATCH 11/27] ts shit builds --- Firmware/Drivers/Inc/CANbus.h | 2 + Firmware/Drivers/Inc/FaultBits.h | 42 +-- Firmware/Drivers/Src/CANbus.c | 37 ++- Firmware/Drivers/Src/FaultBits.c | 53 +-- Firmware/Tasks/Inc/CanTxTelemetryTask.h | 16 - Firmware/Tasks/Inc/DriverInputTask.h | 14 - Firmware/Tasks/Inc/{FSM.h => FSMTask.h} | 14 - Firmware/Tasks/Inc/InitTask.h | 38 +-- Firmware/Tasks/Inc/MotorControlTask.h | 26 -- Firmware/Tasks/Inc/PrechargeTask.h | 66 ++-- Firmware/Tasks/Inc/ReadMotorCAN.h | 10 - Firmware/Tasks/Inc/UpdateFSMInputsTask.h | 12 - Firmware/Tasks/Inc/UpdateVCUInputsTask.h | 26 ++ Firmware/Tasks/Inc/VCUReceiveCANTask.h | 21 -- Firmware/Tasks/Inc/fsm_table_dnr.h | 2 +- Firmware/Tasks/Src/DriverInputTask.c | 40 --- Firmware/Tasks/Src/FSMTask.c | 12 +- Firmware/Tasks/Src/FaultHandlerTask.c | 26 +- Firmware/Tasks/Src/InitTask.c | 61 +--- Firmware/Tasks/Src/PrechargeTask.c | 307 +++++++----------- ...eFSMInputsTask.c => UpdateVCUInputsTask.c} | 19 +- Firmware/Tasks/Src/VCUReceiveCANTask.c | 98 ------ Firmware/Tasks/Src/VCUStatusTask.c | 6 +- Firmware/config/Inc/can1_recv_entries.h | 2 - Firmware/scripts/fsm_generator.py | 2 +- 25 files changed, 272 insertions(+), 680 deletions(-) delete mode 100644 Firmware/Tasks/Inc/CanTxTelemetryTask.h delete mode 100644 Firmware/Tasks/Inc/DriverInputTask.h rename Firmware/Tasks/Inc/{FSM.h => FSMTask.h} (88%) delete mode 100644 Firmware/Tasks/Inc/MotorControlTask.h delete mode 100644 Firmware/Tasks/Inc/ReadMotorCAN.h delete mode 100644 Firmware/Tasks/Inc/UpdateFSMInputsTask.h create mode 100644 Firmware/Tasks/Inc/UpdateVCUInputsTask.h delete mode 100644 Firmware/Tasks/Inc/VCUReceiveCANTask.h delete mode 100644 Firmware/Tasks/Src/DriverInputTask.c rename Firmware/Tasks/Src/{UpdateFSMInputsTask.c => UpdateVCUInputsTask.c} (89%) delete mode 100644 Firmware/Tasks/Src/VCUReceiveCANTask.c diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index eb4ddcf1..7c0fea46 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -30,6 +30,8 @@ can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay); can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t delay); +can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, + TickType_t delay); /* HAL MSP hooks implemented in CANbus.c */ void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *fdcanHandle); diff --git a/Firmware/Drivers/Inc/FaultBits.h b/Firmware/Drivers/Inc/FaultBits.h index 0544281a..0c45148a 100644 --- a/Firmware/Drivers/Inc/FaultBits.h +++ b/Firmware/Drivers/Inc/FaultBits.h @@ -27,6 +27,7 @@ X(BATTERY_UNDERVOLTAGE) /* Battery voltage is less than UNDERVOLTAGE_THRESHOLD_MV */ \ X(MOTOR_GT_BATTERY) /* Motor voltage is greater than battery voltage */ \ X(CONTACTOR_CALLBACK) /* Contactor state didnt match expected state after being set */ \ + X(MOTOR_LT_BATTERY) /* Motor voltage dropped below 80% of battery voltage */ \ \ /* ============== OTHER BOARDS =============== */ \ X(STEERING_SENSOR_FAULT) /* Sensor not OK or data invalid */ \ @@ -54,20 +55,8 @@ _Static_assert(FAULT_ID_COUNT <= MAX_FAULT_BITS, // Names for faults for printing/debugging purposes. Indexed by FaultID_e values extern const char *fault_names[]; - #define FAULT_BIT(id) (1UL << (id)) #define FAULT_MASK_ALL ((1UL << FAULT_ID_COUNT) - 1) -typedef enum -{ - PRECHARGE_WAITING_STATE, - PRECHARGE_INITIAL_STATE, // Indiciates we are in the inital state when set - PRECHARGE_PRECHARGING_STATE, // Indicates we are in the precharging state when set - PRECHARGE_RUN_STATE, // Indicates we are in the run state when set - NUM_STATES -} state_bit_t; - -#define STATE_BIT(state) (1UL << (state)) -#define STATE_BITMASK ((EventBits_t)((1UL << NUM_STATES) - 1UL)) #define FAULT_MASK_MOTOR_ALL ( \ FAULT_BIT(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT) | \ @@ -90,7 +79,8 @@ typedef enum FAULT_BIT(FAULT_ID_BATTERY_OVERVOLTAGE) | \ FAULT_BIT(FAULT_ID_BATTERY_UNDERVOLTAGE) | \ FAULT_BIT(FAULT_ID_MOTOR_GT_BATTERY) | \ - FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK) \ + FAULT_BIT(FAULT_ID_CONTACTOR_CALLBACK) | \ + FAULT_BIT(FAULT_ID_MOTOR_LT_BATTERY) \ ) /** @@ -168,28 +158,4 @@ EventBits_t faults_get(void); * active. If waiting for any fault, the returned bitmask will have all active * fault bits set. */ -EventBits_t faults_wait(FaultID_e id, TickType_t ticks); - -/** - * @brief Initializes state bitmap - * - * @param none - * @return 0 on failure, 1 on success - */ -uint8_t stateBits_init(void); - -/** - * @brief Set a state in the state bitmap - * - * @param bit which state is being set - * @return none - */ -void set_stateBit(state_bit_t bit); - -/** - * @brief Set a fault in the fault bitmap from an ISR - * - * @param bit which fault is being set - * @return none - */ -void set_faultBitFromISR(fault_bit_t bit); +EventBits_t faults_wait(FaultID_e id, TickType_t ticks); \ No newline at end of file diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 1435a1d3..da23a6bc 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -324,16 +324,30 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) return result; } -can_status_t CAN_Init() -{ - if (Motor_CANBus_Init() != CAN_OK) - { - return CAN_ERR; - } - if (Car_CANBus_Init() != CAN_OK) - { - return CAN_ERR; - } +can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, + TickType_t delay) { + FDCAN_TxHeaderTypeDef header = { + .Identifier = CAN_ID_VCU_PRECHARGE_VOLTAGES, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .DataLength = FDCAN_DLC_BYTES(CAN_DLC_VCU_PRECHARGE_VOLTAGES), + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .BitRateSwitch = FDCAN_BRS_OFF, + .FDFormat = FDCAN_CLASSIC_CAN, + .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, + .MessageMarker = 0, + }; + + uint8_t vcu_prech_tx_data[CAN_DLC_VCU_PRECHARGE_VOLTAGES] = {0}; + + memcpy(&vcu_prech_tx_data[0], &motor_mv, sizeof(uint32_t)); + memcpy(&vcu_prech_tx_data[4], &battery_mv, sizeof(uint32_t)); + + can_status_t result = + can_fd_send(carfdcan, &header, vcu_prech_tx_data, delay); + + return result; +} //////// HAL bs @@ -453,5 +467,4 @@ void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *fdcanHandle) { /* FDCAN3 interrupt Deinit */ HAL_NVIC_DisableIRQ(FDCAN3_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN3_IT1_IRQn); - } -} +} \ No newline at end of file diff --git a/Firmware/Drivers/Src/FaultBits.c b/Firmware/Drivers/Src/FaultBits.c index e27a9e4a..635bef93 100644 --- a/Firmware/Drivers/Src/FaultBits.c +++ b/Firmware/Drivers/Src/FaultBits.c @@ -4,10 +4,6 @@ static StaticEventGroup_t faultBuffer; static EventGroupHandle_t faultGroup; -EventGroupHandle_t stateBits; -StaticEventGroup_t stateBitsBuffer; - - const char *fault_names[FAULT_ID_COUNT] = { #define X(name) [FAULT_ID_##name] = #name, FAULT_ID_LIST(X) @@ -31,7 +27,6 @@ void faults_set(FaultID_e id) { void faults_set_from_isr(FaultID_e id) { BaseType_t hpw = pdFALSE; configASSERT(id < FAULT_ID_COUNT); - xEventGroupSetBitsFromISR(faultGroup, FAULT_BIT(id), &hpw); portYIELD_FROM_ISR(hpw); } @@ -64,52 +59,8 @@ EventBits_t faults_wait(FaultID_e id, TickType_t ticks) { return xEventGroupWaitBits( faultGroup, mask, - pdFALSE, // don't clear - pdFALSE, // wait for any + pdFALSE, // don't clear + pdFALSE, // wait for any ticks ); - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -uint8_t stateBits_init(void){ - stateBits = xEventGroupCreateStatic( &stateBitsBuffer ); - if(stateBits == NULL){ - return 0; - } - return 1; -} - -void set_stateBit(state_bit_t bit){ - // not a valid state - if(bit >= NUM_STATES){ - return; - } - - // Clear all state bits first - xEventGroupClearBits(stateBits, STATE_BITMASK); - - // Set only the requested bit - xEventGroupSetBits(stateBits, STATE_BIT(bit)); - - taskYIELD(); -} - -EventBits_t faultBit_wait(fault_bit_t bit, TickType_t xTicksToWait){ - - // NUM_FAULTS indiciates you want to wait for all bits - if(bit > NUM_FAULTS){ - return 0; - } - - EventBits_t uxBitsToWaitFor = bit == NUM_FAULTS ? FAULT_BITMASK : (FAULT_BIT(bit)); - - EventBits_t pending = xEventGroupWaitBits( - faultStateBits, - uxBitsToWaitFor, // wait for any defined fault - pdFALSE, // fault bits are not reset - pdFALSE, // wait for ANY bit to be set - xTicksToWait - ); - return pending; } \ No newline at end of file diff --git a/Firmware/Tasks/Inc/CanTxTelemetryTask.h b/Firmware/Tasks/Inc/CanTxTelemetryTask.h deleted file mode 100644 index f189c465..00000000 --- a/Firmware/Tasks/Inc/CanTxTelemetryTask.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "MotorCAN_can_msgs.h" -#include "stm32xx_hal.h" -#include -#include "CANbus.h" -#include "inits.h" -#include "StatusLEDs.h" -#include "pinDefs.h" -#include "InitTask.h" -#include "slcanFormat.h" - - -void CanTxTelemetryTask_Init(void); - -void Task_CanTxTelemetry(); diff --git a/Firmware/Tasks/Inc/DriverInputTask.h b/Firmware/Tasks/Inc/DriverInputTask.h deleted file mode 100644 index dcd37ac0..00000000 --- a/Firmware/Tasks/Inc/DriverInputTask.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "FaultBits.h" -#include "Contactors.h" -#include "StatusLEDs.h" -#include "ADC_Sense.h" -#include "InitTask.h" -#include "MotorSafeBits.h" -#include "CANbus.h" -#include "CarCAN_can_msgs.h" -#include - -void Init_DriverInputTestTask(); -void Task_DriverInputTest(); diff --git a/Firmware/Tasks/Inc/FSM.h b/Firmware/Tasks/Inc/FSMTask.h similarity index 88% rename from Firmware/Tasks/Inc/FSM.h rename to Firmware/Tasks/Inc/FSMTask.h index be4ef97f..674e284a 100644 --- a/Firmware/Tasks/Inc/FSM.h +++ b/Firmware/Tasks/Inc/FSMTask.h @@ -70,20 +70,6 @@ typedef struct { extern MocoState_t FSM[NUM_STATES]; extern MocoState_t current_state; -typedef struct { - driver_input_status_t driver_input; - pedal_status_t accel_brake; - lws_standard_t lws; - controls_status_t controls_status; - mc_status_t motor_status; - bps_status_t bps_status; - mc_velocitymeasurement_t motor_velocity; -} FSMDataIn_t; - -extern FSMDataIn_t * volatile g_data_read; -extern FSMDataIn_t * volatile g_data_write; - - void fsm_init(void); void fsm_step(void); diff --git a/Firmware/Tasks/Inc/InitTask.h b/Firmware/Tasks/Inc/InitTask.h index 1171d0d2..633cb1c5 100644 --- a/Firmware/Tasks/Inc/InitTask.h +++ b/Firmware/Tasks/Inc/InitTask.h @@ -2,12 +2,9 @@ #include "FaultHandlerTask.h" #include "PrechargeTask.h" -#include "VCUReceiveCANTask.h" -#include "DriverInputTask.h" -#include "MotorSafeBits.h" -#include "MotorControlTask.h" -#include "MotorTelemetryTask.h" -#include "CanTxTelemetryTask.h" +#include "FSMTask.h" +#include "UpdateVCUInputsTask.h" +#include "VCUStatusTask.h" #include "CANbus.h" #define INIT_TASK_STACK_SIZE configMINIMAL_STACK_SIZE @@ -15,15 +12,11 @@ #define PRECHARGE_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 #define FSM_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 #define VCU_STATUS_TASK_STACK_SIZE configMINIMAL_STACK_SIZE * 2 -#define UPDATE_FSM_INPUTS_STACK_SIZE configMINIMAL_STACK_SIZE * 2 +#define UPDATE_VCU_INPUTS_STACK_SIZE configMINIMAL_STACK_SIZE * 2 -// #define MOTOR_CONTROL_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -// #define MOTOR_TELEMETRY_TASK_STACK_SIZE configMINIMAL_STACK_SIZE -// #define CAN_TX_TELEMETRY_STACK_SIZE configMINIMAL_STACK_SIZE - -extern StaticTask_t FaultHandlerTask_Buffer; -extern StackType_t FaultHandlerTask_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; +extern StaticTask_t FaultHandler_Task_Buffer; +extern StackType_t FaultHandler_Task_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; extern StaticTask_t Precharge_Task_Buffer; extern StackType_t Precharge_Task_Stack[PRECHARGE_TASK_STACK_SIZE]; @@ -37,26 +30,18 @@ extern StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; extern StaticTask_t VCUStatus_Task_Buffer; extern StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; -extern StaticTask_t UpdateFSMInputs_Task_Buffer; -extern StackType_t UpdateFSMInputs_Task_Stack[FSM_TASK_STACK_SIZE]; - -// extern StaticTask_t Motor_Control_Task_Buffer; -// extern StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; +extern StaticTask_t UpdateVCUInputs_Task_Buffer; +extern StackType_t UpdateVCUInputs_Task_Stack[FSM_TASK_STACK_SIZE]; -// extern StaticTask_t Motor_Telemetry_Task_Buffer; -// extern StackType_t Motor_Telemetry_Task_Stack[MOTOR_TELEMETRY_TASK_STACK_SIZE]; - -// extern StaticTask_t Can_Tx_Telemetry_Task_Buffer; -// extern StackType_t Can_Tx_Telemetry_Task_Stack[CAN_TX_TELEMETRY_STACK_SIZE]; #define FAULT_HANDLER_THREAD_PRIO (tskIDLE_PRIORITY + 4) #define PRECHARGE_THREAD_PRIO (tskIDLE_PRIORITY + 3) -#define UPDATE_FSM_INPUTS_THREAD_PRIO (tskIDLE_PRIORITY + 2) +#define UPDATE_VCU_INPUTS_THREAD_PRIO (tskIDLE_PRIORITY + 2) #define FSM_THREAD_PRIO (tskIDLE_PRIORITY + 2) #define UPDATE_CONTROL_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 2) #define VCU_STATUS_THREAD_PRIO (tskIDLE_PRIORITY + 1) -#define SDCARD_WORKER_THREAD_PRIO (tskIDLE_PRIORITY + 1) +#define SDCARD_WORKER_THREAD_PRIO (tskIDLE_PRIORITY + 1) // Period the fault thread runs at (once a fault is active) @@ -69,7 +54,6 @@ extern StackType_t UpdateFSMInputs_Task_Stack[FSM_TASK_STACK_SIZE]; #define PRECHARGE_TASK_DELAY_MS 100 -extern StaticTask_t VCUReceiveCAN_Task_Buffer; -extern StackType_t VCUReceiveCAN_Task_Stack[configMINIMAL_STACK_SIZE]; + void Task_Init(); \ No newline at end of file diff --git a/Firmware/Tasks/Inc/MotorControlTask.h b/Firmware/Tasks/Inc/MotorControlTask.h deleted file mode 100644 index e4d0321f..00000000 --- a/Firmware/Tasks/Inc/MotorControlTask.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "MotorCAN_can_msgs.h" -#include "stm32xx_hal.h" -#include -#include "CANbus.h" -#include "inits.h" -#include "MotorSafeBits.h" -#include "InitTask.h" -#include "StatusLEDs.h" - -// this one is just used for testing. TODO: swap out once controls integration starts -static const EventBits_t motorDrivableBits = MOTOR_STATUS_BIT(MOTOR_CONTACTOR_ENABLED) - | MOTOR_STATUS_BIT(MOTOR_PRECHARGE_CONTACTOR_ENABLED); -// Real motor bits -// static const EventBits_t motorDrivableBits = MOTOR_STATUS_BIT(MOTOR_CONTACTOR_ENABLED) -// | MOTOR_STATUS_BIT(MOTOR_PRECHARGE_CONTACTOR_ENABLED) -// | MOTOR_STATUS_BIT(PEDALS_READING_ACCELERATOR) -// | MOTOR_STATUS_BIT(PEDALS_READING_BRAKE) -// | MOTOR_STATUS_BIT(DASHBOARD_IGNITION_MOTOR) -// | MOTOR_STATUS_BIT(BPS_SAFE); - - -void MotorControlTask_Init(void); - -void Task_MotorControl(); diff --git a/Firmware/Tasks/Inc/PrechargeTask.h b/Firmware/Tasks/Inc/PrechargeTask.h index d9083833..37aa87ba 100644 --- a/Firmware/Tasks/Inc/PrechargeTask.h +++ b/Firmware/Tasks/Inc/PrechargeTask.h @@ -1,43 +1,56 @@ #pragma once -#include "FaultBits.h" -#include "Contactors.h" -#include "StatusLEDs.h" #include "ADC_Sense.h" +#include "CANbus.h" +#include "Contactors.h" +#include "FaultBits.h" #include "InitTask.h" #include "MotorSafeBits.h" -#include "CANbus.h" -#include "CarCAN_can_msgs.h" +#include "StatusLEDs.h" #include -#include "VCUReceiveCANTask.h" // Precharge thresholds -#define OVERVOLTAGE_THRESHOLD_MV 140000 // 140 V -#define UNDERVOLTAGE_THRESHOLD_MV 80000 // 80.0 V +#define OVERVOLTAGE_THRESHOLD_MV 140000 // 140 V +#define UNDERVOLTAGE_THRESHOLD_MV 80000 // 80.0 V // Fixed-point scaling for ratio comparisons -#define RATIO_SCALE 1000 +#define RATIO_SCALE 1000 // 900/1000 = 0.900, 800/1000 = 0.800 // TODO: Test and increase hysterisis threshold closer to 90% -#define PRECHARGE_THRESHOLD_90 900 -#define PRECHARGE_THRESHOLD_80 800 // NOTE: The second threshold exists to account for hysteresis, so that we don't drop out of the run state after successfully precharging just because of a small ADC reading change +#define PRECHARGE_THRESHOLD_90 900 +#define PRECHARGE_THRESHOLD_80 800 +// NOTE: The second threshold exists to account for hysteresis, so that we don't drop out of +// the run state after successfully precharging just because of a small ADC reading change // Allowed difference between motor and battery voltage -#define VOLTAGE_TOLERANCE_NUMERATOR 22 -#define VOLTAGE_TOLERANCE_DENOMINATOR 20 // Motor voltage can at most 10% higher than battery voltage +#define VOLTAGE_TOLERANCE_NUMERATOR 22 +// Motor voltage can at most 10% higher than battery voltage +#define VOLTAGE_TOLERANCE_DENOMINATOR 20 + +// Precharge time to 90% -> 0.9 = 1 - e^(-t/RC), so t = -RC * ln(1-0.9) = 2.3*RC. +// For our case, R = 110 Ohms and C = 1 mF -> t = 253 ms. +#define PRECHARGE_TIMEOUT_MS 400 +#define ADC_TIMEOUT_MS 20 + +#define PRECHARGE_STATE_LIST(X) \ + X(WAITING) /* Waiting for ignition state */ \ + X(INITIAL) /* Precharge hasn't started; closing main contactor and starting timer */ \ + X(PRECHARGING) /* Precharge started successfully, close contactor and check hysterisis */ \ + X(COMPLETE) /* Precharge got through hysterisis, now continuously polling ADC */ + +typedef enum { +#define X(name) PRECHARGE_STATE_##name, + PRECHARGE_STATE_LIST(X) +#undef X + PRECHARGE_STATE_COUNT +} PrechargeState_e; -#define PRECHARGE_TIMEOUT_MS 400 // Precharge time to 90% -> 0.9 = 1 - e^(-t/RC), so t = -RC * ln(1-0.9) = 2.3*RC. For our case, R = 110 Ohms and C = 1 mF -> t = 253 ms. -#define ADC_TIMEOUT_MS 20 +// Names for faults for printing/debugging purposes. Indexed by FaultID_e values +extern const char *precharge_state_names[]; -typedef enum -{ - PRECHARGE_STATE_WAITING, // Waiting for ignition state - PRECHARGE_STATE_INITIAL, // Precharge sequence hasn't started, start by closing main contactor and starting a timer to check for precharge timeout - PRECHARGE_STATE_PRECHARGING, // Precharge sequence started successfully, close contactor and check hysterisis - PRECHARGE_STATE_RUN, // Precharge got through hysterisis, now continuously polling ADC - PRECHARGE_STATE_NUM -} Precharge_State_t; +#define PRECHARGE_STATE_BIT(state) (1UL << (state)) +#define PRECHARGE_STATE_MASK ((EventBits_t)((1UL << NUM_PRECHARGE_STATES) - 1UL)) /** * @brief Precharge task initialization function, initializes ADC, printf, and contactors @@ -47,7 +60,8 @@ typedef enum void Init_PrechargeTask(); /** - * @brief Checks the repeated fault conditions for precharge sequence, if any fault condition is met, will call fault handler and not return + * @brief Checks the repeated fault conditions for precharge sequence, if any fault condition is + * met, will call fault handler and not return * @param Motor_Voltage most recent motor voltage reading in mV * @param Battery_Voltage most recent battery voltage reading in mV * @retval None @@ -55,13 +69,13 @@ void Init_PrechargeTask(); void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage); /** - * @brief Precharge task main execution function, implements precharge pseudo state machine and fault handling + * @brief Precharge task main execution function, implements precharge pseudo state machine and + * fault handling * @param None * @retval None */ void Task_Precharge(); -void Ignition_Off(); /* handle for the Precharge task, defined in PrechargeTask.c */ extern TaskHandle_t hprecharge_task; diff --git a/Firmware/Tasks/Inc/ReadMotorCAN.h b/Firmware/Tasks/Inc/ReadMotorCAN.h deleted file mode 100644 index 93c44155..00000000 --- a/Firmware/Tasks/Inc/ReadMotorCAN.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "stm32xx_hal.h" -#include "CANbus.h" -#include "CAN_FD.h" -#include "MotorCAN_can_msgs.h" - -void Init_ReadMotorCAN(); - -void Task_ReadMotorCAN(); diff --git a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h b/Firmware/Tasks/Inc/UpdateFSMInputsTask.h deleted file mode 100644 index 352d7ffd..00000000 --- a/Firmware/Tasks/Inc/UpdateFSMInputsTask.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "inits.h" -#include "CANbus.h" -#include "FSM.h" - -#define BRAKE_THRESH 42.0f // percent -#define BRAKE_THRESH_HYST 30.0f // percent - -#define ACCEPTABLE_PEDAL_DEVIATION 3 // percent - -void Task_UpdateFSMInputs(void *args __attribute__((unused))); diff --git a/Firmware/Tasks/Inc/UpdateVCUInputsTask.h b/Firmware/Tasks/Inc/UpdateVCUInputsTask.h new file mode 100644 index 00000000..930d4936 --- /dev/null +++ b/Firmware/Tasks/Inc/UpdateVCUInputsTask.h @@ -0,0 +1,26 @@ +#pragma once + +#include "inits.h" +#include "CANbus.h" +#include "FSMTask.h" + +#define BRAKE_THRESH 42.0f // percent +#define BRAKE_THRESH_HYST 30.0f // percent + +#define ACCEPTABLE_PEDAL_DEVIATION 3 // percent + +typedef struct { + driver_input_status_t driver_input; + pedal_status_t accel_brake; + lws_standard_t lws; + controls_status_t controls_status; + mc_status_t motor_status; + bps_status_t bps_status; + mc_velocitymeasurement_t motor_velocity; + +} VCUDataIn_t; + +extern VCUDataIn_t * volatile g_data_read; +extern VCUDataIn_t * volatile g_data_write; + +void Task_UpdateVCUInputs(void *args __attribute__((unused))); diff --git a/Firmware/Tasks/Inc/VCUReceiveCANTask.h b/Firmware/Tasks/Inc/VCUReceiveCANTask.h deleted file mode 100644 index a84fd3dc..00000000 --- a/Firmware/Tasks/Inc/VCUReceiveCANTask.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "StatusLEDs.h" -#include "InitTask.h" -#include "MotorSafeBits.h" -#include "CANbus.h" -#include "CarCAN_can_msgs.h" -#include -#include "PrechargeTask.h" - -// enables the fdcan3 recieve hook, calls can_fd_rx_callback_hook everytime a can rx interrupt happens -#define FDCAN3_RECV_HOOK_EN -#define DRIVER_INPUT_QUEUE_SIZE 32 -#define BPS_QUEUE_SIZE 32 -#define IGNITION_MOTOR_INDEX 1 // index of motor ignition in driver input status message -#define CAN_BLOCKING_TIME_MS 100 - -extern uint8_t Start_Precharge; -extern uint8_t End_Precharge; - -void Task_VCUReceiveCAN(); \ No newline at end of file diff --git a/Firmware/Tasks/Inc/fsm_table_dnr.h b/Firmware/Tasks/Inc/fsm_table_dnr.h index 707801dc..aa2b035b 100644 --- a/Firmware/Tasks/Inc/fsm_table_dnr.h +++ b/Firmware/Tasks/Inc/fsm_table_dnr.h @@ -5,7 +5,7 @@ */ #pragma once -#include "FSM.h" +#include "FSMTask.h" extern MocoState_t FSM[NUM_STATES]; diff --git a/Firmware/Tasks/Src/DriverInputTask.c b/Firmware/Tasks/Src/DriverInputTask.c deleted file mode 100644 index 3054a22d..00000000 --- a/Firmware/Tasks/Src/DriverInputTask.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "DriverInputTask.h" - -#define DRIVER_INPUT_TEST_TASK_STACK configMINIMAL_STACK_SIZE -#define DRIVER_INPUT_TEST_TASK_PRIO (tskIDLE_PRIORITY + 1) - -static void initDriverInputHeader(FDCAN_TxHeaderTypeDef *tx_header) -{ - tx_header->Identifier = CAN_ID_DRIVER_INPUT_STATUS; - tx_header->IdType = FDCAN_STANDARD_ID; - tx_header->TxFrameType = FDCAN_DATA_FRAME; - tx_header->DataLength = FDCAN_DLC_BYTES_8; - tx_header->ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header->BitRateSwitch = FDCAN_BRS_OFF; - tx_header->FDFormat = FDCAN_CLASSIC_CAN; - tx_header->TxEventFifoControl = FDCAN_NO_TX_EVENTS; - tx_header->MessageMarker = 0; -} - -void Task_DriverInputTest(void *pvParameters) -{ - FDCAN_TxHeaderTypeDef header; - uint8_t tx_data[8] = {0}; - - initDriverInputHeader(&header); - - vTaskDelay(pdMS_TO_TICKS(2000)); // let everything initialize first - - tx_data[IGNITION_MOTOR_INDEX] = 1; - - if (Car_CANBus_Send(&header, tx_data, portMAX_DELAY) == CAN_OK) - { - printf("TEST: Sent ignition ON frame\r\n"); - } - else - { - printf("TEST: Failed to send ignition ON frame\r\n"); - } - - vTaskDelete(NULL); -} \ No newline at end of file diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 546d4c75..f0dc01fc 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -6,14 +6,12 @@ #define DEFINE_FSM_TABLE #include "fsm_table_dnr.h" +#include "rollover_speed_table.h" -#include "BPSCAN_can_msgs.h" -#include "CarCAN_can_msgs.h" -#include "FSM.h" +#include "FSMTask.h" +#include "UpdateVCUInputsTask.h" #include "FaultBits.h" -#include "MotorCAN_can_msgs.h" #include "Watchdogs.h" -#include "rollover_speed_table.h" #include #include @@ -24,11 +22,7 @@ EventGroupHandle_t fsmInputGroup = {0}; MocoState_t current_state = {0}; -static FSMDataIn_t fsm_input_a = {0}; -static FSMDataIn_t fsm_input_b = {0}; -FSMDataIn_t * volatile g_data_read = &fsm_input_a; -FSMDataIn_t * volatile g_data_write = &fsm_input_b; static bool rollover_limit_active = false; static volatile uint16_t fsm_inputs = 0; diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index 51f06dbb..7992b88b 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -13,21 +13,6 @@ static void FHT_kill_precharge_task(void) { } } -static FDCAN_TxHeaderTypeDef VCUSendStatusHeader; - -static void initVCUSendStatusHeader(FDCAN_TxHeaderTypeDef *tx_header) -{ - tx_header->Identifier = CAN_ID_VCU_STATUS; - tx_header->IdType = FDCAN_STANDARD_ID; - tx_header->TxFrameType = FDCAN_DATA_FRAME; - tx_header->DataLength = FDCAN_DLC_BYTES_8; - tx_header->ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header->BitRateSwitch = FDCAN_BRS_OFF; - tx_header->FDFormat = FDCAN_CLASSIC_CAN; - tx_header->TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header->MessageMarker = 0; -} - // Sets fault LEDs based on which faults are active. Multiple faults may be // active at once, so multiple LEDs may be set. static void FHT_set_fault_leds(EventBits_t bits) { @@ -94,15 +79,6 @@ void Task_FaultHandler(void *args __attribute__((unused))) { Error_Handler(); } - if (stateBits_init() != 1) - { - // Fault bit initialization failed - Error_Handler(); - } - - initVCUSendStatusHeader(&VCUSendStatusHeader); -} - while (true) { EventBits_t bits = faults_wait(FAULT_ID_COUNT, portMAX_DELAY); @@ -138,4 +114,4 @@ void Task_FaultHandler(void *args __attribute__((unused))) { vTaskDelay(pdMS_TO_TICKS(1000)); } -} +} \ No newline at end of file diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 199ff613..f0b94dab 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -1,8 +1,4 @@ #include "InitTask.h" -#include "FSM.h" -#include "VCUStatusTask.h" -#include "PrechargeTask.h" -#include "UpdateFSMInputsTask.h" #include "StatusLEDs.h" /* ===================== Stack Size Definitions ===================== */ @@ -10,8 +6,8 @@ /* ===================== Static Task Buffers ===================== */ -StaticTask_t FaultHandlerTask_Buffer; -StackType_t FaultHandlerTask_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; +StaticTask_t FaultHandler_Task_Buffer; +StackType_t FaultHandler_Task_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; StaticTask_t Precharge_Task_Buffer; StackType_t Precharge_Task_Stack[PRECHARGE_TASK_STACK_SIZE]; @@ -25,17 +21,8 @@ StackType_t FSM_Task_Stack[FSM_TASK_STACK_SIZE]; StaticTask_t VCUStatus_Task_Buffer; StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; -StaticTask_t UpdateFSMInputs_Task_Buffer; -StackType_t UpdateFSMInputs_Task_Stack[UPDATE_FSM_INPUTS_STACK_SIZE]; - -// StaticTask_t Motor_Control_Task_Buffer; -// StackType_t Motor_Control_Task_Stack[MOTOR_CONTROL_TASK_STACK_SIZE]; - -StaticTask_t VCUReceiveCAN_Task_Buffer; -StackType_t VCUReceiveCAN_Task_Stack[configMINIMAL_STACK_SIZE]; - -StaticTask_t Driver_Input_Task_Buffer; -StackType_t Driver_Input_Task_Stack[configMINIMAL_STACK_SIZE]; +StaticTask_t UpdateVCUInputs_Task_Buffer; +StackType_t UpdateVCUInputs_Task_Stack[UPDATE_VCU_INPUTS_STACK_SIZE]; void Task_Init() { @@ -43,8 +30,10 @@ void Task_Init() __HAL_RCC_PWR_CLK_ENABLE(); Init_UART_Printf(); - CAN_Init(); + // prech + ADC_Sense_Init(); + contactor_init(); MotorSafeBits_Init(); MotorCAN_Init(); @@ -54,7 +43,6 @@ void Task_Init() // Required for VCU status testing faults_init(); - Init_PrechargeTask(); xTaskCreateStatic( Task_FaultHandler, @@ -62,8 +50,8 @@ void Task_Init() FAULT_HANDLER_TASK_STACK_SIZE, NULL, FAULT_HANDLER_THREAD_PRIO, - FaultHandlerTask_Stack, - &FaultHandlerTask_Buffer + FaultHandler_Task_Stack, + &FaultHandler_Task_Buffer ); xTaskCreateStatic( @@ -97,36 +85,15 @@ void Task_Init() ); xTaskCreateStatic( - Task_UpdateFSMInputs, + Task_UpdateVCUInputs, "Update FSM Inputs Thread", - UPDATE_FSM_INPUTS_STACK_SIZE, + UPDATE_VCU_INPUTS_STACK_SIZE, NULL, - UPDATE_FSM_INPUTS_THREAD_PRIO, - UpdateFSMInputs_Task_Stack, - &UpdateFSMInputs_Task_Buffer + UPDATE_VCU_INPUTS_THREAD_PRIO, + UpdateVCUInputs_Task_Stack, + &UpdateVCUInputs_Task_Buffer ); - // while (1) { - // LED_toggle(HB); - // HAL_Delay(100); - // } - Task_VCUReceiveCAN, // Task function - "VCUReceiveCAN", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - tskIDLE_PRIORITY + 2, // Task priority - VCUReceiveCAN_Task_Stack, // Task handle - &VCUReceiveCAN_Task_Buffer // Static task buffer (optional) - ); - - xTaskCreateStatic( - Task_DriverInputTest, - "DriverInputTest", - configMINIMAL_STACK_SIZE, - NULL, - tskIDLE_PRIORITY + 2, - Driver_Input_Task_Stack, - &Driver_Input_Task_Buffer); vTaskDelete(NULL); } \ No newline at end of file diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index fc0b1fb5..35701cdc 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -1,270 +1,213 @@ #include "PrechargeTask.h" +#include "UpdateVCUInputsTask.h" #define PRECHARGE_PRINTF_DEBUG_PERIOD_MS 10000 #define PRECHARGE_PRINTF_DEBUG_COUNTER (PRECHARGE_PRINTF_DEBUG_PERIOD_MS / PRECHARGE_TASK_DELAY_MS) -/* handle for the Precharge task, defined here */ +// Handle for precharge task, can be deleted TaskHandle_t hprecharge_task = NULL; -StaticEventGroup_t xPrechargeEventGroup; -EventGroupHandle_t xPrechargeEventGroup_handle; - -uint32_t Battery_Voltage = 0; -uint32_t Motor_Voltage = 0; -static Precharge_State_t State; -uint8_t Ignition_State = 0; -// uint8_t Ignition_Off_Initiated = 0; -TickType_t offTick = 0; - -static FDCAN_TxHeaderTypeDef VCUSendVoltageHeader; - -static void initVCUSendVoltageHeader(FDCAN_TxHeaderTypeDef *tx_header) -{ - tx_header->Identifier = CAN_ID_VCU_PRECHARGE_VOLTAGES; - tx_header->IdType = FDCAN_STANDARD_ID; - tx_header->TxFrameType = FDCAN_DATA_FRAME; - tx_header->DataLength = FDCAN_DLC_BYTES_8; - tx_header->ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header->BitRateSwitch = FDCAN_BRS_OFF; - tx_header->FDFormat = FDCAN_CLASSIC_CAN; - tx_header->TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header->MessageMarker = 0; -} +uint32_t battery_voltage = 0; +uint32_t motor_voltage = 0; +PrechargeState_e g_precharge_state = PRECHARGE_STATE_WAITING; + +const char *precharge_state_names[PRECHARGE_STATE_COUNT] = { +#define X(name) [PRECHARGE_STATE_##name] = #name, + PRECHARGE_STATE_LIST(X) +#undef X +}; -void Ignition_Off() -{ +void PT_ign_off() { printf("Ignition OFF, opening motor precharge contactor\r\n"); - if (contactor_set(MOTOR_PRE_CONTACTOR, OPEN, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) - { - set_faultBit(PRECHARGE_SENSE_TIMEOUT_FAULT); + if (contactor_set(MOTOR_PRE_CONTACTOR, OPEN, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) { + faults_set(FAULT_ID_PRECHARGE_SENSE_TIMEOUT); } printf("Ignition OFF, opening motor contactor\r\n"); - if (contactor_set(MOTOR_CONTACTOR, OPEN, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) - { - set_faultBit(MOTOR_SENSE_TIMEOUT_FAULT); + if (contactor_set(MOTOR_CONTACTOR, OPEN, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) { + faults_set(FAULT_ID_MOTOR_SENSE_TIMEOUT); } - State = PRECHARGE_STATE_WAITING; // Return task to idle/waiting state + taskENTER_CRITICAL(); + g_precharge_state = PRECHARGE_STATE_WAITING; + taskEXIT_CRITICAL(); printf("Ignition OFF, shutdown complete\r\n"); } -void Check_Ignition_State() -{ - // if (Ignition_Off_Initiated && (xTaskGetTickCount() - offTick) > pdMS_TO_TICKS(IGNITION_OFF_DELAY_MS)) +// TODO add message countign to c=transition +void PT_check_ign() { + static bool last_ign; + bool curr_ign = g_data_read->driver_input.Ignition_Motor; - if (Start_Precharge) - { - Start_Precharge = 0; - Ignition_State = 1; - State = PRECHARGE_STATE_INITIAL; + if (curr_ign && !last_ign) { + taskENTER_CRITICAL(); + g_precharge_state = PRECHARGE_STATE_INITIAL; + taskEXIT_CRITICAL(); printf("Ignition ON, starting precharge sequence\r\n"); - } - else if (End_Precharge) - { - End_Precharge = 0; - Ignition_State = 0; + } else if (!curr_ign && last_ign) { printf("Ignition OFF, stopping precharge sequence\r\n"); - Ignition_Off(); + PT_ign_off(); } -} -void Init_PrechargeTask() -{ - // Event Group init - xPrechargeEventGroup_handle = xEventGroupCreateStatic(&xPrechargeEventGroup); - configASSERT(xPrechargeEventGroup_handle); // check if handle is set - // xEventGroupClearBits(xReadADCEventGroup_handle, /* The event group being updated. */ - // 0xFF ); /* The bits being cleared. */ - - // Inits ADC & contactors - ADC_Sense_Init(); - contactor_init(); - MotorSafeBits_Init(); - initVCUSendVoltageHeader(&VCUSendVoltageHeader); -} - -// encodes battery and motor voltage into an array of bytes for can_send -static void packMotorVoltage(vcu_precharge_voltages_t voltages, uint8_t tx_data[8]) -{ - memcpy(&tx_data[0], &(voltages.VCU_Precharge_Battery_Voltage), sizeof(uint32_t)); // TODO: Have Precharge task push adc readings into the can messages struct - memcpy(&tx_data[4], &(voltages.VCU_Precharge_Motor_Voltage), sizeof(uint32_t)); + last_ign = curr_ign; } void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage) { if (Motor_Voltage > (Battery_Voltage * VOLTAGE_TOLERANCE_NUMERATOR / VOLTAGE_TOLERANCE_DENOMINATOR)) { - // Fault handler faults_set(FAULT_ID_MOTOR_GT_BATTERY); } + // is battery booming if (Battery_Voltage > OVERVOLTAGE_THRESHOLD_MV) { - /* BATTERY ABOUT TO GO BOOM */ - // Fault handler faults_set(FAULT_ID_BATTERY_OVERVOLTAGE); } + // Is batt voltage too low or disconnected? if (Battery_Voltage < UNDERVOLTAGE_THRESHOLD_MV) { - /* Battery voltage is too low or battery is disconnected, treat as fault */ - // Fault handler faults_set(FAULT_ID_BATTERY_UNDERVOLTAGE); } if (contactor_get_sense(MOTOR_CONTACTOR) != contactor_get_commanded_state(MOTOR_CONTACTOR)) { - // Fault handler faults_set(FAULT_ID_MOTOR_SENSE_MISMATCH); } if (contactor_get_sense(MOTOR_PRE_CONTACTOR) != contactor_get_commanded_state(MOTOR_PRE_CONTACTOR)) { - // Fault handler faults_set(FAULT_ID_PRECHARGE_SENSE_MISMATCH); } } -static void print_Precharge_State(Precharge_State_t State) { - switch (State) { - case PRECHARGE_STATE_INITIAL: - printf("Precharge State: Initial\r\n"); - break; - case PRECHARGE_STATE_PRECHARGING: - printf("Precharge State: Precharging\r\n"); - break; - case PRECHARGE_STATE_RUN: - printf("Precharge State: Run\r\n"); - break; - default: - printf("Unknown\r\n"); - break; - } +static void PT_print_state(PrechargeState_e state) { + printf("Fault: %s\r\n", precharge_state_names[state]); } void Task_Precharge() { - Init_PrechargeTask(); - - State = PRECHARGE_STATE_WAITING; - static TickType_t Start_Tick = 0; - + TickType_t timeout_start_tick = 0; ADC_Sense_Result ADC_Result = {0}; - - uint8_t VCU_tx_data[8]; - vcu_precharge_voltages_t precharge_voltages = {0}; uint8_t can_send_errors = 0; uint8_t printDebugCounter = 0; while (1) { if (Read_ADC(ADC_TIMEOUT_MS, &ADC_Result) != ADC_SENSE_OK) { - Error_Handler(); + faults_set(FAULT_ID_PRECHARGE_SENSE_TIMEOUT); } - Battery_Voltage = ADC_Result.Battery_Voltage; - Motor_Voltage = ADC_Result.Motor_Voltage; - precharge_voltages.VCU_Precharge_Battery_Voltage = Battery_Voltage; - precharge_voltages.VCU_Precharge_Motor_Voltage = Motor_Voltage; + battery_voltage = ADC_Result.Battery_Voltage; + motor_voltage = ADC_Result.Motor_Voltage; - packMotorVoltage(precharge_voltages, VCU_tx_data); + can_status_t result = + CarCAN_Send_Precharge_Voltages(motor_voltage, battery_voltage, portMAX_DELAY); - if (Car_CANBus_Send(&VCUSendVoltageHeader, VCU_tx_data, portMAX_DELAY) == CAN_ERR) - { + if (result == CAN_ERR) { can_send_errors++; - } - else - { + } else { can_send_errors = 0; } - printf("Motor: %ld mV | Battery: %ld mV\r\n", Motor_Voltage, Battery_Voltage); - - switch (State) - { - case PRECHARGE_STATE_WAITING: - - set_stateBit(PRECHARGE_WAITING_STATE); - Check_Ignition_State(); // Wait for ignition on message from driver input task, then move to initial precharge state - printf("Precharge State: Waiting for Ignition\r\n"); - - break; - case PRECHARGE_STATE_INITIAL: // Startup state: Closes main contactor and moves to precharging state - - Check_Ignition_State(); + printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); - set_stateBit(PRECHARGE_INITIAL_STATE); + PT_check_ign(); - printf("Precharge State: Initial\r\n"); + PrechargeState_e curr_state; + taskENTER_CRITICAL(); + curr_state = g_precharge_state; + taskEXIT_CRITICAL(); - if (contactor_set(MOTOR_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) - { - set_faultBit(MOTOR_SENSE_TIMEOUT_FAULT); - } + switch (curr_state) { + case PRECHARGE_STATE_WAITING: + // Wait for ignition on message from driver input task, + // then move to initial precharge state + printf("Precharge State: Waiting for Ignition\r\n"); + break; - State = PRECHARGE_STATE_PRECHARGING; + // Startup state: Closes main contactor and moves to precharging state + case PRECHARGE_STATE_INITIAL: + printf("Precharge State: Initial\r\n"); - set_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); - - // Start a timer for precharging - Start_Tick = xTaskGetTickCount(); - - break; - case PRECHARGE_STATE_PRECHARGING: // Precharging state: Waits for battery voltage to reach 90% of motor voltage, then closes precharge contactor and moves to run state - - Check_Ignition_State(); - - set_stateBit(PRECHARGE_PRECHARGING_STATE); - - Fault_Checker(Motor_Voltage, Battery_Voltage); // Check for faults while precharging, if any fault conditions are met, will call fault handler and not proceed with precharge sequence - - const TickType_t Current_Tick = xTaskGetTickCount(); // Check how long we've been precharging for, fault if not precharged after PRECHARGE_TIMEOUT_MS - printf("Precharge State: Precharging\r\n"); - if ((Current_Tick - Start_Tick) > pdMS_TO_TICKS(PRECHARGE_TIMEOUT_MS)) // Faults if precharging takes too long - { - // Check if motor voltage is within 90% of battery voltage (precharge complete) - if (Motor_Voltage * RATIO_SCALE >= Battery_Voltage * PRECHARGE_THRESHOLD_90) - { - set_faultBit(MOTOR_SENSE_TIMEOUT_FAULT); + if (contactor_set(MOTOR_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, NORMAL) != + SUCCESS) { + faults_set(FAULT_ID_MOTOR_SENSE_TIMEOUT); } - State = PRECHARGE_STATE_PRECHARGING; - } - // Start a timer for precharging - set_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); - Start_Tick = xTaskGetTickCount(); - break; - case PRECHARGE_STATE_RUN: // Run state: Continuously checks that motor voltage stays within 80% of battery voltage - - Check_Ignition_State(); - - set_stateBit(PRECHARGE_RUN_STATE); - - Fault_Checker(Motor_Voltage, Battery_Voltage); // Check for faults while precharging, if any fault conditions are met, will call fault handler and not proceed with precharge sequence - - // Use 80% threshold for hysteresis - printf("Precharge State: Run\r\n"); - if (Motor_Voltage * RATIO_SCALE < Battery_Voltage * PRECHARGE_THRESHOLD_80) - { - } - break; - default: - break; + taskENTER_CRITICAL(); + g_precharge_state = PRECHARGE_STATE_PRECHARGING; + taskEXIT_CRITICAL(); + + set_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); + + // Start a timer for precharging + timeout_start_tick = xTaskGetTickCount(); + break; + + // Precharging state: Waits for battery voltage to reach 90% of motor voltage, + // then closes precharge contactor and moves to run state + case PRECHARGE_STATE_PRECHARGING: + // Check for faults while precharging, if any fault conditions are met, + // will call fault handler and not proceed with precharge sequence + Fault_Checker(motor_voltage, battery_voltage); + + // Check how long we've been precharging for, fault if not precharged after + // PRECHARGE_TIMEOUT_MS + const TickType_t timeout_curr_tick = xTaskGetTickCount(); + printf("Precharge State: Precharging\r\n"); + + // Faults if precharging takes too long + if ((timeout_curr_tick - timeout_start_tick) > + pdMS_TO_TICKS(PRECHARGE_TIMEOUT_MS)) { + // Check if motor voltage is within 90% of battery voltage (precharge complete) + if (motor_voltage * RATIO_SCALE >= battery_voltage * PRECHARGE_THRESHOLD_90) { + if (contactor_set(MOTOR_PRE_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, + false) != SUCCESS) { + faults_set(FAULT_ID_MOTOR_SENSE_TIMEOUT); + } + taskENTER_CRITICAL(); + g_precharge_state = PRECHARGE_STATE_COMPLETE; + taskEXIT_CRITICAL(); + } else { + faults_set(FAULT_ID_PRECHARGE_TIMEOUT); + } + } + set_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); + break; + + // Run state: Continuously checks that motor voltage stays + // within 80% of battery voltage (Threshold lowered to 80%) + // after precharge is complete + case PRECHARGE_STATE_COMPLETE: + // Check for faults while precharging, if any fault + // conditions are met, will call fault handler and + // not proceed with precharge sequence + Fault_Checker(motor_voltage, battery_voltage); + + // Use 80% threshold for hysteresis + if (motor_voltage * RATIO_SCALE < battery_voltage * PRECHARGE_THRESHOLD_80) { + faults_set(FAULT_ID_MOTOR_LT_BATTERY); + } + break; + default: + break; } - if (printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER) - { + taskENTER_CRITICAL(); + curr_state = g_precharge_state; + taskEXIT_CRITICAL(); + + if (printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER) { // prints battery and motor voltage - printf("Motor: %ld mV | Battery: %ld mV\r\n", - Motor_Voltage, - Battery_Voltage); + printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); // prints current precharge state - print_Precharge_State(State); + PT_print_state(curr_state); printDebugCounter = 0; } // set the Precharge Complete LED - LED_set(PRECHARGE_COMPLETE, State == PRECHARGE_STATE_RUN ? LED_ON : LED_OFF); + LED_set(PRECHARGE_COMPLETE, curr_state == PRECHARGE_STATE_COMPLETE ? LED_ON : LED_OFF); // update the motor safe bits with Contactor state if (contactor_get_sense(MOTOR_PRE_CONTACTOR) == CLOSED) { diff --git a/Firmware/Tasks/Src/UpdateFSMInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c similarity index 89% rename from Firmware/Tasks/Src/UpdateFSMInputsTask.c rename to Firmware/Tasks/Src/UpdateVCUInputsTask.c index b210010c..aaa9875e 100644 --- a/Firmware/Tasks/Src/UpdateFSMInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -1,4 +1,4 @@ -#include "UpdateFSMInputsTask.h" +#include "UpdateVCUInputsTask.h" #include "Contactors.h" #include "FaultBits.h" #include "event_groups.h" @@ -7,6 +7,12 @@ static float brake_threshold = BRAKE_THRESH; +static VCUDataIn_t fsm_input_a = {0}; +static VCUDataIn_t fsm_input_b = {0}; + +VCUDataIn_t * volatile g_data_read = &fsm_input_a; +VCUDataIn_t * volatile g_data_write = &fsm_input_b; + static void rebuild_inputs(void) { EventBits_t s = 0; @@ -77,12 +83,12 @@ void UFI_throw_faults() { faults_set_mask(mask); } -void Task_UpdateFSMInputs(void *args __attribute__((unused))) { +void Task_UpdateVCUInputs(void *args __attribute__((unused))) { TickType_t last = xTaskGetTickCount(); while (1) { // update from can - FSMDataIn_t *volatile update = g_data_write; + VCUDataIn_t *volatile update = g_data_write; MotorCAN_Recv_Status(&update->motor_status, 0); MotorCAN_Recv_Velocity(&update->motor_velocity, 0); @@ -94,13 +100,16 @@ void Task_UpdateFSMInputs(void *args __attribute__((unused))) { CarCAN_Recv_Driver_Input(&update->driver_input, 0); CarCAN_Recv_LWS(&update->lws, 0); - FSMDataIn_t *volatile tmp; + VCUDataIn_t *volatile tmp; taskENTER_CRITICAL(); tmp = g_data_read; g_data_read = g_data_write; g_data_write = tmp; taskEXIT_CRITICAL(); - memcpy(g_data_write, g_data_read, sizeof(FSMDataIn_t)); + + + + memcpy(g_data_write, g_data_read, sizeof(VCUDataIn_t)); // Throw relevant faults UFI_throw_faults(); diff --git a/Firmware/Tasks/Src/VCUReceiveCANTask.c b/Firmware/Tasks/Src/VCUReceiveCANTask.c deleted file mode 100644 index 21145a43..00000000 --- a/Firmware/Tasks/Src/VCUReceiveCANTask.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "VCUReceiveCANTask.h" - -static StaticQueue_t driverInputQueueBuffer; -static uint8_t driverInputQueueStorage[DRIVER_INPUT_QUEUE_SIZE * sizeof(can_rx_payload_t)]; -static QueueHandle_t driverInputQueue; - -static StaticQueue_t BPSQueueBuffer; -static uint8_t BPSQueueStorage[BPS_QUEUE_SIZE * sizeof(can_rx_payload_t)]; -static QueueHandle_t BPSQueue; - -can_rx_payload_t payload; -uint8_t Start_Precharge = 0; -uint8_t End_Precharge = 0; - -static void initDriverInputQueue() -{ - driverInputQueue = xQueueCreateStatic( - DRIVER_INPUT_QUEUE_SIZE, - sizeof(can_rx_payload_t), - driverInputQueueStorage, - &driverInputQueueBuffer); - - if (driverInputQueue == NULL) - { - return; - } -} - -static void initBPSQueue() -{ - BPSQueue = xQueueCreateStatic( - BPS_QUEUE_SIZE, - sizeof(can_rx_payload_t), - BPSQueueStorage, - &BPSQueueBuffer); - - if (BPSQueue == NULL) - { - return; - } -} - -void Init_VCUReceiveCANTask() -{ - initDriverInputQueue(); - initBPSQueue(); -} - -void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, can_rx_payload_t recv_payload) -{ - BaseType_t higherPriorityTaskWoken = pdFALSE; - - if (recv_payload.header.Identifier == CAN_ID_DRIVER_INPUT_STATUS) - { - if (driverInputQueue != NULL) - { - xQueueSendFromISR(driverInputQueue, &recv_payload, &higherPriorityTaskWoken); - } - } - else if (recv_payload.header.Identifier == CAN_ID_BPS_STATUS) - { - if (BPSQueue != NULL) - { - xQueueSendFromISR(BPSQueue, &recv_payload, &higherPriorityTaskWoken); - } - } - - portYIELD_FROM_ISR(higherPriorityTaskWoken); -} - -void Task_VCUReceiveCAN() -{ - Init_VCUReceiveCANTask(); - - while(1) - { - if (xQueueReceive(driverInputQueue, &payload, pdMS_TO_TICKS(CAN_BLOCKING_TIME_MS)) == pdTRUE) - { - if (payload.header.Identifier == CAN_ID_DRIVER_INPUT_STATUS && payload.data[IGNITION_MOTOR_INDEX] == 1 && Ignition_State == 0) - { - Start_Precharge = 1; - } - else if (payload.header.Identifier == CAN_ID_DRIVER_INPUT_STATUS && payload.data[IGNITION_MOTOR_INDEX] == 0 && Ignition_State == 1) - { - // offTick = xTaskGetTickCount(); - End_Precharge = 1; // Turning off ignition - } - } - - if (xQueueReceive(BPSQueue, &payload, pdMS_TO_TICKS(CAN_BLOCKING_TIME_MS)) == pdTRUE) - { - if(payload.header.Identifier == CAN_ID_BPS_STATUS && payload.data[0] != BPS_STATUS_BPS_FAULT_OK) - { - set_faultBit(BPS_FAULT); - } - } - } -} \ No newline at end of file diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 5259ef11..9a737725 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -1,11 +1,11 @@ #include "VCUStatusTask.h" -#include "CANbus.h" -#include "event_groups.h" +#include "UpdateVCUInputsTask.h" +#include "FSMTask.h" #include "FaultBits.h" #include "Contactors.h" -#include "FSM.h" #include "Watchdogs.h" #include "StatusLEDs.h" +#include "event_groups.h" void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { uint8_t buf[CAN_DLC_VCU_STATUS]; diff --git a/Firmware/config/Inc/can1_recv_entries.h b/Firmware/config/Inc/can1_recv_entries.h index 83127d66..26a0097a 100644 --- a/Firmware/config/Inc/can1_recv_entries.h +++ b/Firmware/config/Inc/can1_recv_entries.h @@ -8,5 +8,3 @@ CAN_RECV_ENTRY(CAN_ID_MC_INFO, 2, true) CAN_RECV_ENTRY(CAN_ID_MC_STATUS, 2, true) CAN_RECV_ENTRY(CAN_ID_MC_BUSMEASUREMENT, 2, true) CAN_RECV_ENTRY(CAN_ID_MC_VELOCITYMEASUREMENT, 2, true) -CAN_RECV_ENTRY(0x421, 5, true) -CAN_RECV_ENTRY(CAN_ID_VCU_PRECHARGE_VOLTAGES, 6, true) \ No newline at end of file diff --git a/Firmware/scripts/fsm_generator.py b/Firmware/scripts/fsm_generator.py index ba5e0f41..475ad0a3 100644 --- a/Firmware/scripts/fsm_generator.py +++ b/Firmware/scripts/fsm_generator.py @@ -148,7 +148,7 @@ def write_table(path, fn, label): f" * Regenerate: python3 generate_fsm.py --{label.lower()}\n" f" */\n\n" f"#pragma once\n" - f'#include "FSM.h"\n\n' + f'#include "FSMTask.h"\n\n' f"extern MocoState_t FSM[NUM_STATES];\n\n" f"#ifdef DEFINE_FSM_TABLE\n" f"MocoState_t FSM[NUM_STATES] = {{\n\n" From 99dbcaed36813238ca5a4f0e06790249a54e3ada Mon Sep 17 00:00:00 2001 From: Gavin Wang Date: Sun, 12 Apr 2026 03:43:27 -0500 Subject: [PATCH 12/27] precharge working; tested --- Firmware/Drivers/Src/CANbus.c | 4 +- Firmware/Drivers/Src/UART_Init.c | 97 +++++++++++++++--------- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/InitTask.h | 1 + Firmware/Tasks/Inc/PrechargeTask.h | 15 +--- Firmware/Tasks/Src/FSMTask.c | 2 + Firmware/Tasks/Src/FaultHandlerTask.c | 20 ++--- Firmware/Tasks/Src/InitTask.c | 8 +- Firmware/Tasks/Src/PrechargeTask.c | 6 +- Firmware/Tasks/Src/UpdateVCUInputsTask.c | 18 +++-- Firmware/Tasks/Src/VCUStatusTask.c | 2 +- Firmware/core/Src/main.c | 4 +- 12 files changed, 99 insertions(+), 80 deletions(-) diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index da23a6bc..7c3cde30 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -80,10 +80,10 @@ can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay) { if (out == NULL) return CAN_EMPTY; FDCAN_RxHeaderTypeDef header = {0}; - uint8_t moco_status_rx_data[CAN_DLC_MC_VELOCITYMEASUREMENT] = {0}; + uint8_t moco_status_rx_data[CAN_DLC_MC_STATUS] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_MC_VELOCITYMEASUREMENT, &header, moco_status_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_MC_STATUS, &header, moco_status_rx_data, delay); if (result == CAN_OK) { out->MC_LIMIT_OutputVoltagePWM = (moco_status_rx_data[0] >> 0) & 0x1; diff --git a/Firmware/Drivers/Src/UART_Init.c b/Firmware/Drivers/Src/UART_Init.c index 4fe6739e..78b7abf9 100644 --- a/Firmware/Drivers/Src/UART_Init.c +++ b/Firmware/Drivers/Src/UART_Init.c @@ -1,6 +1,38 @@ #include "UART_Init.h" -void Init_UART_Printf() { +// Initializes the UART specified +void MX_UART_INIT(UART_HandleTypeDef *uartHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + if (uartHandle->Instance == USART3) + { + /** Initializes the peripherals clocks + */ + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3; + PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } + + /* USART3 clock enable */ + __HAL_RCC_USART3_CLK_ENABLE(); + + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**USART3 GPIO Configuration + PC10 ------> USART3_TX + PC11 ------> USART3_RX + */ + GPIO_InitStruct.Pin = USART3_TX_PIN | USART3_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF7_USART3; + HAL_GPIO_Init(USART3_PORT, &GPIO_InitStruct); + husart3->Instance = USART3; husart3->Init.BaudRate = 115200; husart3->Init.WordLength = UART_WORDLENGTH_8B; @@ -13,43 +45,34 @@ void Init_UART_Printf() { husart3->Init.ClockPrescaler = UART_PRESCALER_DIV1; husart3->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; - printf_init(husart3); + if (HAL_UART_Init(husart3) != HAL_OK) + { + Error_Handler(); + } + if (HAL_UARTEx_SetTxFifoThreshold(husart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) + { + Error_Handler(); + } + if (HAL_UARTEx_SetRxFifoThreshold(husart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) + { + Error_Handler(); + } + if (HAL_UARTEx_DisableFifoMode(husart3) != HAL_OK) + { + Error_Handler(); + } + } } -void HAL_UART_MspGPIOInit(UART_HandleTypeDef *huart) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; - - // for the ESP32 - if (huart->Instance == LPUART1) { - __HAL_RCC_GPIOB_CLK_ENABLE(); - /**LPUART1 GPIO Configuration - PB10 ------> LPUART1_RX - PB11 ------> LPUART1_TX - */ - GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - } +void Init_UART_Printf() +{ + husart3->Init.BaudRate = 115200; + husart3->Init.WordLength = UART_WORDLENGTH_8B; + husart3->Init.StopBits = UART_STOPBITS_1; + husart3->Init.Parity = UART_PARITY_NONE; + husart3->Init.Mode = UART_MODE_TX_RX; + husart3->Init.HwFlowCtl = UART_HWCONTROL_NONE; + husart3->Init.OverSampling = UART_OVERSAMPLING_16; - // for printf - if (huart->Instance == USART3) { - - __HAL_RCC_GPIOC_CLK_ENABLE(); - /**USART3 GPIO Configuration - PC10 ------> USART3_TX - PC11 ------> USART3_RX - */ - GPIO_InitStruct.Pin = USART3_TX_PIN | USART3_RX_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF7_USART3; - HAL_GPIO_Init(USART3_PORT, &GPIO_InitStruct); - } - - setvbuf(stdout, NULL, _IONBF, 0); - printf_init(husart3); + printf_init(husart3); } \ No newline at end of file diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 9380420f..25388609 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 9380420f26754d1d456631bae0b61521d4f977ac +Subproject commit 25388609b8009059da425a62e9060685e1bd144a diff --git a/Firmware/Tasks/Inc/InitTask.h b/Firmware/Tasks/Inc/InitTask.h index 633cb1c5..c4e77daf 100644 --- a/Firmware/Tasks/Inc/InitTask.h +++ b/Firmware/Tasks/Inc/InitTask.h @@ -53,6 +53,7 @@ extern StackType_t UpdateVCUInputs_Task_Stack[FSM_TASK_STACK_SIZE]; // Period the precharge thread runs at #define PRECHARGE_TASK_DELAY_MS 100 +extern TaskHandle_t precharge_task_handle; diff --git a/Firmware/Tasks/Inc/PrechargeTask.h b/Firmware/Tasks/Inc/PrechargeTask.h index 37aa87ba..bfd3484e 100644 --- a/Firmware/Tasks/Inc/PrechargeTask.h +++ b/Firmware/Tasks/Inc/PrechargeTask.h @@ -52,12 +52,6 @@ extern const char *precharge_state_names[]; #define PRECHARGE_STATE_BIT(state) (1UL << (state)) #define PRECHARGE_STATE_MASK ((EventBits_t)((1UL << NUM_PRECHARGE_STATES) - 1UL)) -/** - * @brief Precharge task initialization function, initializes ADC, printf, and contactors - * @param None - * @retval None - */ -void Init_PrechargeTask(); /** * @brief Checks the repeated fault conditions for precharge sequence, if any fault condition is @@ -76,10 +70,5 @@ void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage); */ void Task_Precharge(); - -/* handle for the Precharge task, defined in PrechargeTask.c */ -extern TaskHandle_t hprecharge_task; - -extern uint32_t Battery_Voltage; -extern uint32_t Motor_Voltage; -extern uint8_t Ignition_State; \ No newline at end of file +extern uint32_t battery_voltage; +extern uint32_t motor_voltage; \ No newline at end of file diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index f0dc01fc..6d8b99de 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -90,6 +90,8 @@ uint16_t fsm_get_inputs(void) { // goofy ahh logic, uses lut static float apply_rollover_limit(float requested_current) { + printf("Applying rollover limit, requested current: %.2f, vehicle velocity: %.2f, steering angle: %.1f\r\n", + requested_current, g_data_read->motor_velocity.MC_VehicleVelocity, (float)g_data_read->lws.LWS_Angle / 10.0f); int deg = abs((int)g_data_read->lws.LWS_Angle) / 10; if (deg > (int)ROLLOVER_TABLE_MAX_DEG) deg = (int)ROLLOVER_TABLE_MAX_DEG; diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index 7992b88b..d3ecf4c2 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -1,5 +1,5 @@ #include "FaultHandlerTask.h" -#include "PrechargeTask.h" // for hprecharge_task handle +#include "InitTask.h" // for hprecharge_task handle #include "Watchdogs.h" #define FAULT_LOOP_PRINTF_DELAY_MS 10000 @@ -7,9 +7,9 @@ static void FHT_kill_precharge_task(void) { - if (hprecharge_task != NULL) { - vTaskDelete(hprecharge_task); - hprecharge_task = NULL; + if (precharge_task_handle != NULL) { + vTaskDelete(precharge_task_handle); + precharge_task_handle = NULL; } } @@ -94,20 +94,20 @@ void Task_FaultHandler(void *args __attribute__((unused))) { printf("Fault Handler triggered: 0x%02lX\r\n", bits); // Loop to display/handle fault until system reset - uint32_t print_counter = 0; + // uint32_t print_counter = 0; while (true) { - print_counter++; - if (print_counter >= FAULT_PRINTF_COUNTER) { + // print_counter++; + // if (print_counter >= FAULT_PRINTF_COUNTER) { for (int i = 0; i < FAULT_ID_COUNT; i++) { if (bits & FAULT_BIT(i)) { printf("Fault: %s\r\n", fault_names[i]); } } - print_counter = 0; - } + // print_counter = 0; + // } FHT_set_fault_leds(bits); - LED_toggle(HB); + // LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(FAULT_LOOP_PERIOD_MS)); } } diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index f0b94dab..bf063463 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -24,11 +24,13 @@ StackType_t VCUStatus_Task_Stack[VCU_STATUS_TASK_STACK_SIZE]; StaticTask_t UpdateVCUInputs_Task_Buffer; StackType_t UpdateVCUInputs_Task_Stack[UPDATE_VCU_INPUTS_STACK_SIZE]; -void Task_Init() -{ +TaskHandle_t precharge_task_handle = NULL; + +void Task_Init() { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); + Init_UART_Printf(); // prech @@ -54,7 +56,7 @@ void Task_Init() &FaultHandler_Task_Buffer ); - xTaskCreateStatic( + precharge_task_handle = xTaskCreateStatic( Task_Precharge, "Precharge", PRECHARGE_TASK_STACK_SIZE, diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index 35701cdc..516f12dc 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -4,9 +4,6 @@ #define PRECHARGE_PRINTF_DEBUG_PERIOD_MS 10000 #define PRECHARGE_PRINTF_DEBUG_COUNTER (PRECHARGE_PRINTF_DEBUG_PERIOD_MS / PRECHARGE_TASK_DELAY_MS) -// Handle for precharge task, can be deleted -TaskHandle_t hprecharge_task = NULL; - uint32_t battery_voltage = 0; uint32_t motor_voltage = 0; PrechargeState_e g_precharge_state = PRECHARGE_STATE_WAITING; @@ -90,6 +87,7 @@ void Task_Precharge() { ADC_Sense_Result ADC_Result = {0}; uint8_t can_send_errors = 0; uint8_t printDebugCounter = 0; + LED_set(HALL_EFFECT, LED_ON); while (1) { if (Read_ADC(ADC_TIMEOUT_MS, &ADC_Result) != ADC_SENSE_OK) { @@ -223,6 +221,6 @@ void Task_Precharge() { } LED_toggle(HB); - vTaskDelay(PRECHARGE_TASK_DELAY_MS); + vTaskDelay(pdMS_TO_TICKS(PRECHARGE_TASK_DELAY_MS)); } } \ No newline at end of file diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index aaa9875e..a85ccdd7 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -23,12 +23,16 @@ static void rebuild_inputs(void) { else s |= NEUTRAL_BIT; - if (g_data_read->driver_input.Regen_Activate) s |= REGEN_BUTTON_BIT; - if (g_data_read->driver_input.Regen_Enable) s |= REGEN_ENABLED_BIT; - if (g_data_read->driver_input.Cruise_Enable) s |= CRUISE_CONTROL_BUTTON_BIT; - if (g_data_read->bps_status.BPS_Regen_OK) s |= READY_TO_REGEN_BIT; - // if (contactor_get_sense(MOTOR_CONTACTOR) && contactor_get_sense(MOTOR_PRE_CONTACTOR)) - s |= PRECHARGE_COMPLETE_BIT; + if (g_data_read->driver_input.Regen_Activate) + s |= REGEN_BUTTON_BIT; + if (g_data_read->driver_input.Regen_Enable) + s |= REGEN_ENABLED_BIT; + if (g_data_read->driver_input.Cruise_Enable) + s |= CRUISE_CONTROL_BUTTON_BIT; + if (g_data_read->bps_status.BPS_Regen_OK) + s |= READY_TO_REGEN_BIT; + if (contactor_get_sense(MOTOR_CONTACTOR) && contactor_get_sense(MOTOR_PRE_CONTACTOR)) + s |= PRECHARGE_COMPLETE_BIT; if (g_data_read->accel_brake.BrakePedal_Main_Pos >= brake_threshold) { s |= BRAKE_BIT; @@ -73,7 +77,7 @@ void UFI_throw_faults() { g_data_read->accel_brake.BrakePedal_Main_Fault || g_data_read->accel_brake.BrakePedal_Redundant_Fault || fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - - g_data_read->accel_brake.AccelPedal_Redundant_Pos) < ACCEPTABLE_PEDAL_DEVIATION) { + g_data_read->accel_brake.AccelPedal_Redundant_Pos) > ACCEPTABLE_PEDAL_DEVIATION) { mask |= FAULT_BIT(FAULT_ID_PEDAL_BOARD_FAULT); } diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 9a737725..dd05f45b 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -80,7 +80,7 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { CarCAN_Send(&tx_header, buf, sizeof(buf)); - LED_toggle(HB); + // LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(100)); } } \ No newline at end of file diff --git a/Firmware/core/Src/main.c b/Firmware/core/Src/main.c index 7d325778..dbc3520d 100644 --- a/Firmware/core/Src/main.c +++ b/Firmware/core/Src/main.c @@ -9,7 +9,7 @@ int main(void) SystemClock_Config(); LED_init(); - xTaskCreateStatic( + xTaskCreateStatic( Task_Init, // Task function "Init", // Name of the task (for debugging) configMINIMAL_STACK_SIZE, // Stack size in words @@ -19,9 +19,9 @@ int main(void) &Init_Task_Buffer // Static task buffer (optional) ); + vTaskStartScheduler(); - Error_Handler(); /* Infinite loop */ while (1) From 03d001db0dc112d176b66be7151a28f91e151fcb Mon Sep 17 00:00:00 2001 From: Akshay Date: Tue, 14 Apr 2026 03:33:37 -0500 Subject: [PATCH 13/27] goon --- Firmware/Drivers/Inc/CANbus.h | 1 + Firmware/Drivers/Inc/FaultBits.h | 42 +- Firmware/Drivers/Src/CANbus.c | 18 + Firmware/Drivers/Src/FaultBits.c | 25 + Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSMTask.h | 19 +- Firmware/Tasks/Inc/UpdateVCUInputsTask.h | 2 +- Firmware/Tasks/Src/FSMTask.c | 42 +- Firmware/Tasks/Src/InitTask.c | 7 +- Firmware/Tasks/Src/MotorTelemetryTask.c | 53 +- Firmware/Tasks/Src/PrechargeTask.c | 2 +- Firmware/Tasks/Src/UpdateVCUInputsTask.c | 1 + Firmware/Tasks/Src/VCUStatusTask.c | 102 ++- Firmware/config/Inc/BPSCAN_can_msgs.h | 218 +++-- Firmware/config/Inc/CarCAN_can_msgs.h | 901 ++++++++++++--------- Firmware/config/Inc/MotorCAN_can_msgs.h | 47 +- Firmware/config/Inc/SteeringCAN_can_msgs.h | 8 +- Firmware/config/Inc/can1_recv_entries.h | 2 + Firmware/scripts/fsm_generator.py | 23 +- Firmware/tests/FaultHandler_test.c | 41 - Firmware/tests/faulthandler_test.c | 45 + Firmware/tests/fsm_transition_test.c | 14 +- Firmware/tests/fsminputs_test | 69 -- Firmware/tests/fsminputs_test.c | 4 +- Firmware/tests/temp | 167 ---- 25 files changed, 988 insertions(+), 867 deletions(-) delete mode 100644 Firmware/tests/FaultHandler_test.c create mode 100644 Firmware/tests/faulthandler_test.c delete mode 100644 Firmware/tests/fsminputs_test delete mode 100644 Firmware/tests/temp diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index 7c0fea46..fc14a80e 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -17,6 +17,7 @@ can_status_t MotorCAN_Recv(uint32_t id, FDCAN_RxHeaderTypeDef *header, uint8_t d can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay); can_status_t MotorCAN_Recv_Velocity(mc_velocitymeasurement_t *out, TickType_t delay); +can_status_t MotorCAN_Recv_Control_Src(set_motor_cmd_src_t *out, TickType_t delay); can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay); diff --git a/Firmware/Drivers/Inc/FaultBits.h b/Firmware/Drivers/Inc/FaultBits.h index 0c45148a..8974084b 100644 --- a/Firmware/Drivers/Inc/FaultBits.h +++ b/Firmware/Drivers/Inc/FaultBits.h @@ -83,6 +83,33 @@ extern const char *fault_names[]; FAULT_BIT(FAULT_ID_MOTOR_LT_BATTERY) \ ) +#define WARNING_ID_LIST(X) \ + X(MOTOR_DIRECTION_CHANGE_LOCKOUT) \ + X(TIPPING_LIMIT_ACTIVE) \ + X(REGEN_NOT_ALLOWED) \ + X(REGEN_NOT_ENABLED) + +typedef enum { +#define X(name) WARNING_ID_##name, + WARNING_ID_LIST(X) +#undef X + WARNING_ID_COUNT +} WarningID_e; + +#if (configUSE_16_BIT_TICKS == 0) +#define MAX_WARNING_BITS 24U +#else +#define MAX_WARNING_BITS 8U +#endif + +_Static_assert(WARNING_ID_COUNT <= MAX_WARNING_BITS, + "Too many warning bits for EventGroup"); + +// Names for warnings for printing/debugging purposes. Indexed by WarningID_e values +extern const char *warning_names[]; + +#define WARNING_MASK_ALL ((1UL << WARNING_ID_COUNT) - 1) + /** * @brief Initializes fault bitmap and associated data structures. Must be * called before using any other functions in this module. @@ -158,4 +185,17 @@ EventBits_t faults_get(void); * active. If waiting for any fault, the returned bitmask will have all active * fault bits set. */ -EventBits_t faults_wait(FaultID_e id, TickType_t ticks); \ No newline at end of file +EventBits_t faults_wait(FaultID_e id, TickType_t ticks); + +/** + * @brief Set a warning. Non critical and just informational for driver. + * + * @param id The warning to set. + */ +void warning_set(WarningID_e id); + +/** + * @brief Get the state of all warnings. + * @return A bitmask of fault bits that are currently active. + */ +EventBits_t warning_get(void); \ No newline at end of file diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 7c3cde30..889b2e84 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -2,6 +2,7 @@ #include "BPSCAN_can_msgs.h" #include "CarCAN_can_msgs.h" #include "MotorCAN_can_msgs.h" +#include "UpdateVCUInputsTask.h" #include #include @@ -116,9 +117,26 @@ can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay) { return result; } +can_status_t MotorCAN_Recv_Control_Src(set_motor_cmd_src_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t moco_control_src_rx_data[CAN_DLC_SET_MOTOR_CMD_SRC] = {0}; + + can_status_t result = + can_fd_recv(motorfdcan, CAN_ID_SET_MOTOR_CMD_SRC, &header, moco_status_rx_data, delay); + + if (result == CAN_OK) { + out->Motor_Command_Source = moco_control_src_rx_data[0]; + } + + return result; +} + can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay) { if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; + if (g_data_read->motor_controls_src.Motor_Command_Source) return CAN_OK; FDCAN_TxHeaderTypeDef header = { .Identifier = CAN_ID_MC_DRIVECOMMAND, diff --git a/Firmware/Drivers/Src/FaultBits.c b/Firmware/Drivers/Src/FaultBits.c index 635bef93..1d0142b7 100644 --- a/Firmware/Drivers/Src/FaultBits.c +++ b/Firmware/Drivers/Src/FaultBits.c @@ -4,18 +4,34 @@ static StaticEventGroup_t faultBuffer; static EventGroupHandle_t faultGroup; +static StaticEventGroup_t warningBuffer; +static EventGroupHandle_t warningGroup; + const char *fault_names[FAULT_ID_COUNT] = { #define X(name) [FAULT_ID_##name] = #name, FAULT_ID_LIST(X) #undef X }; +const char *warning_names[WARNING_ID_COUNT] = { +#define X(name) [WARNING_ID_##name] = #name, + WARNING_ID_LIST(X) +#undef X +}; + bool faults_init(void) { faultGroup = xEventGroupCreateStatic(&faultBuffer); if (faultGroup == NULL) { return false; } xEventGroupClearBits(faultGroup, FAULT_MASK_ALL); + + warningGroup = xEventGroupCreateStatic(&warningBuffer); + if (warningGroup == NULL) { + return false; + } + xEventGroupClearBits(warningGroup, WARNING_MASK_ALL); + return true; } @@ -63,4 +79,13 @@ EventBits_t faults_wait(FaultID_e id, TickType_t ticks) { pdFALSE, // wait for any ticks ); +} + +void warning_set(WarningID_e id) { + configASSERT(id < FAULT_ID_COUNT); + xEventGroupSetBits(warningGroup, FAULT_BIT(id)); +} + +EventBits_t warning_get(void) { + return xEventGroupGetBits(warningGroup) & WARNING_MASK_ALL; } \ No newline at end of file diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 25388609..260c8f94 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 25388609b8009059da425a62e9060685e1bd144a +Subproject commit 260c8f9426f3be10e58db60574779992d7b38411 diff --git a/Firmware/Tasks/Inc/FSMTask.h b/Firmware/Tasks/Inc/FSMTask.h index 674e284a..3902825e 100644 --- a/Firmware/Tasks/Inc/FSMTask.h +++ b/Firmware/Tasks/Inc/FSMTask.h @@ -15,7 +15,10 @@ #include "CANbus.h" #include "event_groups.h" -// make sure if you change this to also change it in scripts/fsm_generator.py +/** + * @brief A list of inputs; uses X macro pattern + * @note Make sure if you change this to also change it in scripts/fsm_generator.py + */ #define BITFIELD_INPUT_LIST(X) \ X(NEUTRAL) \ X(FORWARD) \ @@ -28,7 +31,7 @@ X(PRECHARGE_COMPLETE) /** - * @brief + * @brief An enum of all FSM inputs */ typedef enum { #define X(name) BIT_IDX_##name, @@ -70,6 +73,15 @@ typedef struct { extern MocoState_t FSM[NUM_STATES]; extern MocoState_t current_state; +/** + * @brief Used for stepping current down at higher speeds. An array of these will + * represent a bin for min speed and associated max current. + */ +typedef struct { + float speed_mph; + uint8_t max_percent; +} swoc_threshold_t; + void fsm_init(void); void fsm_step(void); @@ -82,11 +94,8 @@ uint16_t fsm_get_inputs(void); bool fsm_is_over_rollover_speed(void); -void Task_UpdateControlStatus(void *args); void FSM_TaskInit(); void Task_FSM(void *args); -void Task_BroadcastVCUStatus(void *args); -void Task_UpdateControlStatus(void *args __attribute__((unused))); float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, uint8_t out_max); diff --git a/Firmware/Tasks/Inc/UpdateVCUInputsTask.h b/Firmware/Tasks/Inc/UpdateVCUInputsTask.h index 930d4936..502a6401 100644 --- a/Firmware/Tasks/Inc/UpdateVCUInputsTask.h +++ b/Firmware/Tasks/Inc/UpdateVCUInputsTask.h @@ -17,7 +17,7 @@ typedef struct { mc_status_t motor_status; bps_status_t bps_status; mc_velocitymeasurement_t motor_velocity; - + set_motor_cmd_src_t motor_controls_src; } VCUDataIn_t; extern VCUDataIn_t * volatile g_data_read; diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 6d8b99de..f578b988 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -14,16 +14,15 @@ #include "Watchdogs.h" #include #include +#include -#define MAX_VELOCITY 100.0f // meters per second +#define MAX_VELOCITY 100.0f // meters per second +#define MAX_CURRENT_PERCENT 100.0f StaticEventGroup_t fsmInputBuffer = {0}; EventGroupHandle_t fsmInputGroup = {0}; - MocoState_t current_state = {0}; - - static bool rollover_limit_active = false; static volatile uint16_t fsm_inputs = 0; @@ -37,9 +36,8 @@ static void handle_state_regen(void); static void handle_state_cruise(void); static void handle_state_disabled(void); -// static void update_from_can(void); -// static void rebuild_bitfield(void); static float apply_rollover_limit(float requested_current); +static uint8_t apply_swoc_speed_limit(float speed_mph); //must be called Before the FSM task gets called void FSM_TaskInit(){ @@ -129,7 +127,11 @@ static void handle_state_forward(void) { // if we're actually going backwards, let off the pedal until we slow down MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } else { - MotorCAN_Send_Drive_Cmd(MAX_VELOCITY, apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos), 0); + MotorCAN_Send_Drive_Cmd( + MAX_VELOCITY, + fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), + apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), + 0); } } @@ -138,16 +140,36 @@ static void handle_state_reverse(void) { // if we're actually going forwards, let off the pedal until we slow down MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } else { - MotorCAN_Send_Drive_Cmd(-MAX_VELOCITY, apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos), 0); + MotorCAN_Send_Drive_Cmd( + -MAX_VELOCITY, + fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), + apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), + 0); } } static void handle_state_cruise(void) { - float current = apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos); float velocity = rollover_limit_active ? 0.0f : MAX_VELOCITY; - MotorCAN_Send_Drive_Cmd(velocity, current, 0); + MotorCAN_Send_Drive_Cmd( + velocity, + fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), + apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), + 0); } +static const swoc_threshold_t SWOC_THRESHOLDS[] = {{10.0f, 80}, {17.0f, 75}, {20.0f, 70}, + {23.0f, 60}, {25.0f, 50}, {28.5f, 45}}; +static const size_t NUM_SWOC_THRESHOLDS = (sizeof(SWOC_THRESHOLDS) / sizeof(SWOC_THRESHOLDS[0])); + +static uint8_t apply_swoc_speed_limit(float speed_mph) { + uint8_t cap = MAX_CURRENT_PERCENT; // Default is 100% + for (size_t i = 0; i < NUM_SWOC_THRESHOLDS; ++i) { + if (speed_mph >= SWOC_THRESHOLDS[i].speed_mph) { + cap = SWOC_THRESHOLDS[i].max_percent; + } + } + return cap; +} //////// rtos tasks diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index bf063463..d9686fca 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -1,11 +1,6 @@ #include "InitTask.h" #include "StatusLEDs.h" -/* ===================== Stack Size Definitions ===================== */ - - - -/* ===================== Static Task Buffers ===================== */ StaticTask_t FaultHandler_Task_Buffer; StackType_t FaultHandler_Task_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; @@ -56,7 +51,7 @@ void Task_Init() { &FaultHandler_Task_Buffer ); - precharge_task_handle = xTaskCreateStatic( + precharge_task_handle = xTaskCreateStatic( Task_Precharge, "Precharge", PRECHARGE_TASK_STACK_SIZE, diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index c806e306..e1777197 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -37,26 +37,41 @@ void MotorTelemetryTask_Init(void) { return; } } -// void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, can_rx_payload_t recv_payload ){ + +void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, can_rx_payload_t recv_payload ){ -// // only forward motorCAN messages to CarCAN -// if(motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance){ - -// BaseType_t higherPriorityTaskWoken = pdFALSE; - -// xQueueSendFromISR( -// motorTelemetryQueue, -// &recv_payload, -// &higherPriorityTaskWoken -// ); -// // don't yield at the end of this since the rest of the ISR needs to run -// } -// } - -// xQueueSendFromISR(motorTelemetryQueue, &recv_payload, &higherPriorityTaskWoken); -// // don't yield at the end of this since the rest of the ISR needs to run -// } -// } + // only forward motorCAN messages to CarCAN + if(motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance){ + + BaseType_t higherPriorityTaskWoken = pdFALSE; + + xQueueSendFromISR( + motorTelemetryQueue, + &recv_payload, + &higherPriorityTaskWoken + ); + // don't yield at the end of this since the rest of the ISR needs to run + + + FDCAN_TxHeaderTypeDef tx_header = {0}; + tx_header.Identifier = recv_payload.header.Identifier; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = FDCAN_DLC_BYTES(CAN_DLC_VCU_STATUS); + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; + tx_header.MessageMarker = 0; + + can_fd_send_isr(motorfdcan, &tx_header, recv_payload.data, higherPriorityTaskWoken); + } +} + + xQueueSendFromISR(motorTelemetryQueue, &recv_payload, &higherPriorityTaskWoken); + // don't yield at the end of this since the rest of the ISR needs to run + } +} void Task_MotorTelemetry() { diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index 516f12dc..e2e85fcf 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -55,7 +55,7 @@ void PT_check_ign() { void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage) { if (Motor_Voltage > (Battery_Voltage * VOLTAGE_TOLERANCE_NUMERATOR / VOLTAGE_TOLERANCE_DENOMINATOR)) { - faults_set(FAULT_ID_MOTOR_GT_BATTERY); + faults_set(FAULT_ID_MOTOR_GT_BATTERY); } // is battery booming diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index a85ccdd7..d9d23237 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -95,6 +95,7 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { VCUDataIn_t *volatile update = g_data_write; MotorCAN_Recv_Status(&update->motor_status, 0); MotorCAN_Recv_Velocity(&update->motor_velocity, 0); + MotorCAN_Recv_Control_Src(&update->motor_controls_src, 0); // making these motor can should be CARCAN diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index dd05f45b..70dd8331 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -1,73 +1,71 @@ #include "VCUStatusTask.h" -#include "UpdateVCUInputsTask.h" +#include "Contactors.h" #include "FSMTask.h" #include "FaultBits.h" -#include "Contactors.h" -#include "Watchdogs.h" #include "StatusLEDs.h" +#include "UpdateVCUInputsTask.h" +#include "Watchdogs.h" #include "event_groups.h" void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { uint8_t buf[CAN_DLC_VCU_STATUS]; while (1) { - // Byte 0: VCU_Fault — map internal faults to DBC enum - uint8_t vcu_fault = VCU_STATUS_VCU_FAULT_NO_FAULT; - if (faults_is_active(FAULT_ID_PRECHARGE_TIMEOUT)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_PRECHARGE_TIMEOUT; - else if(faults_is_active(VCU_STATUS_VCU_FAULT_MOTOR_PCHG_CONTACTOR_SENSE)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_PCHG_CONTACTOR_SENSE; - else if(faults_is_active(VCU_STATUS_VCU_FAULT_MOTOR_CONTACTOR_SENSE)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_CONTACTOR_SENSE; - else if (faults_is_active(FAULT_ID_MOTOR_DC_BUS_OVERVOLTAGE)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE; - else if (faults_is_active(FAULT_ID_MOTOR_15V_UNDERVOLTAGE)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE; - else if (faults_is_active(FAULT_ID_MOTOR_HARDWARE_OVERCURRENT) || - faults_is_active(FAULT_ID_MOTOR_SOFTWARE_OVERCURRENT) || - faults_is_active(FAULT_ID_MOTOR_BAD_HALL_SEQUENCE) || - faults_is_active(FAULT_ID_MOTOR_WD_RESET) || - faults_is_active(FAULT_ID_MOTOR_CONFIG_READ) || - faults_is_active(FAULT_ID_MOTOR_DESATURATION) || - faults_is_active(FAULT_ID_MOTOR_OVERSPEED)) - vcu_fault = VCU_STATUS_VCU_FAULT_MOTOR_CONTROLLER_FAULT; - buf[0] = vcu_fault; + // Byte 0 + uint8_t state = current_state.stateName & 0x0FU; + bool motor_ready = (current_state.stateName != DISABLED) && + (current_state.stateName != STATE_INIT) && + (current_state.stateName != CAR_NOT_READY); + bool motor_prech_cont_state = contactor_get_sense(MOTOR_PRE_CONTACTOR); + bool motor_cont_state = contactor_get_sense(MOTOR_CONTACTOR); + bool driver_inp_wdog = watchdog_is_alive(WD_IDX_DRIVER_INPUT); + buf[0] = (state) | (motor_ready << 4) | (motor_prech_cont_state << 5) | + (motor_cont_state << 6) | (driver_inp_wdog << 7); - + // Byte 1 + bool pedals_wdog = watchdog_is_alive(WD_IDX_ACCEL_BRAKE); + bool bps_wdog = watchdog_is_alive(WD_IDX_BPS_STATUS); + bool steering_wdog = watchdog_is_alive(WD_IDX_STEERING_ANGLE); + bool bps_fault = faults_is_active(FAULT_ID_BPS_FAULT); + bool controls_fault = faults_is_active(FAULT_ID_CONTROLS_FAULT); + bool motor_fault = !!(faults_get() & FAULT_MASK_MOTOR_ALL); + bool pedals_fault = !((bool)g_data_read->accel_brake.AccelPedal_Main_Fault) && + !((bool)g_data_read->accel_brake.AccelPedal_Redundant_Fault) && + !((bool)g_data_read->accel_brake.BrakePedal_Main_Fault) && + !((bool)g_data_read->accel_brake.BrakePedal_Redundant_Fault); + bool steering_fault = g_data_read->lws.LWS_Fault; + buf[1] = (pedals_wdog) | (bps_wdog << 1) | (steering_wdog << 2) | (bps_fault << 3) | + (controls_fault << 4) | (motor_fault << 5) | (pedals_fault << 6) | + (steering_fault << 7); - - // Byte 1: status bits per DBC positions 8-14 - bool pedals_ok = !g_data_read->accel_brake.AccelPedal_Main_Fault && - !g_data_read->accel_brake.AccelPedal_Redundant_Fault && - !g_data_read->accel_brake.BrakePedal_Main_Fault && - !g_data_read->accel_brake.BrakePedal_Redundant_Fault; + buf[2] = g_data_read->motor_controls_src | + (!!(fsm_get_inputs() & READY_TO_REGEN_BIT) << 1) | + (g_data_read->bps_status.BPS_Regen_OK << 2) | + (faults_is_active(FAULT_ID_PRECHARGE_TIMEOUT) << 3) | + (faults_is_active(FAULT_ID_PRECHARGE_SENSE_TIMEOUT) << 4) | + (faults_is_active(FAULT_ID_PRECHARGE_SENSE_MISMATCH) << 5) | + (faults_is_active(FAULT_ID_MOTOR_SENSE_MISMATCH) << 6) | + (faults_is_active(FAULT_ID_MOTOR_SENSE_TIMEOUT) << 7); - bool driver_input_ok = !faults_is_active(FAULT_ID_GENERIC_WATCHDOG_FAULT) && - !faults_is_active(FAULT_ID_CONTROLS_FAULT); + buf[3] = (faults_is_active(FAULT_ID_BATTERY_OVERVOLTAGE)) | + (faults_is_active(FAULT_ID_BATTERY_UNDERVOLTAGE) << 1) | + (faults_is_active(FAULT_ID_MOTOR_GT_BATTERY) << 2) | // TODO check if this is right + (faults_is_active(FAULT_ID_MOTOR_LT_BATTERY) << 3) | + (faults_any_active() << 4) | // TODO: make this "other" + (faults_is_active(FAULT_ID_MOTOR_GT_BATTERY) << 2) | - bool steering_angle_ok = g_data_read->lws.LWS_Fault == 0; - // while(1){ - // LED_toggle(HB); - // vTaskDelay(pdMS_TO_TICKS(100)); - // } - buf[1] = ((uint8_t)contactor_get_sense(MOTOR_CONTACTOR) << 0) | // Motor_Contactor_State - ((uint8_t)contactor_get_sense(MOTOR_PRE_CONTACTOR) << 1) | // Motor_Precharge_Contactor_State - ((uint8_t) (contactor_get_sense(MOTOR_PRE_CONTACTOR) && vcu_fault == 0) << 2) | // Motor_Ready_To_Drive - ((uint8_t)driver_input_ok << 3) | // VCU_Driver_Input_OK - ((uint8_t)pedals_ok << 4) | // VCU_Pedals_OK - ((uint8_t)!!(fsm_get_inputs() & READY_TO_REGEN_BIT) << 5) | // VCU_Regen_OK - ((uint8_t)(current_state.stateName == REGEN) << 6) | // VCU_Regen_Active - ((uint8_t)steering_angle_ok << 7); // VCU_Steering_Angle_OK (not implemented, set to OK) + buf[3] = fsm_get_inputs(); // this supposed to have fsm states as well but stateName covers + // it for now - // Byte 2: VCU_FSM_State bits [3:0] - buf[2] = (uint8_t)(current_state.stateName & 0x0FU); + // for viewing faults in status + int faults = 0x0FFFFFF & faults_get(); + buf[4] = (faults >> 16) & 0xFF; + buf[5] = (faults >> 8) & 0xFF; + buf[6] = faults & 0xFF; - buf[3] = fsm_get_inputs() ; //this supposed to have fsm states as well but stateName covers it for now - - - FDCAN_TxHeaderTypeDef tx_header = {0}; + FDCAN_TxHeaderTypeDef tx_header = {0}; tx_header.Identifier = CAN_ID_VCU_STATUS; tx_header.IdType = FDCAN_STANDARD_ID; tx_header.TxFrameType = FDCAN_DATA_FRAME; diff --git a/Firmware/config/Inc/BPSCAN_can_msgs.h b/Firmware/config/Inc/BPSCAN_can_msgs.h index 406d8bdd..adde79c9 100644 --- a/Firmware/config/Inc/BPSCAN_can_msgs.h +++ b/Firmware/config/Inc/BPSCAN_can_msgs.h @@ -21,6 +21,7 @@ #define CAN_ID_BPS_VT5_TEMPERATURE_ARR 0x15 #define CAN_ID_BPS_VT6_TEMPERATURE_ARR 0x16 #define CAN_ID_BPS_VT7_TEMPERATURE_ARR 0x17 +#define CAN_ID_BPS_PACK_CURRENT_RAWV 0x755 #define CAN_ID_BPS_BALANCE_DISCHARGE 0x7A0 /* ================= CAN Length Macros ================= */ @@ -42,153 +43,186 @@ #define CAN_DLC_BPS_VT5_TEMPERATURE_ARR 7 #define CAN_DLC_BPS_VT6_TEMPERATURE_ARR 7 #define CAN_DLC_BPS_VT7_TEMPERATURE_ARR 7 +#define CAN_DLC_BPS_PACK_CURRENT_RAWV 3 #define CAN_DLC_BPS_BALANCE_DISCHARGE 1 /* ================= Value Table Enums ================= */ typedef enum { - BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT0_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt0_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT1_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt1_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT2_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt2_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT3_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt3_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT4_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt4_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT5_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt5_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT6_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt6_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VT7_VOLTAGE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_vt7_voltage_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, + BPS_PACK_CURRENT_BPS_AMPERES_FAULT_OK = 0, + BPS_PACK_CURRENT_BPS_AMPERES_FAULT_OUT_OF_BOUNDS = 1, + BPS_PACK_CURRENT_BPS_AMPERES_FAULT_OVER_CURRENT_DISCHARGE_ = 2, + BPS_PACK_CURRENT_BPS_AMPERES_FAULT_OVER_CURRENT_CHARGE_ = 3, + BPS_PACK_CURRENT_BPS_AMPERES_FAULT_MESSAGE_WATCHDOG = 4, +} bps_pack_current_bps_amperes_fault_e; + +typedef enum { BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT0_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt0_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT1_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt1_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT2_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt2_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT3_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt3_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT4_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt4_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT5_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt5_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT6_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt6_temperature_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_VT7_TEMPERATURE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_vt7_temperature_arr_bps_temperature_tap_fault_e; /* ================= Message Structs ================= */ @@ -242,66 +276,72 @@ typedef struct { } bps_vt7_voltage_arr_t; typedef struct { + uint8_t BPS_Amperes_Fault; int32_t Main_Battery_Current; - uint16_t Main_Battery_Current_RawV; + uint8_t FrameID_Amperes; } bps_pack_current_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt0_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt1_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt2_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt3_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt4_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt5_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt6_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_RawV; } bps_vt7_temperature_arr_t; +typedef struct { + uint16_t Main_Battery_Current_RawV; + uint8_t FrameID_Amperes; +} bps_pack_current_rawv_t; + typedef struct { uint8_t BPS_Segment_idx; uint8_t BPS_Tap_idx; diff --git a/Firmware/config/Inc/CarCAN_can_msgs.h b/Firmware/config/Inc/CarCAN_can_msgs.h index 239822fd..f6ccbf55 100644 --- a/Firmware/config/Inc/CarCAN_can_msgs.h +++ b/Firmware/config/Inc/CarCAN_can_msgs.h @@ -7,14 +7,12 @@ #define CAN_ID_BPS_STATUS 0x1 #define CAN_ID_BPS_VOLTAGE_AGGREGATE_ARR 0xB #define CAN_ID_BPS_TEMPERATURE_AGGREGATE_ARR 0xC -#define CAN_ID_BPS_TEMP_RAWV_AGGREGATE_ARR 0xD +#define CAN_ID_CHARGERINTERFACE_STATUS 0xE #define CAN_ID_VCU_STATUS 0x18 #define CAN_ID_CONTROLS_STATUS 0x19 #define CAN_ID_BPS_PRECHARGE_VOLTAGES 0x20 #define CAN_ID_VCU_PRECHARGE_VOLTAGES 0x21 #define CAN_ID_PEDAL_STATUS 0x50 -#define CAN_ID_PEDAL_ACCEL_RAWV 0x51 -#define CAN_ID_PEDAL_BRAKE_RAWV 0x52 #define CAN_ID_DRIVER_INPUT_STATUS 0x60 #define CAN_ID_MPPT_A_POWERMEASUREMENTS 0x200 #define CAN_ID_MPPT_A_STATUS 0x201 @@ -38,7 +36,7 @@ #define CAN_ID_MPPT_C_SETOUTPUTVOLTAGELIMIT 0x251 #define CAN_ID_MPPT_C_SETOUTPUTCURRENTLIMIT 0x252 #define CAN_ID_SUPP_BATTERY_STATUS 0x300 -#define CAN_ID_SUPP_BATTERY_CHARGER_STATUS 0x301 +#define CAN_ID_SUPP_CHARGING_STATUS 0x301 #define CAN_ID_PDU_STATUS_ARR 0x350 #define CAN_ID_PDU_SET_SWITCH_ARR 0x351 #define CAN_ID_PDU_SET_CURRENT_LIMIT_ARR 0x352 @@ -48,22 +46,25 @@ #define CAN_ID_LV_CARRIER_STATUS 0x600 #define CAN_ID_BRAKE_PRESSURE_1 0x650 #define CAN_ID_BRAKE_PRESSURE_2 0x651 -#define CAN_ID_DISPLAY_STATUS 0x700 -#define CAN_ID_TELEMETRY_STATUS 0x750 +#define CAN_ID_DISPLAY_STATUS 0x680 +#define CAN_ID_TELEMETRY_STATUS 0x700 +#define CAN_ID_BPS_TEMP_RAWV_AGGREGATE_ARR 0x750 +#define CAN_ID_SUPP_MEASUREMENTS_RAWV 0x751 +#define CAN_ID_SUPP_VICOR_MEASUREMENTS_RAWV 0x752 +#define CAN_ID_PEDAL_BRAKE_RAWV 0x753 +#define CAN_ID_PEDAL_ACCEL_RAWV 0x754 /* ================= CAN Length Macros ================= */ #define CAN_DLC_BPS_STATUS 8 #define CAN_DLC_BPS_VOLTAGE_AGGREGATE_ARR 6 #define CAN_DLC_BPS_TEMPERATURE_AGGREGATE_ARR 8 -#define CAN_DLC_BPS_TEMP_RAWV_AGGREGATE_ARR 4 -#define CAN_DLC_VCU_STATUS 4 +#define CAN_DLC_CHARGERINTERFACE_STATUS 5 +#define CAN_DLC_VCU_STATUS 6 #define CAN_DLC_CONTROLS_STATUS 6 #define CAN_DLC_BPS_PRECHARGE_VOLTAGES 6 #define CAN_DLC_VCU_PRECHARGE_VOLTAGES 6 #define CAN_DLC_PEDAL_STATUS 6 -#define CAN_DLC_PEDAL_ACCEL_RAWV 5 -#define CAN_DLC_PEDAL_BRAKE_RAWV 5 #define CAN_DLC_DRIVER_INPUT_STATUS 2 #define CAN_DLC_MPPT_A_POWERMEASUREMENTS 8 #define CAN_DLC_MPPT_A_STATUS 5 @@ -86,8 +87,8 @@ #define CAN_DLC_MPPT_C_PERFORMSWEEP 5 #define CAN_DLC_MPPT_C_SETOUTPUTVOLTAGELIMIT 2 #define CAN_DLC_MPPT_C_SETOUTPUTCURRENTLIMIT 2 -#define CAN_DLC_SUPP_BATTERY_STATUS 5 -#define CAN_DLC_SUPP_BATTERY_CHARGER_STATUS 5 +#define CAN_DLC_SUPP_BATTERY_STATUS 6 +#define CAN_DLC_SUPP_CHARGING_STATUS 6 #define CAN_DLC_PDU_STATUS_ARR 5 #define CAN_DLC_PDU_SET_SWITCH_ARR 1 #define CAN_DLC_PDU_SET_CURRENT_LIMIT_ARR 3 @@ -95,663 +96,786 @@ #define CAN_DLC_COOLANT_TEMPERATURE 4 #define CAN_DLC_RADIATOR_FANSPEED 8 #define CAN_DLC_LV_CARRIER_STATUS 1 -#define CAN_DLC_BRAKE_PRESSURE_1 6 -#define CAN_DLC_BRAKE_PRESSURE_2 6 +#define CAN_DLC_BRAKE_PRESSURE_1 5 +#define CAN_DLC_BRAKE_PRESSURE_2 5 #define CAN_DLC_DISPLAY_STATUS 2 #define CAN_DLC_TELEMETRY_STATUS 8 +#define CAN_DLC_BPS_TEMP_RAWV_AGGREGATE_ARR 4 +#define CAN_DLC_SUPP_MEASUREMENTS_RAWV 5 +#define CAN_DLC_SUPP_VICOR_MEASUREMENTS_RAWV 5 +#define CAN_DLC_PEDAL_BRAKE_RAWV 5 +#define CAN_DLC_PEDAL_ACCEL_RAWV 5 /* ================= Value Table Enums ================= */ typedef enum { - BPS_STATUS_BPS_FAULT_DISCHARGING_OVERCURRENT = 17, - BPS_STATUS_BPS_FAULT_CHARGING_OVERCURRENT = 16, - BPS_STATUS_BPS_FAULT_ESTOP_3 = 15, - BPS_STATUS_BPS_FAULT_ESTOP_2 = 14, - BPS_STATUS_BPS_FAULT_ESTOP_1 = 13, - BPS_STATUS_BPS_FAULT_ARRAY_PCHG_CONTACTOR_SENSE = 12, - BPS_STATUS_BPS_FAULT_ARRAY_CONTACTOR_SENSE = 11, - BPS_STATUS_BPS_FAULT_HV_MINUS_CONTACTOR_SENSE = 10, - BPS_STATUS_BPS_FAULT_HV_PLUS_CONTACTOR_SENSE = 9, - BPS_STATUS_BPS_FAULT_SEGMENT_WATCHDOG = 8, - BPS_STATUS_BPS_FAULT_INTERNAL_WATCHDOG = 7, - BPS_STATUS_BPS_FAULT_ARRAY_PRECHARGE_TIMEOUT = 6, - BPS_STATUS_BPS_FAULT_ELCON = 5, - BPS_STATUS_BPS_FAULT_OVERTEMPERATURE = 4, - BPS_STATUS_BPS_FAULT_REGEN = 3, - BPS_STATUS_BPS_FAULT_UNDERVOLTAGE = 2, - BPS_STATUS_BPS_FAULT_OVERVOLTAGE = 1, BPS_STATUS_BPS_FAULT_OK = 0, + BPS_STATUS_BPS_FAULT_OVERVOLTAGE = 1, + BPS_STATUS_BPS_FAULT_UNDERVOLTAGE = 2, + BPS_STATUS_BPS_FAULT_REGEN = 3, + BPS_STATUS_BPS_FAULT_OVERTEMPERATURE = 4, + BPS_STATUS_BPS_FAULT_ELCON = 5, + BPS_STATUS_BPS_FAULT_ARRAY_PRECHARGE_TIMEOUT = 6, + BPS_STATUS_BPS_FAULT_INTERNAL_WATCHDOG = 7, + BPS_STATUS_BPS_FAULT_SEGMENT_WATCHDOG = 8, + BPS_STATUS_BPS_FAULT_HV_PLUS_CONTACTOR_SENSE = 9, + BPS_STATUS_BPS_FAULT_HV_MINUS_CONTACTOR_SENSE = 10, + BPS_STATUS_BPS_FAULT_ARRAY_CONTACTOR_SENSE = 11, + BPS_STATUS_BPS_FAULT_ARRAY_PCHG_CONTACTOR_SENSE = 12, + BPS_STATUS_BPS_FAULT_ESTOP_1 = 13, + BPS_STATUS_BPS_FAULT_ESTOP_2 = 14, + BPS_STATUS_BPS_FAULT_ESTOP_3 = 15, + BPS_STATUS_BPS_FAULT_CHARGING_OVERCURRENT = 16, + BPS_STATUS_BPS_FAULT_DISCHARGING_OVERCURRENT = 17, BPS_STATUS_BPS_FAULT_AMPERES_WATCHDOG = 18, } bps_status_bps_fault_e; typedef enum { - BPS_STATUS_BPS_CHARGE_OK_OK = 1, BPS_STATUS_BPS_CHARGE_OK_NOT_OK = 0, + BPS_STATUS_BPS_CHARGE_OK_OK = 1, } bps_status_bps_charge_ok_e; typedef enum { - BPS_STATUS_BPS_REGEN_OK_OK = 1, BPS_STATUS_BPS_REGEN_OK_NOT_OK = 0, + BPS_STATUS_BPS_REGEN_OK_OK = 1, } bps_status_bps_regen_ok_e; typedef enum { - BPS_STATUS_HV_PLUS_CONTACTOR_STATE_CLOSED = 1, BPS_STATUS_HV_PLUS_CONTACTOR_STATE_OPEN = 0, + BPS_STATUS_HV_PLUS_CONTACTOR_STATE_CLOSED = 1, } bps_status_hv_plus_contactor_state_e; typedef enum { - BPS_STATUS_HV_MINUS_CONTACTOR_STATE_CLOSED = 1, BPS_STATUS_HV_MINUS_CONTACTOR_STATE_OPEN = 0, + BPS_STATUS_HV_MINUS_CONTACTOR_STATE_CLOSED = 1, } bps_status_hv_minus_contactor_state_e; typedef enum { - BPS_STATUS_ARRAY_CONTACTOR_STATE_CLOSED = 1, BPS_STATUS_ARRAY_CONTACTOR_STATE_OPEN = 0, + BPS_STATUS_ARRAY_CONTACTOR_STATE_CLOSED = 1, } bps_status_array_contactor_state_e; typedef enum { - BPS_STATUS_ARRAY_PRECHARGE_CONTACTOR_STATE_CLOSED = 1, BPS_STATUS_ARRAY_PRECHARGE_CONTACTOR_STATE_OPEN = 0, + BPS_STATUS_ARRAY_PRECHARGE_CONTACTOR_STATE_CLOSED = 1, } bps_status_array_precharge_contactor_state_e; typedef enum { - BPS_STATUS_BPS_SEGMENT0_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT0_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT0_STATUS_FAULT = 1, } bps_status_bps_segment0_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT1_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT1_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT1_STATUS_FAULT = 1, } bps_status_bps_segment1_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT2_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT2_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT2_STATUS_FAULT = 1, } bps_status_bps_segment2_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT3_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT3_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT3_STATUS_FAULT = 1, } bps_status_bps_segment3_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT4_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT4_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT4_STATUS_FAULT = 1, } bps_status_bps_segment4_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT5_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT5_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT5_STATUS_FAULT = 1, } bps_status_bps_segment5_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT6_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT6_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT6_STATUS_FAULT = 1, } bps_status_bps_segment6_status_e; typedef enum { - BPS_STATUS_BPS_SEGMENT7_STATUS_FAULT = 1, BPS_STATUS_BPS_SEGMENT7_STATUS_OK = 0, + BPS_STATUS_BPS_SEGMENT7_STATUS_FAULT = 1, } bps_status_bps_segment7_status_e; typedef enum { - BPS_VOLTAGE_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_OK = 1, - BPS_VOLTAGE_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_NOT_OK = 0, -} bps_voltage_aggregate_arr_bps_tap_msg_wdog_e; - -typedef enum { - BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 3, - BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 2, - BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_OK = 0, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_BQ_I2C_READ_ERROR = 1, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_OUT_OF_BOUNDS = 2, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_OVER_VOLTAGE = 3, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_UNDER_VOLTAGE = 4, + BPS_VOLTAGE_AGGREGATE_ARR_BPS_VOLTAGE_TAP_FAULT_MESSAGE_WATCHDOG = 5, } bps_voltage_aggregate_arr_bps_voltage_tap_fault_e; typedef enum { - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_VCC = 2, - BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_SHORT_TO_GND = 1, BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OK = 0, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_GND_ = 1, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OUT_OF_BOUNDS_SHORT_TO_VCC_ = 2, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_DISCONNECTED = 3, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_OVER_TEMPERATURE = 4, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_OVER_TEMPERATURE = 5, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_UNDER_TEMPERATURE = 6, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_CHARGE_UNDER_TEMPERATURE = 7, + BPS_TEMPERATURE_AGGREGATE_ARR_BPS_TEMPERATURE_TAP_FAULT_MESSAGE_WATCHDOG = 8, } bps_temperature_aggregate_arr_bps_temperature_tap_fault_e; typedef enum { - BPS_TEMP_RAWV_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_OK = 1, - BPS_TEMP_RAWV_AGGREGATE_ARR_BPS_TAP_MSG_WDOG_NOT_OK = 0, -} bps_temp_rawv_aggregate_arr_bps_tap_msg_wdog_e; + CHARGERINTERFACE_STATUS_ELCON_WATCHDOG_NOT_OK = 0, + CHARGERINTERFACE_STATUS_ELCON_WATCHDOG_OK = 1, +} chargerinterface_status_elcon_watchdog_e; typedef enum { - VCU_STATUS_VCU_FAULT_MOTOR_HV_UNDERVOLTAGE = 6, - VCU_STATUS_VCU_FAULT_MOTOR_HV_OVERVOLTAGE = 5, - VCU_STATUS_VCU_FAULT_MOTOR_CONTROLLER_FAULT = 4, - VCU_STATUS_VCU_FAULT_MOTOR_PRECHARGE_TIMEOUT = 3, - VCU_STATUS_VCU_FAULT_MOTOR_PCHG_CONTACTOR_SENSE = 2, - VCU_STATUS_VCU_FAULT_MOTOR_CONTACTOR_SENSE = 1, - VCU_STATUS_VCU_FAULT_NO_FAULT = 0, -} vcu_status_vcu_fault_e; + CHARGERINTERFACE_STATUS_ELCON_CMD_TIMEOUT_NOT_OK = 0, + CHARGERINTERFACE_STATUS_ELCON_CMD_TIMEOUT_OK = 1, +} chargerinterface_status_elcon_cmd_timeout_e; typedef enum { - VCU_STATUS_MOTOR_CONTACTOR_STATE_CLOSED = 1, - VCU_STATUS_MOTOR_CONTACTOR_STATE_OPEN = 0, -} vcu_status_motor_contactor_state_e; + CHARGERINTERFACE_STATUS_ELCON_START_STATE_NOT_OK = 0, + CHARGERINTERFACE_STATUS_ELCON_START_STATE_OK = 1, +} chargerinterface_status_elcon_start_state_e; typedef enum { - VCU_STATUS_MOTOR_PRECHARGE_CONTACTOR_STATE_CLOSED = 1, - VCU_STATUS_MOTOR_PRECHARGE_CONTACTOR_STATE_OPEN = 0, -} vcu_status_motor_precharge_contactor_state_e; + CHARGERINTERFACE_STATUS_ELCON_INPUT_VOL_ERROR_OK = 0, + CHARGERINTERFACE_STATUS_ELCON_INPUT_VOL_ERROR_FAULT = 1, +} chargerinterface_status_elcon_input_vol_error_e; + +typedef enum { + CHARGERINTERFACE_STATUS_ELCON_OVER_TEMPERATURE_OK = 0, + CHARGERINTERFACE_STATUS_ELCON_OVER_TEMPERATURE_FAULT = 1, +} chargerinterface_status_elcon_over_temperature_e; + +typedef enum { + CHARGERINTERFACE_STATUS_ELCON_HW_FAULT_OK = 0, + CHARGERINTERFACE_STATUS_ELCON_HW_FAULT_FAULT = 1, +} chargerinterface_status_elcon_hw_fault_e; + +typedef enum { + VCU_STATUS_VCU_FSM_STATE_INIT = 0, + VCU_STATUS_VCU_FSM_STATE_FORWARD_DRIVE = 1, + VCU_STATUS_VCU_FSM_STATE_NEUTRAL_DRIVE = 2, + VCU_STATUS_VCU_FSM_STATE_REVERSE_DRIVE = 3, + VCU_STATUS_VCU_FSM_STATE_REGEN = 4, + VCU_STATUS_VCU_FSM_STATE_CRUISE_CONTROL = 5, + VCU_STATUS_VCU_FSM_STATE_DISABLED = 6, + VCU_STATUS_VCU_FSM_STATE_VEHICLE_NOT_READY = 7, +} vcu_status_vcu_fsm_state_e; typedef enum { - VCU_STATUS_MOTOR_READY_OK = 1, VCU_STATUS_MOTOR_READY_NOT_OK = 0, + VCU_STATUS_MOTOR_READY_OK = 1, } vcu_status_motor_ready_e; typedef enum { - VCU_STATUS_VCU_DRIVER_INPUT_OK_OK = 1, - VCU_STATUS_VCU_DRIVER_INPUT_OK_NOT_OK = 0, -} vcu_status_vcu_driver_input_ok_e; + VCU_STATUS_MOTOR_PRECHARGE_CONTACTOR_STATE_OPEN = 0, + VCU_STATUS_MOTOR_PRECHARGE_CONTACTOR_STATE_CLOSED = 1, +} vcu_status_motor_precharge_contactor_state_e; + +typedef enum { + VCU_STATUS_MOTOR_CONTACTOR_STATE_OPEN = 0, + VCU_STATUS_MOTOR_CONTACTOR_STATE_CLOSED = 1, +} vcu_status_motor_contactor_state_e; + +typedef enum { + VCU_STATUS_VCU_DRIVER_INPUT_WATCHDOG_NOT_OK = 0, + VCU_STATUS_VCU_DRIVER_INPUT_WATCHDOG_OK = 1, +} vcu_status_vcu_driver_input_watchdog_e; typedef enum { - VCU_STATUS_VCU_PEDALS_OK_OK = 1, - VCU_STATUS_VCU_PEDALS_OK_NOT_OK = 0, -} vcu_status_vcu_pedals_ok_e; + VCU_STATUS_VCU_PEDALS_WATCHDOG_NOT_OK = 0, + VCU_STATUS_VCU_PEDALS_WATCHDOG_OK = 1, +} vcu_status_vcu_pedals_watchdog_e; typedef enum { - VCU_STATUS_VCU_REGEN_OK_OK = 1, - VCU_STATUS_VCU_REGEN_OK_NOT_OK = 0, -} vcu_status_vcu_regen_ok_e; + VCU_STATUS_VCU_BPS_WATCHDOG_NOT_OK = 0, + VCU_STATUS_VCU_BPS_WATCHDOG_OK = 1, +} vcu_status_vcu_bps_watchdog_e; + +typedef enum { + VCU_STATUS_VCU_STEERING_ANGLE_WATCHDOG_NOT_OK = 0, + VCU_STATUS_VCU_STEERING_ANGLE_WATCHDOG_OK = 1, +} vcu_status_vcu_steering_angle_watchdog_e; + +typedef enum { + VCU_STATUS_VCU_BPS_FAULT_DETECTED_OK = 0, + VCU_STATUS_VCU_BPS_FAULT_DETECTED_FAULT = 1, +} vcu_status_vcu_bps_fault_detected_e; + +typedef enum { + VCU_STATUS_VCU_CONTROLS_FAULT_DETECTED_OK = 0, + VCU_STATUS_VCU_CONTROLS_FAULT_DETECTED_FAULT = 1, +} vcu_status_vcu_controls_fault_detected_e; + +typedef enum { + VCU_STATUS_VCU_MTR_FAULT_DETECTED_OK = 0, + VCU_STATUS_VCU_MTR_FAULT_DETECTED_FAULT = 1, +} vcu_status_vcu_mtr_fault_detected_e; + +typedef enum { + VCU_STATUS_VCU_PEDALS_FAULT_DETECTED_OK = 0, + VCU_STATUS_VCU_PEDALS_FAULT_DETECTED_FAULT = 1, +} vcu_status_vcu_pedals_fault_detected_e; + +typedef enum { + VCU_STATUS_VCU_STEERING_FAULT_DETECTED_OK = 0, + VCU_STATUS_VCU_STEERING_FAULT_DETECTED_FAULT = 1, +} vcu_status_vcu_steering_fault_detected_e; + +typedef enum { + VCU_STATUS_VCU_MOTORCOMMANDSOURCE_VCU = 0, + VCU_STATUS_VCU_MOTORCOMMANDSOURCE_TRITIUM_EXTERNAL = 1, +} vcu_status_vcu_motorcommandsource_e; typedef enum { - VCU_STATUS_VCU_REGEN_ACTIVE_ACTIVE = 1, VCU_STATUS_VCU_REGEN_ACTIVE_INACTIVE = 0, + VCU_STATUS_VCU_REGEN_ACTIVE_ACTIVE = 1, } vcu_status_vcu_regen_active_e; typedef enum { - VCU_STATUS_VCU_STEERING_ANGLE_OK_OK = 1, - VCU_STATUS_VCU_STEERING_ANGLE_OK_NOT_OK = 0, -} vcu_status_vcu_steering_angle_ok_e; + VCU_STATUS_VCU_REGEN_OK_NOT_OK = 0, + VCU_STATUS_VCU_REGEN_OK_OK = 1, +} vcu_status_vcu_regen_ok_e; typedef enum { - VCU_STATUS_VCU_FSM_STATE_VEHICLE_NOT_READY = 7, - VCU_STATUS_VCU_FSM_STATE_DISABLED = 6, - VCU_STATUS_VCU_FSM_STATE_CRUISE_CONTROL = 5, - VCU_STATUS_VCU_FSM_STATE_REGEN = 4, - VCU_STATUS_VCU_FSM_STATE_REVERSE_DRIVE = 3, - VCU_STATUS_VCU_FSM_STATE_NEUTRAL_DRIVE = 2, - VCU_STATUS_VCU_FSM_STATE_FORWARD_DRIVE = 1, - VCU_STATUS_VCU_FSM_STATE_INIT = 0, -} vcu_status_vcu_fsm_state_e; + VCU_STATUS_VCU_MTR_PCHG_TIMEOUT_OK = 0, + VCU_STATUS_VCU_MTR_PCHG_TIMEOUT_FAULT = 1, +} vcu_status_vcu_mtr_pchg_timeout_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_PCHG_OK_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_PCHG_OK_TRUE = 1, -} vcu_status_vcu_fsm_in_pchg_ok_e; + VCU_STATUS_VCU_MTR_PCHG_CONT_TIMEOUT_OK = 0, + VCU_STATUS_VCU_MTR_PCHG_CONT_TIMEOUT_FAULT = 1, +} vcu_status_vcu_mtr_pchg_cont_timeout_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_BRAKE_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_BRAKE_TRUE = 1, -} vcu_status_vcu_fsm_in_brake_e; + VCU_STATUS_VCU_MTR_PCHG_CONT_MISMATCH_OK = 0, + VCU_STATUS_VCU_MTR_PCHG_CONT_MISMATCH_FAULT = 1, +} vcu_status_vcu_mtr_pchg_cont_mismatch_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_FORWARD_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_FORWARD_TRUE = 1, -} vcu_status_vcu_fsm_in_forward_e; + VCU_STATUS_VCU_MTR_CONT_MISMATCH_OK = 0, + VCU_STATUS_VCU_MTR_CONT_MISMATCH_FAULT = 1, +} vcu_status_vcu_mtr_cont_mismatch_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_NEUTRAL_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_NEUTRAL_TRUE = 1, -} vcu_status_vcu_fsm_in_neutral_e; + VCU_STATUS_VCU_MTR_CONT_TIMEOUT_OK = 0, + VCU_STATUS_VCU_MTR_CONT_TIMEOUT_FAULT = 1, +} vcu_status_vcu_mtr_cont_timeout_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_REVERSE_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_REVERSE_TRUE = 1, -} vcu_status_vcu_fsm_in_reverse_e; + VCU_STATUS_VCU_PCHG_OV_OK = 0, + VCU_STATUS_VCU_PCHG_OV_FAULT = 1, +} vcu_status_vcu_pchg_ov_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_REGEN_RDY_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_REGEN_RDY_TRUE = 1, -} vcu_status_vcu_fsm_in_regen_rdy_e; + VCU_STATUS_VCU_PCHG_UV_OK = 0, + VCU_STATUS_VCU_PCHG_UV_FAULT = 1, +} vcu_status_vcu_pchg_uv_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_REGEN_ENABLE_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_REGEN_ENABLE_TRUE = 1, -} vcu_status_vcu_fsm_in_regen_enable_e; + VCU_STATUS_VCU_MTR_OV_OK = 0, + VCU_STATUS_VCU_MTR_OV_FAULT = 1, +} vcu_status_vcu_mtr_ov_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_CRUISE_REQ_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_CRUISE_REQ_TRUE = 1, -} vcu_status_vcu_fsm_in_cruise_req_e; + VCU_STATUS_VCU_MTR_UV_OK = 0, + VCU_STATUS_VCU_MTR_UV_FAULT = 1, +} vcu_status_vcu_mtr_uv_e; typedef enum { - VCU_STATUS_VCU_FSM_IN_REGEN_REQ_FALSE = 0, - VCU_STATUS_VCU_FSM_IN_REGEN_REQ_TRUE = 1, -} vcu_status_vcu_fsm_in_regen_req_e; + VCU_STATUS_VCU_OTHER_FAULT_OK = 0, + VCU_STATUS_VCU_OTHER_FAULT_FAULT = 1, +} vcu_status_vcu_other_fault_e; + +typedef enum { + VCU_STATUS_VCU_MTR_DIR_CHANGE_LOCKOUT_INACTIVE = 0, + VCU_STATUS_VCU_MTR_DIR_CHANGE_LOCKOUT_ACTIVE = 1, +} vcu_status_vcu_mtr_dir_change_lockout_e; + +typedef enum { + VCU_STATUS_VCU_TIPPING_WARNING_INACTIVE = 0, + VCU_STATUS_VCU_TIPPING_WARNING_ACTIVE = 1, +} vcu_status_vcu_tipping_warning_e; + +typedef enum { + VCU_STATUS_VCU_WARN_REGEN_NOT_ALLOW_INACTIVE = 0, + VCU_STATUS_VCU_WARN_REGEN_NOT_ALLOW_ACTIVE = 1, +} vcu_status_vcu_warn_regen_not_allow_e; + +typedef enum { + VCU_STATUS_VCU_WARN_REGEN_NOT_EN_INACTIVE = 0, + VCU_STATUS_VCU_WARN_REGEN_NOT_EN_ACTIVE = 1, +} vcu_status_vcu_warn_regen_not_en_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_BRAKE_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_BRAKE_TRUE = 1, +} vcu_status_vcu_fsm_inp_brake_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_PCHG_OK_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_PCHG_OK_TRUE = 1, +} vcu_status_vcu_fsm_inp_pchg_ok_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_CRUISE_REQ_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_CRUISE_REQ_TRUE = 1, +} vcu_status_vcu_fsm_inp_cruise_req_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_REGEN_REQ_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_REGEN_REQ_TRUE = 1, +} vcu_status_vcu_fsm_inp_regen_req_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_REGEN_ENABLE_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_REGEN_ENABLE_TRUE = 1, +} vcu_status_vcu_fsm_inp_regen_enable_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_REGEN_RDY_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_REGEN_RDY_TRUE = 1, +} vcu_status_vcu_fsm_inp_regen_rdy_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_FORWARD_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_FORWARD_TRUE = 1, +} vcu_status_vcu_fsm_inp_forward_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_NEUTRAL_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_NEUTRAL_TRUE = 1, +} vcu_status_vcu_fsm_inp_neutral_e; + +typedef enum { + VCU_STATUS_VCU_FSM_INP_REVERSE_FALSE = 0, + VCU_STATUS_VCU_FSM_INP_REVERSE_TRUE = 1, +} vcu_status_vcu_fsm_inp_reverse_e; typedef enum { - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_LIGHTING_BOARD_FAULT = 4, - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_INVALID_DRIVER_INPUTS = 3, - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BPS_WATCHDOG = 2, - CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BOSCH_LWS_WATCHDOG = 1, CONTROLS_STATUS_CONTROLS_LEADER_FAULT_OK = 0, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BOSCH_LWS_WATCHDOG = 1, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_BPS_WATCHDOG = 2, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_INVALID_DRIVER_INPUTS = 3, + CONTROLS_STATUS_CONTROLS_LEADER_FAULT_LIGHTING_BOARD_FAULT = 4, CONTROLS_STATUS_CONTROLS_LEADER_FAULT_LIGHTING_BOARD_WATCHDOG = 5, } controls_status_controls_leader_fault_e; typedef enum { - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED1_OVERCURRENT = 6, - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED0_OVERCURRENT = 5, - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_ADDR_LED_OVERCURRENT = 4, - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED1_UNDERCURRENT = 3, - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED0_UNDERCURRENT = 2, - CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_ADDR_LED_UNDERCURRENT = 1, CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, CONTROLS_STATUS_LIGHTINGBOARD_FRONT_STATUS_WATCHDOG = 8, } controls_status_lightingboard_front_status_e; typedef enum { - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED1_OVERCURRENT = 6, - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED0_OVERCURRENT = 5, - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_ADDR_LED_OVERCURRENT = 4, - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED1_UNDERCURRENT = 3, - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED0_UNDERCURRENT = 2, - CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_ADDR_LED_UNDERCURRENT = 1, CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, CONTROLS_STATUS_LIGHTINGBOARD_LEFT_STATUS_WATCHDOG = 8, } controls_status_lightingboard_left_status_e; typedef enum { - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED1_OVERCURRENT = 6, - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED0_OVERCURRENT = 5, - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_ADDR_LED_OVERCURRENT = 4, - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED1_UNDERCURRENT = 3, - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED0_UNDERCURRENT = 2, - CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_ADDR_LED_UNDERCURRENT = 1, CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_LIGHT_COMMAND_WATCHDOG = 7, CONTROLS_STATUS_LIGHTINGBOARD_RIGHT_STATUS_WATCHDOG = 8, } controls_status_lightingboard_right_status_e; typedef enum { - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LIGHT_COMMAND_WATCHDOG = 7, - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED1_OVERCURRENT = 6, - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED0_OVERCURRENT = 5, - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_ADDR_LED_OVERCURRENT = 4, - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED1_UNDERCURRENT = 3, - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED0_UNDERCURRENT = 2, - CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_ADDR_LED_UNDERCURRENT = 1, CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_LIGHT_COMMAND_WATCHDOG = 7, CONTROLS_STATUS_LIGHTINGBOARD_REAR_STATUS_WATCHDOG = 8, } controls_status_lightingboard_rear_status_e; typedef enum { - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LIGHT_COMMAND_WATCHDOG = 7, - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED1_OVERCURRENT = 6, - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED0_OVERCURRENT = 5, - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_ADDR_LED_OVERCURRENT = 4, - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED1_UNDERCURRENT = 3, - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED0_UNDERCURRENT = 2, - CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_ADDR_LED_UNDERCURRENT = 1, CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_OK = 0, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_ADDR_LED_UNDERCURRENT = 1, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED0_UNDERCURRENT = 2, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED1_UNDERCURRENT = 3, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_ADDR_LED_OVERCURRENT = 4, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED0_OVERCURRENT = 5, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LED1_OVERCURRENT = 6, + CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_LIGHT_COMMAND_WATCHDOG = 7, CONTROLS_STATUS_LIGHTINGBOARD_CANOPY_STATUS_WATCHDOG = 8, } controls_status_lightingboard_canopy_status_e; typedef enum { - PEDAL_STATUS_ACCELPEDAL_MAIN_FAULT_FAULT = 1, PEDAL_STATUS_ACCELPEDAL_MAIN_FAULT_OK = 0, + PEDAL_STATUS_ACCELPEDAL_MAIN_FAULT_FAULT = 1, } pedal_status_accelpedal_main_fault_e; typedef enum { - PEDAL_STATUS_ACCELPEDAL_REDUNDANT_FAULT_FAULT = 1, PEDAL_STATUS_ACCELPEDAL_REDUNDANT_FAULT_OK = 0, + PEDAL_STATUS_ACCELPEDAL_REDUNDANT_FAULT_FAULT = 1, } pedal_status_accelpedal_redundant_fault_e; typedef enum { - PEDAL_STATUS_BRAKEPEDAL_MAIN_FAULT_FAULT = 1, PEDAL_STATUS_BRAKEPEDAL_MAIN_FAULT_OK = 0, + PEDAL_STATUS_BRAKEPEDAL_MAIN_FAULT_FAULT = 1, } pedal_status_brakepedal_main_fault_e; typedef enum { - PEDAL_STATUS_BRAKEPEDAL_REDUNDANT_FAULT_FAULT = 1, PEDAL_STATUS_BRAKEPEDAL_REDUNDANT_FAULT_OK = 0, + PEDAL_STATUS_BRAKEPEDAL_REDUNDANT_FAULT_FAULT = 1, } pedal_status_brakepedal_redundant_fault_e; typedef enum { - DRIVER_INPUT_STATUS_IGNITION_ARRAY_SELECTED = 1, + PEDAL_STATUS_BRAKE_PRESSURE_1_FAULT_OK = 0, + PEDAL_STATUS_BRAKE_PRESSURE_1_FAULT_FAULT = 1, +} pedal_status_brake_pressure_1_fault_e; + +typedef enum { + PEDAL_STATUS_BRAKE_PRESSURE_2_FAULT_OK = 0, + PEDAL_STATUS_BRAKE_PRESSURE_2_FAULT_FAULT = 1, +} pedal_status_brake_pressure_2_fault_e; + +typedef enum { DRIVER_INPUT_STATUS_IGNITION_ARRAY__ = 0, + DRIVER_INPUT_STATUS_IGNITION_ARRAY_SELECTED = 1, } driver_input_status_ignition_array_e; typedef enum { - DRIVER_INPUT_STATUS_IGNITION_MOTOR_SELECTED = 1, DRIVER_INPUT_STATUS_IGNITION_MOTOR__ = 0, + DRIVER_INPUT_STATUS_IGNITION_MOTOR_SELECTED = 1, } driver_input_status_ignition_motor_e; typedef enum { - DRIVER_INPUT_STATUS_IGNITION_OFF_SELECTED = 1, DRIVER_INPUT_STATUS_IGNITION_OFF__ = 0, + DRIVER_INPUT_STATUS_IGNITION_OFF_SELECTED = 1, } driver_input_status_ignition_off_e; typedef enum { - DRIVER_INPUT_STATUS_CRUISE_ENABLE_ENABLED = 1, DRIVER_INPUT_STATUS_CRUISE_ENABLE_DISABLED = 0, + DRIVER_INPUT_STATUS_CRUISE_ENABLE_ENABLED = 1, } driver_input_status_cruise_enable_e; typedef enum { - DRIVER_INPUT_STATUS_CRUISE_SET_PRESSED = 1, DRIVER_INPUT_STATUS_CRUISE_SET__ = 0, + DRIVER_INPUT_STATUS_CRUISE_SET_PRESSED = 1, } driver_input_status_cruise_set_e; typedef enum { - DRIVER_INPUT_STATUS_GEAR_FORWARD_SELECTED = 1, DRIVER_INPUT_STATUS_GEAR_FORWARD__ = 0, + DRIVER_INPUT_STATUS_GEAR_FORWARD_SELECTED = 1, } driver_input_status_gear_forward_e; typedef enum { - DRIVER_INPUT_STATUS_GEAR_NEUTRAL_SELECTED = 1, DRIVER_INPUT_STATUS_GEAR_NEUTRAL__ = 0, + DRIVER_INPUT_STATUS_GEAR_NEUTRAL_SELECTED = 1, } driver_input_status_gear_neutral_e; typedef enum { - DRIVER_INPUT_STATUS_GEAR_REVERSE_SELECTED = 1, DRIVER_INPUT_STATUS_GEAR_REVERSE__ = 0, + DRIVER_INPUT_STATUS_GEAR_REVERSE_SELECTED = 1, } driver_input_status_gear_reverse_e; typedef enum { - DRIVER_INPUT_STATUS_HAZARD_PRESSED_ON = 1, DRIVER_INPUT_STATUS_HAZARD_PRESSED_OFF = 0, + DRIVER_INPUT_STATUS_HAZARD_PRESSED_ON = 1, } driver_input_status_hazard_pressed_e; typedef enum { - DRIVER_INPUT_STATUS_HORN_PRESSED_ON = 1, DRIVER_INPUT_STATUS_HORN_PRESSED_OFF = 0, + DRIVER_INPUT_STATUS_HORN_PRESSED_ON = 1, } driver_input_status_horn_pressed_e; typedef enum { - DRIVER_INPUT_STATUS_BLINKER_LEFT_SELECTED = 1, DRIVER_INPUT_STATUS_BLINKER_LEFT__ = 0, + DRIVER_INPUT_STATUS_BLINKER_LEFT_SELECTED = 1, } driver_input_status_blinker_left_e; typedef enum { - DRIVER_INPUT_STATUS_BLINKER_RIGHT_SELECTED = 1, DRIVER_INPUT_STATUS_BLINKER_RIGHT__ = 0, + DRIVER_INPUT_STATUS_BLINKER_RIGHT_SELECTED = 1, } driver_input_status_blinker_right_e; typedef enum { - DRIVER_INPUT_STATUS_PUSHTOTALK_PRESSED_PRESSED = 1, DRIVER_INPUT_STATUS_PUSHTOTALK_PRESSED__ = 0, + DRIVER_INPUT_STATUS_PUSHTOTALK_PRESSED_PRESSED = 1, } driver_input_status_pushtotalk_pressed_e; typedef enum { - DRIVER_INPUT_STATUS_REGEN_ACTIVATE_PRESSED = 1, DRIVER_INPUT_STATUS_REGEN_ACTIVATE__ = 0, + DRIVER_INPUT_STATUS_REGEN_ACTIVATE_PRESSED = 1, } driver_input_status_regen_activate_e; typedef enum { - DRIVER_INPUT_STATUS_REGEN_ENABLE_ENABLED = 1, DRIVER_INPUT_STATUS_REGEN_ENABLE_DISABLED = 0, + DRIVER_INPUT_STATUS_REGEN_ENABLE_ENABLED = 1, } driver_input_status_regen_enable_e; typedef enum { - MPPT_A_STATUS_MPPT_MODE_FAULT = 6, - MPPT_A_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, - MPPT_A_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, - MPPT_A_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, - MPPT_A_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, - MPPT_A_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, MPPT_A_STATUS_MPPT_MODE_CONSTANT_INPUT_VOLTAGE = 0, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, + MPPT_A_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, + MPPT_A_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, + MPPT_A_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, + MPPT_A_STATUS_MPPT_MODE_FAULT = 6, } mppt_a_status_mppt_mode_e; typedef enum { - MPPT_A_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, - MPPT_A_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, - MPPT_A_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, - MPPT_A_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, - MPPT_A_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, - MPPT_A_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, - MPPT_A_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, - MPPT_A_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, MPPT_A_STATUS_MPPT_FAULT_OK = 0, + MPPT_A_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, + MPPT_A_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, + MPPT_A_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, + MPPT_A_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, + MPPT_A_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, + MPPT_A_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, + MPPT_A_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, + MPPT_A_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, } mppt_a_status_mppt_fault_e; typedef enum { - MPPT_A_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, - MPPT_A_STATUS_MPPT_ENABLED_ENABLED = 1, MPPT_A_STATUS_MPPT_ENABLED_DISABLED = 0, + MPPT_A_STATUS_MPPT_ENABLED_ENABLED = 1, + MPPT_A_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, } mppt_a_status_mppt_enabled_e; typedef enum { - MPPT_A_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, - MPPT_A_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, MPPT_A_SETMODE_MPPT_SET_ENABLE_DISABLED = 0, + MPPT_A_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, + MPPT_A_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, } mppt_a_setmode_mppt_set_enable_e; typedef enum { - MPPT_B_STATUS_MPPT_MODE_FAULT = 6, - MPPT_B_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, - MPPT_B_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, - MPPT_B_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, - MPPT_B_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, - MPPT_B_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, MPPT_B_STATUS_MPPT_MODE_CONSTANT_INPUT_VOLTAGE = 0, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, + MPPT_B_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, + MPPT_B_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, + MPPT_B_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, + MPPT_B_STATUS_MPPT_MODE_FAULT = 6, } mppt_b_status_mppt_mode_e; typedef enum { - MPPT_B_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, - MPPT_B_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, - MPPT_B_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, - MPPT_B_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, - MPPT_B_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, - MPPT_B_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, - MPPT_B_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, - MPPT_B_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, MPPT_B_STATUS_MPPT_FAULT_OK = 0, + MPPT_B_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, + MPPT_B_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, + MPPT_B_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, + MPPT_B_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, + MPPT_B_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, + MPPT_B_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, + MPPT_B_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, + MPPT_B_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, } mppt_b_status_mppt_fault_e; typedef enum { - MPPT_B_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, - MPPT_B_STATUS_MPPT_ENABLED_ENABLED = 1, MPPT_B_STATUS_MPPT_ENABLED_DISABLED = 0, + MPPT_B_STATUS_MPPT_ENABLED_ENABLED = 1, + MPPT_B_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, } mppt_b_status_mppt_enabled_e; typedef enum { - MPPT_B_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, - MPPT_B_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, MPPT_B_SETMODE_MPPT_SET_ENABLE_DISABLED = 0, + MPPT_B_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, + MPPT_B_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, } mppt_b_setmode_mppt_set_enable_e; typedef enum { - MPPT_C_STATUS_MPPT_MODE_FAULT = 6, - MPPT_C_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, - MPPT_C_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, - MPPT_C_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, - MPPT_C_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, - MPPT_C_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, MPPT_C_STATUS_MPPT_MODE_CONSTANT_INPUT_VOLTAGE = 0, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_INPUT_CURRENT = 1, + MPPT_C_STATUS_MPPT_MODE_MINIMUM_INPUT_CURRENT = 2, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_OUTPUT_VOLTAGE = 3, + MPPT_C_STATUS_MPPT_MODE_CONSTANT_OUTPUT_CURRENT = 4, + MPPT_C_STATUS_MPPT_MODE_TEMPERATURE_DE_RATING = 5, + MPPT_C_STATUS_MPPT_MODE_FAULT = 6, } mppt_c_status_mppt_mode_e; typedef enum { - MPPT_C_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, - MPPT_C_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, - MPPT_C_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, - MPPT_C_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, - MPPT_C_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, - MPPT_C_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, - MPPT_C_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, - MPPT_C_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, MPPT_C_STATUS_MPPT_FAULT_OK = 0, + MPPT_C_STATUS_MPPT_FAULT_CONFIGURATION_ERROR = 1, + MPPT_C_STATUS_MPPT_FAULT_INPUT_OVER_VOLTAGE = 2, + MPPT_C_STATUS_MPPT_FAULT_OUTPUT_OVER_VOLTAGE = 3, + MPPT_C_STATUS_MPPT_FAULT_OUTPUT_OVER_CURRENT = 4, + MPPT_C_STATUS_MPPT_FAULT_INPUT_OVER_CURRENT = 5, + MPPT_C_STATUS_MPPT_FAULT_INPUT_UNDER_CURRENT = 6, + MPPT_C_STATUS_MPPT_FAULT_PHASE_OVER_CURRENT = 7, + MPPT_C_STATUS_MPPT_FAULT_UNKNOWN_FAULT = 8, } mppt_c_status_mppt_fault_e; typedef enum { - MPPT_C_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, - MPPT_C_STATUS_MPPT_ENABLED_ENABLED = 1, MPPT_C_STATUS_MPPT_ENABLED_DISABLED = 0, + MPPT_C_STATUS_MPPT_ENABLED_ENABLED = 1, + MPPT_C_STATUS_MPPT_ENABLED_ENABLED_CONSTANT_VOLTAGE = 2, } mppt_c_status_mppt_enabled_e; typedef enum { - MPPT_C_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, - MPPT_C_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, MPPT_C_SETMODE_MPPT_SET_ENABLE_DISABLED = 0, + MPPT_C_SETMODE_MPPT_SET_ENABLE_ENABLED = 1, + MPPT_C_SETMODE_MPPT_SET_ENABLE_ENABLED_CONSTANT_VOLTAGE = 2, } mppt_c_setmode_mppt_set_enable_e; typedef enum { - SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_UNKNOWN_FAULT = 5, - SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_CURRENT_CHARGE_ = 4, - SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_CURRENT_DISCHARGE_ = 3, - SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_VOLTAGE = 2, - SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_UNDER_VOLTAGE = 1, SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OK = 0, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_UNDER_VOLTAGE = 1, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_VOLTAGE = 2, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_CURRENT_DISCHARGE_ = 3, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_OVER_CURRENT_CHARGE_ = 4, + SUPP_BATTERY_STATUS_SUPPLEMENTAL_BATTERY_FAULT_UNKNOWN_FAULT = 5, } supp_battery_status_supplemental_battery_fault_e; typedef enum { - SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_FAULT = 3, - SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_CHARGING_ = 2, - SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_CHARGE_COMPLETE = 1, - SUPP_BATTERY_CHARGER_STATUS_SUPPCHARGER_STATUS_CHARGE_DISABLED = 0, -} supp_battery_charger_status_suppcharger_status_e; + SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_CHARGE_DISABLED = 0, + SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_CHARGE_COMPLETE = 1, + SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_CHARGING_ = 2, + SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_FAULT = 3, +} supp_charging_status_supplemental_charging_status_e; typedef enum { - PDU_STATUS_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_PUMP = 12, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_MPPTS = 9, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_BATTERY = 8, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_PEDALS = 5, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_HORN = 2, - PDU_STATUS_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, PDU_STATUS_ARR_HSS_CHANNEL_IDX_VCU = 0, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_HORN = 2, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PEDALS = 5, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_BATTERY = 8, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_MPPTS = 9, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PUMP = 12, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, + PDU_STATUS_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, } pdu_status_arr_hss_channel_idx_e; typedef enum { - PDU_STATUS_ARR_HSS_FAULT_FAULT = 1, PDU_STATUS_ARR_HSS_FAULT_OK = 0, + PDU_STATUS_ARR_HSS_FAULT_FAULT = 1, } pdu_status_arr_hss_fault_e; typedef enum { - PDU_STATUS_ARR_HSS_ENABLED_ENABLED = 1, PDU_STATUS_ARR_HSS_ENABLED_DISABLED = 0, + PDU_STATUS_ARR_HSS_ENABLED_ENABLED = 1, } pdu_status_arr_hss_enabled_e; typedef enum { - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PUMP = 12, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_MPPTS = 9, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_BATTERY = 8, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PEDALS = 5, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_HORN = 2, - PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_VCU = 0, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_HORN = 2, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PEDALS = 5, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_BATTERY = 8, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_MPPTS = 9, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PUMP = 12, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, + PDU_SET_SWITCH_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, } pdu_set_switch_arr_hss_channel_idx_e; typedef enum { - PDU_SET_SWITCH_ARR_HSS_SETSWITCH_TOGGLE_OFF = 2, - PDU_SET_SWITCH_ARR_HSS_SETSWITCH_TOGGLE_ON = 1, PDU_SET_SWITCH_ARR_HSS_SETSWITCH_DO_NOTHING = 0, + PDU_SET_SWITCH_ARR_HSS_SETSWITCH_TOGGLE_ON = 1, + PDU_SET_SWITCH_ARR_HSS_SETSWITCH_TOGGLE_OFF = 2, } pdu_set_switch_arr_hss_setswitch_e; typedef enum { - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PUMP = 12, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_MPPTS = 9, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_BATTERY = 8, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PEDALS = 5, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_HORN = 2, - PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_VCU = 0, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_DASHBOARD = 1, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_HORN = 2, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_LIGHTS = 3, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PI_DISPLAY = 4, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PEDALS = 5, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_CAMERAS = 6, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_0 = 7, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_BATTERY = 8, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_MPPTS = 9, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_MOTOR_CONTROLLER = 10, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_TELEMETRY_DATA_ACQ = 11, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PUMP = 12, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_1 = 13, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_UNASSIGNED_2 = 14, + PDU_SET_CURRENT_LIMIT_ARR_HSS_CHANNEL_IDX_PDE_FANS = 15, } pdu_set_current_limit_arr_hss_channel_idx_e; typedef enum { - PUMP_STATUS_PUMP_FAULT_FAULT = 1, PUMP_STATUS_PUMP_FAULT_OK = 0, + PUMP_STATUS_PUMP_FAULT_FAULT = 1, } pump_status_pump_fault_e; typedef enum { - LV_CARRIER_STATUS_LTC4421_HVDCDC_SELECTED_SELECTED = 1, LV_CARRIER_STATUS_LTC4421_HVDCDC_SELECTED__ = 0, + LV_CARRIER_STATUS_LTC4421_HVDCDC_SELECTED_SELECTED = 1, } lv_carrier_status_ltc4421_hvdcdc_selected_e; typedef enum { - LV_CARRIER_STATUS_LTC4421_HVDCDC_FAULT_FAULT = 1, LV_CARRIER_STATUS_LTC4421_HVDCDC_FAULT_OK = 0, + LV_CARRIER_STATUS_LTC4421_HVDCDC_FAULT_FAULT = 1, } lv_carrier_status_ltc4421_hvdcdc_fault_e; typedef enum { - LV_CARRIER_STATUS_LTC4421_HVDCDC_VALID_OK = 1, LV_CARRIER_STATUS_LTC4421_HVDCDC_VALID_NOT_OK = 0, + LV_CARRIER_STATUS_LTC4421_HVDCDC_VALID_OK = 1, } lv_carrier_status_ltc4421_hvdcdc_valid_e; typedef enum { - LV_CARRIER_STATUS_LTC4421_SUPPBATT_SELECTED_SELECTED = 1, LV_CARRIER_STATUS_LTC4421_SUPPBATT_SELECTED__ = 0, + LV_CARRIER_STATUS_LTC4421_SUPPBATT_SELECTED_SELECTED = 1, } lv_carrier_status_ltc4421_suppbatt_selected_e; typedef enum { - LV_CARRIER_STATUS_LTC4421_SUPPBATT_FAULT_FAULT = 1, LV_CARRIER_STATUS_LTC4421_SUPPBATT_FAULT_OK = 0, + LV_CARRIER_STATUS_LTC4421_SUPPBATT_FAULT_FAULT = 1, } lv_carrier_status_ltc4421_suppbatt_fault_e; typedef enum { - LV_CARRIER_STATUS_LTC4421_SUPPBATT_VALID_OK = 1, LV_CARRIER_STATUS_LTC4421_SUPPBATT_VALID_NOT_OK = 0, + LV_CARRIER_STATUS_LTC4421_SUPPBATT_VALID_OK = 1, } lv_carrier_status_ltc4421_suppbatt_valid_e; typedef enum { - LV_CARRIER_STATUS_LV_EN_SUPPLEMENTALBATTERY_ENABLED = 1, LV_CARRIER_STATUS_LV_EN_SUPPLEMENTALBATTERY_DISABLED = 0, + LV_CARRIER_STATUS_LV_EN_SUPPLEMENTALBATTERY_ENABLED = 1, } lv_carrier_status_lv_en_supplementalbattery_e; typedef enum { - LV_CARRIER_STATUS_LV_EN_POWERSUPPLY_ENABLED = 1, LV_CARRIER_STATUS_LV_EN_POWERSUPPLY_DISABLED = 0, + LV_CARRIER_STATUS_LV_EN_POWERSUPPLY_ENABLED = 1, } lv_carrier_status_lv_en_powersupply_e; typedef enum { - BRAKE_PRESSURE_1_BRAKE_PRESSURE_FAULT_FAULT = 1, - BRAKE_PRESSURE_1_BRAKE_PRESSURE_FAULT_OK = 0, -} brake_pressure_1_brake_pressure_fault_e; - -typedef enum { - BRAKE_PRESSURE_2_BRAKE_PRESSURE_FAULT_FAULT = 1, - BRAKE_PRESSURE_2_BRAKE_PRESSURE_FAULT_OK = 0, -} brake_pressure_2_brake_pressure_fault_e; - -typedef enum { - DISPLAY_STATUS_CAMERA_STATUS_BACKUP_OK = 1, DISPLAY_STATUS_CAMERA_STATUS_BACKUP_NOT_OK = 0, + DISPLAY_STATUS_CAMERA_STATUS_BACKUP_OK = 1, } display_status_camera_status_backup_e; typedef enum { - DISPLAY_STATUS_CAMERA_STATUS_LEFT_OK = 1, DISPLAY_STATUS_CAMERA_STATUS_LEFT_NOT_OK = 0, + DISPLAY_STATUS_CAMERA_STATUS_LEFT_OK = 1, } display_status_camera_status_left_e; typedef enum { - DISPLAY_STATUS_CAMERA_STATUS_RIGHT_OK = 1, DISPLAY_STATUS_CAMERA_STATUS_RIGHT_NOT_OK = 0, + DISPLAY_STATUS_CAMERA_STATUS_RIGHT_OK = 1, } display_status_camera_status_right_e; /* ================= Message Structs ================= */ @@ -767,7 +891,7 @@ typedef struct { uint32_t Main_Battery_Voltage; int16_t Main_Battery_Avg_Temperature; uint8_t BPS_Segment0_Status; - int8_t BPS_Segment1_Status; + uint8_t BPS_Segment1_Status; uint8_t BPS_Segment2_Status; uint8_t BPS_Segment3_Status; uint8_t BPS_Segment4_Status; @@ -778,7 +902,6 @@ typedef struct { typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Tap_Msg_WDog; uint16_t BPS_Voltage_Tap_Data; uint8_t BPS_Voltage_Tap_Fault; uint16_t BPS_Voltage_Tap_Age; @@ -786,39 +909,63 @@ typedef struct { typedef struct { uint8_t BPS_Tap_idx; - uint8_t BPS_Temperature_Tap_Fault; int32_t BPS_Temperature_Tap_Data; + uint8_t BPS_Temperature_Tap_Fault; uint16_t BPS_Temperature_Tap_Age; - uint8_t BPS_Temperature_FrameID; + uint8_t FrameID_BPS_Temperature; } bps_temperature_aggregate_arr_t; typedef struct { - uint8_t BPS_Tap_idx; - uint8_t BPS_Tap_Msg_WDog; - uint16_t BPS_Temperature_Tap_RawV; - uint8_t BPS_Temperature_FrameID; -} bps_temp_rawv_aggregate_arr_t; + uint16_t Elcon_VOL_OUT; + uint16_t Elcon_CUR_OUT; + uint8_t Elcon_Watchdog; + uint8_t Elcon_CMD_TIMEOUT; + uint8_t Elcon_START_STATE; + uint8_t Elcon_INPUT_VOL_ERROR; + uint8_t Elcon_OVER_TEMPERATURE; + uint8_t Elcon_HW_FAULT; +} chargerinterface_status_t; typedef struct { - uint8_t VCU_Fault; - uint8_t Motor_Contactor_State; - uint8_t Motor_Precharge_Contactor_State; + uint8_t VCU_FSM_State; uint8_t Motor_Ready; - uint8_t VCU_Driver_Input_OK; - uint8_t VCU_Pedals_OK; - uint8_t VCU_Regen_OK; + uint8_t Motor_Precharge_Contactor_State; + uint8_t Motor_Contactor_State; + uint8_t VCU_Driver_Input_Watchdog; + uint8_t VCU_Pedals_Watchdog; + uint8_t VCU_BPS_Watchdog; + uint8_t VCU_Steering_Angle_Watchdog; + uint8_t VCU_BPS_FAULT_DETECTED; + uint8_t VCU_CONTROLS_FAULT_DETECTED; + uint8_t VCU_MTR_FAULT_DETECTED; + uint8_t VCU_PEDALS_FAULT_DETECTED; + uint8_t VCU_STEERING_FAULT_DETECTED; + uint8_t VCU_MotorCommandSource; uint8_t VCU_Regen_Active; - uint8_t VCU_Steering_Angle_OK; - uint8_t VCU_FSM_State; - uint8_t VCU_FSM_IN_PCHG_OK; - uint8_t VCU_FSM_IN_BRAKE; - uint8_t VCU_FSM_IN_FORWARD; - uint8_t VCU_FSM_IN_NEUTRAL; - uint8_t VCU_FSM_IN_REVERSE; - uint8_t VCU_FSM_IN_REGEN_RDY; - uint8_t VCU_FSM_IN_REGEN_ENABLE; - uint8_t VCU_FSM_IN_CRUISE_REQ; - uint8_t VCU_FSM_IN_REGEN_REQ; + uint8_t VCU_Regen_OK; + uint8_t VCU_MTR_PCHG_TIMEOUT; + uint8_t VCU_MTR_PCHG_CONT_TIMEOUT; + uint8_t VCU_MTR_PCHG_CONT_MISMATCH; + uint8_t VCU_MTR_CONT_MISMATCH; + uint8_t VCU_MTR_CONT_TIMEOUT; + uint8_t VCU_PCHG_OV; + uint8_t VCU_PCHG_UV; + uint8_t VCU_MTR_OV; + uint8_t VCU_MTR_UV; + uint8_t VCU_OTHER_FAULT; + uint8_t VCU_MTR_DIR_CHANGE_LOCKOUT; + uint8_t VCU_TIPPING_WARNING; + uint8_t VCU_WARN_REGEN_NOT_ALLOW; + uint8_t VCU_WARN_REGEN_NOT_EN; + uint8_t VCU_FSM_INP_BRAKE; + uint8_t VCU_FSM_INP_PCHG_OK; + uint8_t VCU_FSM_INP_CRUISE_REQ; + uint8_t VCU_FSM_INP_REGEN_REQ; + uint8_t VCU_FSM_INP_REGEN_ENABLE; + uint8_t VCU_FSM_INP_REGEN_RDY; + uint8_t VCU_FSM_INP_FORWARD; + uint8_t VCU_FSM_INP_NEUTRAL; + uint8_t VCU_FSM_INP_REVERSE; } vcu_status_t; typedef struct { @@ -849,21 +996,11 @@ typedef struct { uint8_t AccelPedal_Redundant_Fault; uint8_t BrakePedal_Main_Fault; uint8_t BrakePedal_Redundant_Fault; - uint8_t Pedals_FrameID; + uint8_t Brake_Pressure_1_Fault; + uint8_t Brake_Pressure_2_Fault; + uint8_t FrameID_Pedals; } pedal_status_t; -typedef struct { - uint16_t AccelPedal_Main_RawV; - uint16_t AccelPedal_Redundant_RawV; - uint8_t Pedals_FrameID; -} pedal_accel_rawv_t; - -typedef struct { - uint16_t BrakePedal_Main_RawV; - uint16_t BrakePedal_Redundant_RawV; - uint8_t Pedals_FrameID; -} pedal_brake_rawv_t; - typedef struct { uint8_t Ignition_Array; uint8_t Ignition_Motor; @@ -1003,13 +1140,15 @@ typedef struct { uint8_t Supplemental_Battery_Fault; uint16_t Supplemental_Battery_Voltage; int16_t Supplemental_Battery_Current; + uint8_t FrameID_Supp; } supp_battery_status_t; typedef struct { - uint8_t SuppCharger_Status; - uint16_t Supplemental_DCDC_Voltage; - int16_t Supplemental_DCDC_Current; -} supp_battery_charger_status_t; + uint8_t Supplemental_Charging_Status; + uint16_t Supplemental_Vicor_Voltage; + int16_t Supplemental_Vicor_Current; + uint8_t FrameID_Supp_Vicor; +} supp_charging_status_t; typedef struct { uint8_t HSS_Channel_idx; @@ -1062,15 +1201,13 @@ typedef struct { typedef struct { uint16_t Brake_Pressure; uint16_t Brake_Pressure_RawV; - uint8_t Brake_Pressure_Fault; - uint8_t Pedals_FrameID; + uint8_t FrameID_Pedals; } brake_pressure_1_t; typedef struct { uint16_t Brake_Pressure; uint16_t Brake_Pressure_RawV; - uint8_t Brake_Pressure_Fault; - uint8_t Pedals_FrameID; + uint8_t FrameID_Pedals; } brake_pressure_2_t; typedef struct { @@ -1083,3 +1220,33 @@ typedef struct { typedef struct { } telemetry_status_t; +typedef struct { + uint8_t BPS_Tap_idx; + uint16_t BPS_Temperature_Tap_RawV; + uint8_t FrameID_BPS_Temperature; +} bps_temp_rawv_aggregate_arr_t; + +typedef struct { + uint16_t Supp_Battery_Voltage_RawV; + int16_t Supp_Battery_Current_RawV; + uint8_t FrameID_Supp; +} supp_measurements_rawv_t; + +typedef struct { + uint16_t Supp_Vicor_Voltage_RawV; + int16_t Supp_Vicor_Current_RawV; + uint8_t FrameID_Supp_Vicor; +} supp_vicor_measurements_rawv_t; + +typedef struct { + uint16_t BrakePedal_Main_RawV; + uint16_t BrakePedal_Redundant_RawV; + uint8_t FrameID_Pedals; +} pedal_brake_rawv_t; + +typedef struct { + uint16_t AccelPedal_Main_RawV; + uint16_t AccelPedal_Redundant_RawV; + uint8_t FrameID_Pedals; +} pedal_accel_rawv_t; + diff --git a/Firmware/config/Inc/MotorCAN_can_msgs.h b/Firmware/config/Inc/MotorCAN_can_msgs.h index fb03a22d..f58ee493 100644 --- a/Firmware/config/Inc/MotorCAN_can_msgs.h +++ b/Firmware/config/Inc/MotorCAN_can_msgs.h @@ -21,6 +21,7 @@ #define CAN_ID_MC_DSPBOARDTEMPMEASUREMENT 0x42C #define CAN_ID_MC_ODOMETERBUSAHMEASUREMENT 0x42E #define CAN_ID_MC_SLIPSPEEDMEASUREMENT 0x437 +#define CAN_ID_SET_MOTOR_CMD_SRC 0x7A1 /* ================= CAN Length Macros ================= */ @@ -41,100 +42,106 @@ #define CAN_DLC_MC_DSPBOARDTEMPMEASUREMENT 8 #define CAN_DLC_MC_ODOMETERBUSAHMEASUREMENT 8 #define CAN_DLC_MC_SLIPSPEEDMEASUREMENT 8 +#define CAN_DLC_SET_MOTOR_CMD_SRC 1 /* ================= Value Table Enums ================= */ typedef enum { - MC_STATUS_MC_LIMIT_OUTPUTVOLTAGEPWM_LIMIT = 1, MC_STATUS_MC_LIMIT_OUTPUTVOLTAGEPWM_OK = 0, + MC_STATUS_MC_LIMIT_OUTPUTVOLTAGEPWM_LIMIT = 1, } mc_status_mc_limit_outputvoltagepwm_e; typedef enum { - MC_STATUS_MC_LIMIT_MOTORCURRENT_LIMIT = 1, MC_STATUS_MC_LIMIT_MOTORCURRENT_OK = 0, + MC_STATUS_MC_LIMIT_MOTORCURRENT_LIMIT = 1, } mc_status_mc_limit_motorcurrent_e; typedef enum { - MC_STATUS_MC_LIMIT_VELOCITY_LIMIT = 1, MC_STATUS_MC_LIMIT_VELOCITY_OK = 0, + MC_STATUS_MC_LIMIT_VELOCITY_LIMIT = 1, } mc_status_mc_limit_velocity_e; typedef enum { - MC_STATUS_MC_LIMIT_BUSCURRENT_LIMIT = 1, MC_STATUS_MC_LIMIT_BUSCURRENT_OK = 0, + MC_STATUS_MC_LIMIT_BUSCURRENT_LIMIT = 1, } mc_status_mc_limit_buscurrent_e; typedef enum { - MC_STATUS_MC_LIMIT_BUSVOLTAGEUPPER_LIMIT = 1, MC_STATUS_MC_LIMIT_BUSVOLTAGEUPPER_OK = 0, + MC_STATUS_MC_LIMIT_BUSVOLTAGEUPPER_LIMIT = 1, } mc_status_mc_limit_busvoltageupper_e; typedef enum { - MC_STATUS_MC_LIMIT_BUSVOLTAGELOWER_LIMIT = 1, MC_STATUS_MC_LIMIT_BUSVOLTAGELOWER_OK = 0, + MC_STATUS_MC_LIMIT_BUSVOLTAGELOWER_LIMIT = 1, } mc_status_mc_limit_busvoltagelower_e; typedef enum { - MC_STATUS_MC_LIMIT_MOTORTEMP_LIMIT = 1, MC_STATUS_MC_LIMIT_MOTORTEMP_OK = 0, + MC_STATUS_MC_LIMIT_MOTORTEMP_LIMIT = 1, } mc_status_mc_limit_motortemp_e; typedef enum { - MC_STATUS_MC_LIMIT_RESERVED_LIMIT = 1, MC_STATUS_MC_LIMIT_RESERVED_OK = 0, + MC_STATUS_MC_LIMIT_RESERVED_LIMIT = 1, } mc_status_mc_limit_reserved_e; typedef enum { - MC_STATUS_MC_FAULT_HARDWAREOVERCURRENT_FAULT = 1, MC_STATUS_MC_FAULT_HARDWAREOVERCURRENT_OK = 0, + MC_STATUS_MC_FAULT_HARDWAREOVERCURRENT_FAULT = 1, } mc_status_mc_fault_hardwareovercurrent_e; typedef enum { - MC_STATUS_MC_FAULT_SOFTWAREOVERCURRENT_FAULT = 1, MC_STATUS_MC_FAULT_SOFTWAREOVERCURRENT_OK = 0, + MC_STATUS_MC_FAULT_SOFTWAREOVERCURRENT_FAULT = 1, } mc_status_mc_fault_softwareovercurrent_e; typedef enum { - MC_STATUS_MC_FAULT_DCBUSOVERVOLTAGE_FAULT = 1, MC_STATUS_MC_FAULT_DCBUSOVERVOLTAGE_OK = 0, + MC_STATUS_MC_FAULT_DCBUSOVERVOLTAGE_FAULT = 1, } mc_status_mc_fault_dcbusovervoltage_e; typedef enum { - MC_STATUS_MC_FAULT_BADMOTORPOSITIONHALLSEQ_FAULT = 1, MC_STATUS_MC_FAULT_BADMOTORPOSITIONHALLSEQ_OK = 0, + MC_STATUS_MC_FAULT_BADMOTORPOSITIONHALLSEQ_FAULT = 1, } mc_status_mc_fault_badmotorpositionhallseq_e; typedef enum { - MC_STATUS_MC_FAULT_WATCHDOGCAUSEDLASTRESET_FAULT = 1, MC_STATUS_MC_FAULT_WATCHDOGCAUSEDLASTRESET_OK = 0, + MC_STATUS_MC_FAULT_WATCHDOGCAUSEDLASTRESET_FAULT = 1, } mc_status_mc_fault_watchdogcausedlastreset_e; typedef enum { - MC_STATUS_MC_FAULT_CONFIGREAD_FAULT = 1, MC_STATUS_MC_FAULT_CONFIGREAD_OK = 0, + MC_STATUS_MC_FAULT_CONFIGREAD_FAULT = 1, } mc_status_mc_fault_configread_e; typedef enum { - MC_STATUS_MC_FAULT_15VRAILUNDERVOLTAGE_FAULT = 1, MC_STATUS_MC_FAULT_15VRAILUNDERVOLTAGE_OK = 0, + MC_STATUS_MC_FAULT_15VRAILUNDERVOLTAGE_FAULT = 1, } mc_status_mc_fault_15vrailundervoltage_e; typedef enum { - MC_STATUS_MC_FAULT_DESATURATIONFAULT_FAULT = 1, MC_STATUS_MC_FAULT_DESATURATIONFAULT_OK = 0, + MC_STATUS_MC_FAULT_DESATURATIONFAULT_FAULT = 1, } mc_status_mc_fault_desaturationfault_e; typedef enum { - MC_STATUS_MC_FAULT_MOTOROVERSPEED_FAULT = 1, MC_STATUS_MC_FAULT_MOTOROVERSPEED_OK = 0, + MC_STATUS_MC_FAULT_MOTOROVERSPEED_FAULT = 1, } mc_status_mc_fault_motoroverspeed_e; typedef enum { - MC_STATUS_MC_FAULT_RESERVED_FAULT = 1, MC_STATUS_MC_FAULT_RESERVED_OK = 0, + MC_STATUS_MC_FAULT_RESERVED_FAULT = 1, } mc_status_mc_fault_reserved_e; +typedef enum { + SET_MOTOR_CMD_SRC_MOTOR_COMMAND_SOURCE_VCU = 0, + SET_MOTOR_CMD_SRC_MOTOR_COMMAND_SOURCE_TRITIUM_EXTERNAL = 1, +} set_motor_cmd_src_motor_command_source_e; + /* ================= Message Structs ================= */ typedef struct { @@ -236,3 +243,7 @@ typedef struct { float MC_SlipSpeed; } mc_slipspeedmeasurement_t; +typedef struct { + uint8_t Motor_Command_Source; +} set_motor_cmd_src_t; + diff --git a/Firmware/config/Inc/SteeringCAN_can_msgs.h b/Firmware/config/Inc/SteeringCAN_can_msgs.h index 9788e492..60d4c594 100644 --- a/Firmware/config/Inc/SteeringCAN_can_msgs.h +++ b/Firmware/config/Inc/SteeringCAN_can_msgs.h @@ -16,22 +16,22 @@ /* ================= Value Table Enums ================= */ typedef enum { - LWS_STANDARD_LWS_FAULT_INTERNAL_FAULT = 1, LWS_STANDARD_LWS_FAULT_OK = 0, + LWS_STANDARD_LWS_FAULT_INTERNAL_FAULT = 1, } lws_standard_lws_fault_e; typedef enum { - LWS_STANDARD_LWS_CALIBRATIONSTAUS_SENSOR_CALIBRATED = 1, LWS_STANDARD_LWS_CALIBRATIONSTAUS_SENSOR_NOT_CALIBRATED = 0, + LWS_STANDARD_LWS_CALIBRATIONSTAUS_SENSOR_CALIBRATED = 1, } lws_standard_lws_calibrationstaus_e; typedef enum { - LWS_STANDARD_LWS_TRIMMING_STATUS_SENSOR_TRIMMED = 1, LWS_STANDARD_LWS_TRIMMING_STATUS_FAULT_SENSOR_NOT_TRIMMED = 0, + LWS_STANDARD_LWS_TRIMMING_STATUS_SENSOR_TRIMMED = 1, } lws_standard_lws_trimming_status_e; typedef enum { - LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0_ = 3, + LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0Â_ = 3, LWS_CONFIG_LWS_CCW_RESETS_CALIBRATION_STATUS = 5, } lws_config_lws_ccw_e; diff --git a/Firmware/config/Inc/can1_recv_entries.h b/Firmware/config/Inc/can1_recv_entries.h index 26a0097a..2aa2ecfd 100644 --- a/Firmware/config/Inc/can1_recv_entries.h +++ b/Firmware/config/Inc/can1_recv_entries.h @@ -8,3 +8,5 @@ CAN_RECV_ENTRY(CAN_ID_MC_INFO, 2, true) CAN_RECV_ENTRY(CAN_ID_MC_STATUS, 2, true) CAN_RECV_ENTRY(CAN_ID_MC_BUSMEASUREMENT, 2, true) CAN_RECV_ENTRY(CAN_ID_MC_VELOCITYMEASUREMENT, 2, true) +CAN_RECV_ENTRY(CAN_ID_SET_MOTOR_CMD_SRC, 2, true) + diff --git a/Firmware/scripts/fsm_generator.py b/Firmware/scripts/fsm_generator.py index 475ad0a3..404fe64b 100644 --- a/Firmware/scripts/fsm_generator.py +++ b/Firmware/scripts/fsm_generator.py @@ -94,29 +94,38 @@ def transition_full(cur, bits): def transition_dnr(cur, bits): + if cur == DISABLED: + return DISABLED + if cur == INIT: return NOT_READY + + if curr != DISABLED and not (bits & PC): + return NOT_READY if cur == NOT_READY: return NEUTRAL if (bits & PC) else NOT_READY - if cur == DISABLED: - return DISABLED - if cur == NEUTRAL: - if (bits & FWD) and not (bits & REV) and not (bits & BRK): + if (bits & FWD) and not (bits & REV): return FWD_DRIVE - if (bits & REV) and not (bits & FWD) and not (bits & BRK): + if (bits & REV) and not (bits & FWD): return REV_DRIVE return NEUTRAL - if cur in (FWD_DRIVE, REGEN, CRUISE): + if cur == FWD_DRIVE: + if (bits & REV) or (bits & NEU): + return NEUTRAL + return FWD_DRIVE + + + if cur in (REGEN, CRUISE): if (bits & REV) or (bits & NEU) or (bits & BRK): return NEUTRAL return FWD_DRIVE if cur == REV_DRIVE: - if (bits & REV) and not (bits & FWD) and not (bits & BRK): + if (bits & REV) and not (bits & FWD): return REV_DRIVE return NEUTRAL diff --git a/Firmware/tests/FaultHandler_test.c b/Firmware/tests/FaultHandler_test.c deleted file mode 100644 index 7b365063..00000000 --- a/Firmware/tests/FaultHandler_test.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "FaultHandlerTask.h" -#include "PrechargeTask.h" -#include "StatusLEDs.h" -#include "inits.h" - -int main() -{ - if (HAL_Init() != HAL_OK) - Error_Handler(); - SystemClock_Config(); - __HAL_RCC_SYSCFG_CLK_ENABLE(); - __HAL_RCC_PWR_CLK_ENABLE(); - - Init_UART_Printf(); - LED_init(); - - // Task - xTaskCreateStatic( - Task_FaultHandler, // Task function - "FaultHandler", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - tskIDLE_PRIORITY + 2, // Task priority - FaultHandlerTask_Stack, // Task handle - &FaultHandlerTask_Buffer // Static task buffer (optional) - ); - - hprecharge_task = xTaskCreateStatic( - Task_Precharge, // Task function - "Precharge", // Name of the task (for debugging) - configMINIMAL_STACK_SIZE, // Stack size in words - NULL, // Task input parameter - tskIDLE_PRIORITY + 1, // Task priority - Precharge_Task_Stack, // Task handle - &Precharge_Task_Buffer // Static task buffer (optional) - ); - - vTaskStartScheduler(); - - return 0; -} \ No newline at end of file diff --git a/Firmware/tests/faulthandler_test.c b/Firmware/tests/faulthandler_test.c new file mode 100644 index 00000000..28eb0de3 --- /dev/null +++ b/Firmware/tests/faulthandler_test.c @@ -0,0 +1,45 @@ +#include "FaultHandlerTask.h" +#include "PrechargeTask.h" +#include "StatusLEDs.h" +#include "InitTask.h" +#include "inits.h" + +int main() +{ + if (HAL_Init() != HAL_OK) + Error_Handler(); + SystemClock_Config(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + Init_UART_Printf(); + LED_init(); + + faults_init(); + + + // Task + xTaskCreateStatic( + Task_FaultHandler, + "FaultHandler", + FAULT_HANDLER_TASK_STACK_SIZE, + NULL, + FAULT_HANDLER_THREAD_PRIO, + FaultHandler_Task_Stack, + &FaultHandler_Task_Buffer + ); + + precharge_task_handle = xTaskCreateStatic( + Task_Precharge, + "Precharge", + PRECHARGE_TASK_STACK_SIZE, + NULL, + PRECHARGE_THREAD_PRIO, + Precharge_Task_Stack, + &Precharge_Task_Buffer + ); + + vTaskStartScheduler(); + + return 0; +} \ No newline at end of file diff --git a/Firmware/tests/fsm_transition_test.c b/Firmware/tests/fsm_transition_test.c index 199881c0..21010ed2 100644 --- a/Firmware/tests/fsm_transition_test.c +++ b/Firmware/tests/fsm_transition_test.c @@ -8,10 +8,10 @@ */ #include "VCUStatusTask.h" -#include "UpdateFSMInputsTask.h" +#include "UpdateVCUInputsTask.h" #include "inits.h" #include "InitTask.h" -#include "FSM.h" +#include "FSMTask.h" // #include "" #define PRINTF_DEBUG @@ -54,13 +54,13 @@ int main() { ); xTaskCreateStatic( - Task_UpdateFSMInputs, + Task_UpdateVCUInputs, "Update FSM Inputs Thread", - UPDATE_FSM_INPUTS_STACK_SIZE, + UPDATE_VCU_INPUTS_STACK_SIZE, NULL, - UPDATE_FSM_INPUTS_THREAD_PRIO, - UpdateFSMInputs_Task_Stack, - &UpdateFSMInputs_Task_Buffer + UPDATE_VCU_INPUTS_THREAD_PRIO, + UpdateVCUInputs_Task_Stack, + &UpdateVCUInputs_Task_Buffer ); xTaskCreateStatic( diff --git a/Firmware/tests/fsminputs_test b/Firmware/tests/fsminputs_test deleted file mode 100644 index cd1b41bc..00000000 --- a/Firmware/tests/fsminputs_test +++ /dev/null @@ -1,69 +0,0 @@ -/** - * VCU fsm inputs test. - * - * Enables vcu status task + update fsm inputs task. This basically tests if the - * inputs task is properly updating inputs as well as if the vcu status is - * properly updating too. - * - */ - -#include "VCUStatusTask.h" -#include "UpdateFSMInputsTask.h" -#include "inits.h" -#include "InitTask.h" -#include "FSM.h" - -#define PRINTF_DEBUG - -void can_error_handler() { - while (1) { - HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); - HAL_Delay(500); - } -} - -int main() { - HAL_Init(); - - SystemClock_Config(); - __HAL_RCC_SYSCFG_CLK_ENABLE(); - __HAL_RCC_PWR_CLK_ENABLE(); - - LED_init(); - - if (CarCAN_Init() != CAN_OK) { - can_error_handler(); - } - - Init_UART_Printf(); - - faults_init(); - contactor_init(); - FSM_TaskInit(); - fsm_init(); - - xTaskCreateStatic( - Task_BroadcastVCUStatus, - "VCU status", - VCU_STATUS_TASK_STACK_SIZE, - NULL, - VCU_STATUS_THREAD_PRIO, - VCUStatus_Task_Stack, - &VCUStatus_Task_Buffer - ); - - xTaskCreateStatic( - Task_UpdateFSMInputs, - "Update FSM Inputs Thread", - UPDATE_FSM_INPUTS_STACK_SIZE, - NULL, - UPDATE_FSM_INPUTS_THREAD_PRIO, - UpdateFSMInputs_Task_Stack, - &UpdateFSMInputs_Task_Buffer - ); - - vTaskStartScheduler(); - - while (1) { - } -} diff --git a/Firmware/tests/fsminputs_test.c b/Firmware/tests/fsminputs_test.c index 09c439c4..8154cea1 100644 --- a/Firmware/tests/fsminputs_test.c +++ b/Firmware/tests/fsminputs_test.c @@ -8,10 +8,10 @@ */ #include "VCUStatusTask.h" -#include "UpdateFSMInputsTask.h" +#include "UpdateVCUInputsTask.h" #include "inits.h" #include "InitTask.h" -#include "FSM.h" +#include "FSMTask.h" // #include "" #define PRINTF_DEBUG diff --git a/Firmware/tests/temp b/Firmware/tests/temp deleted file mode 100644 index f9669276..00000000 --- a/Firmware/tests/temp +++ /dev/null @@ -1,167 +0,0 @@ -// #include "CANbus.h" -#include "stm32xx_hal.h" -// #include "inits.h" -// #include "StatusLEDs.h" -#include "pinDefs.h" -#include "can_utils.h" - -StaticTask_t task_buffer; -StackType_t task_stack[512]; - -static void task(void *pvParameters){ - - int test_id = 0x321; - FDCAN_TxHeaderTypeDef tx_header = {0}; - tx_header.Identifier = test_id; - tx_header.IdType = FDCAN_STANDARD_ID; - tx_header.TxFrameType = FDCAN_DATA_FRAME; - tx_header.DataLength = FDCAN_DLC_BYTES_8; - tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header.BitRateSwitch = FDCAN_BRS_OFF; - tx_header.FDFormat = FDCAN_CLASSIC_CAN; - tx_header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; - tx_header.MessageMarker = 0; - - FDCAN_RxHeaderTypeDef rx_header; - uint8_t rx_data[64]; - - - // carcan for receiving - hfdcan3->Instance = FDCAN3; - hfdcan3->Init.ClockDivider = FDCAN_CLOCK_DIV1; - hfdcan3->Init.FrameFormat = FDCAN_FRAME_CLASSIC; - hfdcan3->Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; - hfdcan3->Init.AutoRetransmission = DISABLE; - hfdcan3->Init.TransmitPause = DISABLE; - hfdcan3->Init.ProtocolException = DISABLE; - hfdcan3->Init.NominalPrescaler = 20; - hfdcan3->Init.NominalSyncJumpWidth = 1; - hfdcan3->Init.NominalTimeSeg1 = 13; - hfdcan3->Init.NominalTimeSeg2 = 2; - hfdcan3->Init.DataPrescaler = 1; - hfdcan3->Init.DataSyncJumpWidth = 1; - hfdcan3->Init.DataTimeSeg1 = 1; - hfdcan3->Init.DataTimeSeg2 = 1; - hfdcan3->Init.StdFiltersNbr = 1; - hfdcan3->Init.ExtFiltersNbr = 0; - hfdcan3->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; - - FDCAN_FilterTypeDef carcan_filter_config = {0}; - carcan_filter_config.IdType = FDCAN_STANDARD_ID; - carcan_filter_config.FilterIndex = 0; - carcan_filter_config.FilterType = FDCAN_FILTER_MASK; - carcan_filter_config.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; - carcan_filter_config.FilterID1 = 0x000; - carcan_filter_config.FilterID2 = 0x000; - - can_fd_init(hfdcan3, &carcan_filter_config); - can_fd_start(hfdcan3); - - - // send x1234 to 0x11 - uint8_t tx_data[8] = {0}; - tx_data[0] = 0x12; - tx_data[1] = 0x34; - tx_data[2] = 0x56; - tx_data[3] = 0x78; - tx_data[4] = 0x9A; - tx_data[5] = 0xBC; - tx_data[6] = 0xDE; - tx_data[7] = 0xFF; - - while(1){ - - - HAL_GPIO_WritePin(HB_LED_PORT, HB_LED_PIN, GPIO_PIN_RESET); - if (can_fd_send(hfdcan3, &tx_header, tx_data, portMAX_DELAY) == CAN_ERR){ - Error_Handler(); - } - - vTaskDelay(pdMS_TO_TICKS(500)); - - if(can_fd_recv(hfdcan3, test_id, &rx_header, rx_data, portMAX_DELAY) != CAN_ERR){ - HAL_GPIO_WritePin(HB_LED_PORT, HB_LED_PIN, GPIO_PIN_SET); - vTaskDelay(pdMS_TO_TICKS(1000)); - - if(rx_data[0] == 0x12){ - for(int i = 0; i < 50; i++){ - HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); - vTaskDelay(pdMS_TO_TICKS(100)); - } - } - } - - HAL_GPIO_WritePin(HB_LED_PORT, HB_LED_PIN, GPIO_PIN_RESET); - vTaskDelay(pdMS_TO_TICKS(1000)); - - // TODO: add status LED - // HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); - // vTaskDelay(pdMS_TO_TICKS(1000)); - } -} - -void can_error_handler(){ - while(1){ - // LED_set(MOTOR_FAULT, GPIO_PIN_SET); - HAL_GPIO_TogglePin(HB_LED_PORT, HB_LED_PIN); - vTaskDelay(pdMS_TO_TICKS(200)); - } -} - -// Initialize clock for heartbeat LED port -void Heartbeat_Clock_Init() { - switch ((uint32_t)HB_LED_PORT) { - case (uint32_t)GPIOA: - __HAL_RCC_GPIOA_CLK_ENABLE(); - break; - case (uint32_t)GPIOB: - __HAL_RCC_GPIOB_CLK_ENABLE(); - break; - case (uint32_t)GPIOC: - __HAL_RCC_GPIOC_CLK_ENABLE(); - break; - } -} - -int main(){ - HAL_Init(); - - SystemClock_Config(); - __HAL_RCC_SYSCFG_CLK_ENABLE(); - __HAL_RCC_PWR_CLK_ENABLE(); - - // LEDs_init(); - - // Heartbeat LED on VCU is PB14 - GPIO_InitTypeDef led_config = { - .Mode = GPIO_MODE_OUTPUT_PP, - .Pull = GPIO_NOPULL, - .Pin = HB_LED_PIN - }; - - Heartbeat_Clock_Init(); // enable clock for HB_LED_PORT - HAL_GPIO_Init(HB_LED_PORT, &led_config); // initialize HB_LED_PORT with led_config - - - - // if(Motor_CANBus_Init() != CAN_OK){ - // can_error_handler(); - // } - - - xTaskCreateStatic( - task, - "task", - 512, - NULL, - tskIDLE_PRIORITY + 2, - task_stack, - &task_buffer); - - - vTaskStartScheduler(); - - while(1){ - - } -} \ No newline at end of file From c3c40d21aab3662e3e8e790edf7bff074ef03324 Mon Sep 17 00:00:00 2001 From: Adiv Padgilwar Date: Tue, 14 Apr 2026 14:48:16 -0500 Subject: [PATCH 14/27] erm dawgs -> no dawgs --- Firmware/Drivers/Inc/FaultBits.h | 14 +++++++- Firmware/Drivers/Src/CANbus.c | 19 ++++++++-- Firmware/Drivers/Src/FaultBits.c | 14 ++++++-- Firmware/Drivers/Src/Watchdogs.c | 22 ++++++++++++ Firmware/Makefile | 4 +++ Firmware/Tasks/Inc/FSMTask.h | 2 ++ Firmware/Tasks/Src/FSMTask.c | 10 ++++++ Firmware/Tasks/Src/InitTask.c | 5 +++ Firmware/Tasks/Src/MotorTelemetryTask.c | 6 +--- Firmware/Tasks/Src/UpdateVCUInputsTask.c | 6 ++++ Firmware/Tasks/Src/VCUStatusTask.c | 44 +++++++++++++++--------- 11 files changed, 118 insertions(+), 28 deletions(-) diff --git a/Firmware/Drivers/Inc/FaultBits.h b/Firmware/Drivers/Inc/FaultBits.h index 8974084b..44b2208c 100644 --- a/Firmware/Drivers/Inc/FaultBits.h +++ b/Firmware/Drivers/Inc/FaultBits.h @@ -198,4 +198,16 @@ void warning_set(WarningID_e id); * @brief Get the state of all warnings. * @return A bitmask of fault bits that are currently active. */ -EventBits_t warning_get(void); \ No newline at end of file +EventBits_t warning_get(void); + +/** + * @brief Checks if a specific warning bit is active. + * @return true if the specified warning bit is active, false otherwise. + */ +bool warning_is_active(WarningID_e id); + +/** + * @brief Clear a specific warning bit. + * @param id The warning to clear. + */ +void warning_clear(WarningID_e id); \ No newline at end of file diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 889b2e84..c3fedbfc 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -3,6 +3,7 @@ #include "CarCAN_can_msgs.h" #include "MotorCAN_can_msgs.h" #include "UpdateVCUInputsTask.h" +#include "Watchdogs.h" #include #include @@ -73,6 +74,7 @@ can_status_t MotorCAN_Recv_Velocity(mc_velocitymeasurement_t *out, TickType_t de if (result == CAN_OK) { out->MC_MotorVelocity = *((float *)&motor_vel_rx_data[0]); out->MC_VehicleVelocity = *((float *)&motor_vel_rx_data[4]); + watchdog_received_can_message(WD_IDX_MOCO_VELOCITY); } return result; } @@ -112,6 +114,8 @@ can_status_t MotorCAN_Recv_Status(mc_status_t *out, TickType_t delay) { (uint16_t)moco_status_rx_data[4] | ((uint16_t)moco_status_rx_data[5] << 8); out->MC_TxErrorCount = moco_status_rx_data[6]; out->MC_RxErrorCount = moco_status_rx_data[7]; + + watchdog_received_can_message(WD_IDX_MOCO_STATUS); } return result; @@ -124,7 +128,7 @@ can_status_t MotorCAN_Recv_Control_Src(set_motor_cmd_src_t *out, TickType_t dela uint8_t moco_control_src_rx_data[CAN_DLC_SET_MOTOR_CMD_SRC] = {0}; can_status_t result = - can_fd_recv(motorfdcan, CAN_ID_SET_MOTOR_CMD_SRC, &header, moco_status_rx_data, delay); + can_fd_recv(motorfdcan, CAN_ID_SET_MOTOR_CMD_SRC, &header, moco_control_src_rx_data, delay); if (result == CAN_OK) { out->Motor_Command_Source = moco_control_src_rx_data[0]; @@ -239,6 +243,8 @@ can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay) { ((uint32_t)bps_status_rx_data[6] << 16) | ((uint32_t)bps_status_rx_data[7] << 24)); out->Main_Battery_Avg_Temperature = (int16_t)((uint16_t)bps_status_rx_data[2] | ((uint16_t)bps_status_rx_data[3] << 8)); + + watchdog_received_can_message(WD_IDX_BPS_STATUS); } return result; } @@ -255,6 +261,7 @@ can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t dela if (result == CAN_OK) { out->Controls_Leader_Fault = controls_status_rx_data[0]; // out->Controls_Lighting_Fault = (uint16_t) (controls_status_rx_data[1]); + watchdog_received_can_message(WD_IDX_CONTROLS_STATUS); } return result; @@ -282,6 +289,8 @@ can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay) { out->LWS_Fault = (steering_angle_rx_data[3] >> 0) & 0x01; out->LWS_CalibrationStaus = (steering_angle_rx_data[3] >> 1) & 0x01; out->LWS_Trimming_Status = (steering_angle_rx_data[3] >> 2) & 0x01; + + watchdog_received_can_message(WD_IDX_STEERING_ANGLE); } return result; @@ -313,6 +322,8 @@ can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t del out->PushToTalk_Pressed = !!(driver_input_rx_data[1] & (1U << 4)); out->Regen_Activate = !!(driver_input_rx_data[1] & (1U << 5)); out->Regen_Enable = !!(driver_input_rx_data[1] & (1U << 6)); + + watchdog_received_can_message(WD_IDX_DRIVER_INPUT); } return result; @@ -337,6 +348,8 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) out->AccelPedal_Redundant_Fault = !!(pedals_pos_rx_data[4] & (1U << 1)); out->BrakePedal_Main_Fault = !!(pedals_pos_rx_data[4] & (1U << 2)); out->BrakePedal_Redundant_Fault = !!(pedals_pos_rx_data[4] & (1U << 3)); + + watchdog_received_can_message(WD_IDX_ACCEL_BRAKE); } return result; @@ -358,8 +371,8 @@ can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_ uint8_t vcu_prech_tx_data[CAN_DLC_VCU_PRECHARGE_VOLTAGES] = {0}; - memcpy(&vcu_prech_tx_data[0], &motor_mv, sizeof(uint32_t)); - memcpy(&vcu_prech_tx_data[4], &battery_mv, sizeof(uint32_t)); + memcpy(&vcu_prech_tx_data[0], &motor_mv, 3); + memcpy(&vcu_prech_tx_data[3], &battery_mv, 3); can_status_t result = can_fd_send(carfdcan, &header, vcu_prech_tx_data, delay); diff --git a/Firmware/Drivers/Src/FaultBits.c b/Firmware/Drivers/Src/FaultBits.c index 1d0142b7..d111aaba 100644 --- a/Firmware/Drivers/Src/FaultBits.c +++ b/Firmware/Drivers/Src/FaultBits.c @@ -82,10 +82,20 @@ EventBits_t faults_wait(FaultID_e id, TickType_t ticks) { } void warning_set(WarningID_e id) { - configASSERT(id < FAULT_ID_COUNT); - xEventGroupSetBits(warningGroup, FAULT_BIT(id)); + configASSERT(id < WARNING_ID_COUNT); + xEventGroupSetBits(warningGroup, 1 << id); +} + +void warning_clear(WarningID_e id) { + configASSERT(id < WARNING_ID_COUNT); + xEventGroupClearBits(warningGroup, 1 << id); } EventBits_t warning_get(void) { return xEventGroupGetBits(warningGroup) & WARNING_MASK_ALL; +} + +bool warning_is_active(WarningID_e id) { + configASSERT(id < WARNING_ID_COUNT); + return (xEventGroupGetBits(warningGroup) & (1 << id)) != 0; } \ No newline at end of file diff --git a/Firmware/Drivers/Src/Watchdogs.c b/Firmware/Drivers/Src/Watchdogs.c index 627a0c12..cb0f6d0a 100644 --- a/Firmware/Drivers/Src/Watchdogs.c +++ b/Firmware/Drivers/Src/Watchdogs.c @@ -9,12 +9,16 @@ #include #include +#ifndef NODAWG static StaticTimer_t wd_buffers[MAX_WD_TIMERS] = {0}; static TimerHandle_t wd_timers[MAX_WD_TIMERS] = {0}; static bool wd_alive[MAX_WD_TIMERS] = {0}; static FaultID_e wd_fault_ids[MAX_WD_TIMERS] = {0}; +#endif + static uint8_t wd_count = 0; +#ifndef NODAWG // Callback function for when a watchdog timer expires static void wd_callback(TimerHandle_t xTimer) { uint8_t idx = (uint8_t)(uintptr_t)pvTimerGetTimerID(xTimer); @@ -22,15 +26,20 @@ static void wd_callback(TimerHandle_t xTimer) { printf("WD timeout: signal %d\n", idx); faults_set(wd_fault_ids[idx]); } +#endif void watchdog_init(void) { +#ifndef NODAWG #define X(name, str, timeout, fault) \ watchdog_create(str, WD_IDX_##name, timeout, fault); WATCHDOG_LIST(X) #undef X +#endif } void watchdog_create(const char *name, uint8_t idx, uint32_t timeout_ms, FaultID_e fault_id) { +#ifndef NODAWG + configASSERT(wd_count < MAX_WD_TIMERS); configASSERT(idx < MAX_WD_TIMERS); @@ -47,35 +56,48 @@ void watchdog_create(const char *name, uint8_t idx, uint32_t timeout_ms, FaultID wd_alive[idx] = true; wd_fault_ids[idx] = fault_id; wd_count++; +#endif } void watchdog_start_all(void) { +#ifndef NODAWG for (uint8_t i = 0; i < wd_count; i++) { configASSERT(xTimerStart(wd_timers[i], portMAX_DELAY) == pdPASS); } +#endif } void watchdog_stop_all(void) { +#ifndef NODAWG for (uint8_t i = 0; i < wd_count; i++) { xTimerStop(wd_timers[i], portMAX_DELAY); } +#endif } void watchdog_received_can_message(uint8_t idx) { +#ifndef NODAWG configASSERT(idx < MAX_WD_TIMERS && wd_timers[idx] != NULL); wd_alive[idx] = true; xTimerReset(wd_timers[idx], 0); +#endif } void watchdog_received_can_message_ISR(uint8_t idx, BaseType_t *pxHigherPriorityTaskWoken) { +#ifndef NODAWG configASSERT(idx < MAX_WD_TIMERS && wd_timers[idx] != NULL); wd_alive[idx] = true; xTimerResetFromISR(wd_timers[idx], pxHigherPriorityTaskWoken); +#endif } bool watchdog_is_alive(int idx) { +#ifndef NODAWG if (idx < 0 || idx >= MAX_WD_TIMERS) return false; return wd_alive[idx]; +#else + return true; +#endif } uint8_t watchdog_count(void) { return wd_count; } diff --git a/Firmware/Makefile b/Firmware/Makefile index a3781177..b3524a16 100644 --- a/Firmware/Makefile +++ b/Firmware/Makefile @@ -52,6 +52,10 @@ PROJECT_BUILD_DIR := $(addprefix $(MAKEFILE_DIR)/, $(PROJECT_BUILD_DIR)) # Additional defines PROJECT_MACROS = USART3_RX_QUEUE_SIZE=100 +ifeq ($(NODAWG),1) +PROJECT_MACROS += NODAWG +endif + # export variables export PROJECT_TARGET export PROJECT_C_SOURCES diff --git a/Firmware/Tasks/Inc/FSMTask.h b/Firmware/Tasks/Inc/FSMTask.h index 3902825e..c184f914 100644 --- a/Firmware/Tasks/Inc/FSMTask.h +++ b/Firmware/Tasks/Inc/FSMTask.h @@ -99,3 +99,5 @@ void Task_FSM(void *args); float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, uint8_t out_max); + +bool fsm_is_input_set(InputBits_t bit); diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index f578b988..297c0ae3 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -84,6 +84,10 @@ uint16_t fsm_get_inputs(void) { return (uint16_t)xEventGroupGetBits(fsmInputGroup); } +bool fsm_is_input_set(InputBits_t bit) { + return (xEventGroupGetBits(fsmInputGroup) & bit) != 0; +} + // goofy ahh logic, uses lut @@ -98,8 +102,11 @@ static float apply_rollover_limit(float requested_current) { if (v_max_cms != ROLLOVER_TABLE_NO_LIMIT && v_now_cms > v_max_cms) { rollover_limit_active = true; + warning_set(WARNING_ID_TIPPING_LIMIT_ACTIVE); return 0.0f; } + + warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); rollover_limit_active = false; return requested_current; } @@ -126,7 +133,9 @@ static void handle_state_forward(void) { if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { // if we're actually going backwards, let off the pedal until we slow down MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { + warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); MotorCAN_Send_Drive_Cmd( MAX_VELOCITY, fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), @@ -139,6 +148,7 @@ static void handle_state_reverse(void) { if (g_data_read->motor_velocity.MC_VehicleVelocity > 0.5f) { // if we're actually going forwards, let off the pedal until we slow down MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { MotorCAN_Send_Drive_Cmd( -MAX_VELOCITY, diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index d9686fca..f7529037 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -1,5 +1,6 @@ #include "InitTask.h" #include "StatusLEDs.h" +#include "Watchdogs.h" StaticTask_t FaultHandler_Task_Buffer; StackType_t FaultHandler_Task_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; @@ -38,6 +39,10 @@ void Task_Init() { FSM_TaskInit(); + // watchdog_init(); + // watchdog_start_all(); + + // Required for VCU status testing faults_init(); diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index e1777197..f3d7896a 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -64,14 +64,10 @@ void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, c tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; tx_header.MessageMarker = 0; - can_fd_send_isr(motorfdcan, &tx_header, recv_payload.data, higherPriorityTaskWoken); + can_fd_send_isr(motorfdcan, &tx_header, recv_payload.data, &higherPriorityTaskWoken); } } - xQueueSendFromISR(motorTelemetryQueue, &recv_payload, &higherPriorityTaskWoken); - // don't yield at the end of this since the rest of the ISR needs to run - } -} void Task_MotorTelemetry() { diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index d9d23237..0024ecb0 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -42,6 +42,12 @@ static void rebuild_inputs(void) { } fsm_set_all_inputs(s); + + if(fsm_is_input_set(REGEN_BUTTON_BIT) && !fsm_is_input_set(READY_TO_REGEN_BIT)) { + warning_set(WARNING_ID_REGEN_NOT_ALLOWED); + } else { + warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); + } } void UFI_throw_faults() { diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 70dd8331..074f3e9d 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -6,6 +6,7 @@ #include "UpdateVCUInputsTask.h" #include "Watchdogs.h" #include "event_groups.h" +#include "math.h" void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { uint8_t buf[CAN_DLC_VCU_STATUS]; @@ -29,17 +30,21 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { bool bps_fault = faults_is_active(FAULT_ID_BPS_FAULT); bool controls_fault = faults_is_active(FAULT_ID_CONTROLS_FAULT); bool motor_fault = !!(faults_get() & FAULT_MASK_MOTOR_ALL); - bool pedals_fault = !((bool)g_data_read->accel_brake.AccelPedal_Main_Fault) && - !((bool)g_data_read->accel_brake.AccelPedal_Redundant_Fault) && - !((bool)g_data_read->accel_brake.BrakePedal_Main_Fault) && - !((bool)g_data_read->accel_brake.BrakePedal_Redundant_Fault); + bool pedals_fault = ((bool)g_data_read->accel_brake.AccelPedal_Main_Fault) || + ((bool)g_data_read->accel_brake.AccelPedal_Redundant_Fault) || + ((bool)g_data_read->accel_brake.BrakePedal_Main_Fault) || + ((bool)g_data_read->accel_brake.BrakePedal_Redundant_Fault) || + (fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - + g_data_read->accel_brake.AccelPedal_Redundant_Pos) > + ACCEPTABLE_PEDAL_DEVIATION); + bool steering_fault = g_data_read->lws.LWS_Fault; buf[1] = (pedals_wdog) | (bps_wdog << 1) | (steering_wdog << 2) | (bps_fault << 3) | (controls_fault << 4) | (motor_fault << 5) | (pedals_fault << 6) | (steering_fault << 7); - buf[2] = g_data_read->motor_controls_src | - (!!(fsm_get_inputs() & READY_TO_REGEN_BIT) << 1) | + buf[2] = g_data_read->motor_controls_src.Motor_Command_Source | + ((current_state.stateName == REGEN) << 1) | (g_data_read->bps_status.BPS_Regen_OK << 2) | (faults_is_active(FAULT_ID_PRECHARGE_TIMEOUT) << 3) | (faults_is_active(FAULT_ID_PRECHARGE_SENSE_TIMEOUT) << 4) | @@ -51,19 +56,24 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { (faults_is_active(FAULT_ID_BATTERY_UNDERVOLTAGE) << 1) | (faults_is_active(FAULT_ID_MOTOR_GT_BATTERY) << 2) | // TODO check if this is right (faults_is_active(FAULT_ID_MOTOR_LT_BATTERY) << 3) | - (faults_any_active() << 4) | // TODO: make this "other" - (faults_is_active(FAULT_ID_MOTOR_GT_BATTERY) << 2) | - + //(faults_any_active() << 4) | // TODO: make this "other" but not enough faults bits rn + //The rest of these bits and one of the next one are all warnings + (warning_is_active(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT) << 5) | + (warning_is_active(WARNING_ID_TIPPING_LIMIT_ACTIVE) << 6) | + (warning_is_active(WARNING_ID_REGEN_NOT_ALLOWED) << 7); + buf[4] = (warning_is_active(WARNING_ID_REGEN_NOT_ENABLED) << 0) | + (fsm_is_input_set(BRAKE_BIT) << 1) | + (fsm_is_input_set(PRECHARGE_COMPLETE_BIT) << 2) | + (fsm_is_input_set(CRUISE_CONTROL_BUTTON_BIT) << 3) | + (fsm_is_input_set(REGEN_BUTTON_BIT) << 4) | + (fsm_is_input_set(REGEN_ENABLED_BIT) << 5) | + (fsm_is_input_set(READY_TO_REGEN_BIT) << 6) | + (fsm_is_input_set(FORWARD_BIT) << 7); - buf[3] = fsm_get_inputs(); // this supposed to have fsm states as well but stateName covers - // it for now + buf[5] = (fsm_is_input_set(NEUTRAL_BIT) << 0) | + (fsm_is_input_set(REVERSE_BIT) << 1); - // for viewing faults in status - int faults = 0x0FFFFFF & faults_get(); - buf[4] = (faults >> 16) & 0xFF; - buf[5] = (faults >> 8) & 0xFF; - buf[6] = faults & 0xFF; FDCAN_TxHeaderTypeDef tx_header = {0}; tx_header.Identifier = CAN_ID_VCU_STATUS; @@ -78,7 +88,7 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { CarCAN_Send(&tx_header, buf, sizeof(buf)); - // LED_toggle(HB); + LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(100)); } } \ No newline at end of file From ddcbc8ff681cc443e9175d0228ab28db767bd68d Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 15 Apr 2026 06:52:31 -0500 Subject: [PATCH 15/27] stuff semi working --- Firmware/Drivers/Inc/Watchdogs.h | 16 +- Firmware/Drivers/Src/CANbus.c | 10 +- Firmware/Drivers/Src/Watchdogs.c | 25 +- Firmware/Tasks/Inc/PrechargeTask.h | 2 +- Firmware/Tasks/Inc/fsm_table.h | 2 +- Firmware/Tasks/Inc/fsm_table_dnr.h | 326 +++++++++++----------- Firmware/Tasks/Src/FSMTask.c | 11 +- Firmware/Tasks/Src/FaultHandlerTask.c | 2 +- Firmware/Tasks/Src/InitTask.c | 4 +- Firmware/Tasks/Src/MotorTelemetryTask.c | 12 +- Firmware/Tasks/Src/PrechargeTask.c | 9 +- Firmware/Tasks/Src/UpdateVCUInputsTask.c | 17 +- Firmware/Tasks/Src/VCUStatusTask.c | 4 +- Firmware/scripts/fsm_generator.py | 2 +- Firmware/scripts/voltage_lut_generator.py | 63 +++++ 15 files changed, 300 insertions(+), 205 deletions(-) create mode 100644 Firmware/scripts/voltage_lut_generator.py diff --git a/Firmware/Drivers/Inc/Watchdogs.h b/Firmware/Drivers/Inc/Watchdogs.h index e56625f2..f049fed7 100644 --- a/Firmware/Drivers/Inc/Watchdogs.h +++ b/Firmware/Drivers/Inc/Watchdogs.h @@ -14,6 +14,8 @@ #define MAX_WD_TIMERS 10 +#define NODAWG 1 + /** * @brief List of watchdogs to create, along with their timeouts and fault IDs * Format: X(name, string_name, timeout_ms, fault_id) @@ -27,13 +29,13 @@ * caused the fault. Just make sure to add the new fault IDs to FaultBits.h as well. */ #define WATCHDOG_LIST(X) \ - X(DRIVER_INPUT, "wd_driver_input", 150U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(ACCEL_BRAKE, "wd_accel_brake", 150U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(STEERING_ANGLE, "wd_steering_angle", 300U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(CONTROLS_STATUS, "wd_controls_status", 300U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(BPS_STATUS, "wd_bps_status", 300U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(MOCO_STATUS, "wd_moco_status", 500U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(MOCO_VELOCITY, "wd_moco_velocity", 500U, FAULT_ID_GENERIC_WATCHDOG_FAULT) + X(DRIVER_INPUT, "wd_driver_input", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(ACCEL_BRAKE, "wd_accel_brake", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(STEERING_ANGLE, "wd_steering_angle", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(CONTROLS_STATUS, "wd_controls_status", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(BPS_STATUS, "wd_bps_status", 2000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(MOCO_STATUS, "wd_moco_status", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(MOCO_VELOCITY, "wd_moco_velocity", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) typedef enum { #define X(name, str, timeout, fault) WD_IDX_##name, diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index c3fedbfc..58b0fba0 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -20,7 +20,7 @@ can_status_t MotorCAN_Init(void) { motorfdcan->Init.ClockDivider = FDCAN_CLOCK_DIV1; motorfdcan->Init.FrameFormat = FDCAN_FRAME_CLASSIC; motorfdcan->Init.Mode = FDCAN_MODE_NORMAL; - motorfdcan->Init.AutoRetransmission = DISABLE; + motorfdcan->Init.AutoRetransmission = ENABLE; motorfdcan->Init.TransmitPause = DISABLE; motorfdcan->Init.ProtocolException = DISABLE; motorfdcan->Init.NominalPrescaler = 20; @@ -139,6 +139,7 @@ can_status_t MotorCAN_Recv_Control_Src(set_motor_cmd_src_t *out, TickType_t dela can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay) { + // printf("Motor CAN send drive cmd: %f vel, %f curr", velocity, current); if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; if (g_data_read->motor_controls_src.Motor_Command_Source) return CAN_OK; @@ -150,7 +151,7 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d .ErrorStateIndicator = FDCAN_ESI_ACTIVE, .BitRateSwitch = FDCAN_BRS_OFF, .FDFormat = FDCAN_CLASSIC_CAN, - .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, .MessageMarker = 0, }; @@ -357,6 +358,9 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, TickType_t delay) { + + printf("Car CAN send prech voltages: %lu motor_mv, %lu batt_mv\n\r", motor_mv, battery_mv); + FDCAN_TxHeaderTypeDef header = { .Identifier = CAN_ID_VCU_PRECHARGE_VOLTAGES, .IdType = FDCAN_STANDARD_ID, @@ -365,7 +369,7 @@ can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_ .ErrorStateIndicator = FDCAN_ESI_ACTIVE, .BitRateSwitch = FDCAN_BRS_OFF, .FDFormat = FDCAN_CLASSIC_CAN, - .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, .MessageMarker = 0, }; diff --git a/Firmware/Drivers/Src/Watchdogs.c b/Firmware/Drivers/Src/Watchdogs.c index cb0f6d0a..d578388b 100644 --- a/Firmware/Drivers/Src/Watchdogs.c +++ b/Firmware/Drivers/Src/Watchdogs.c @@ -9,21 +9,26 @@ #include #include + #ifndef NODAWG +static StaticEventGroup_t dogBuffer; +static EventGroupHandle_t dogGroup; // 1 = alive, 0 = dead static StaticTimer_t wd_buffers[MAX_WD_TIMERS] = {0}; static TimerHandle_t wd_timers[MAX_WD_TIMERS] = {0}; -static bool wd_alive[MAX_WD_TIMERS] = {0}; static FaultID_e wd_fault_ids[MAX_WD_TIMERS] = {0}; #endif static uint8_t wd_count = 0; +#define WDOG_MASK_ALL ((1UL << WD_IDX_COUNT) - 1) +#define WDOG_BIT(idx) (1UL << idx) + #ifndef NODAWG // Callback function for when a watchdog timer expires static void wd_callback(TimerHandle_t xTimer) { uint8_t idx = (uint8_t)(uintptr_t)pvTimerGetTimerID(xTimer); - wd_alive[idx] = false; - printf("WD timeout: signal %d\n", idx); + xEventGroupClearBits(dogGroup, WDOG_BIT(idx)); + printf("WD timeout: signal %d\r\n", idx); faults_set(wd_fault_ids[idx]); } #endif @@ -34,6 +39,11 @@ void watchdog_init(void) { watchdog_create(str, WD_IDX_##name, timeout, fault); WATCHDOG_LIST(X) #undef X + dogGroup = xEventGroupCreateStatic(&dogBuffer); + if (dogGroup == NULL) { + return; + } + xEventGroupSetBits(dogGroup, WDOG_MASK_ALL); #endif } @@ -52,8 +62,7 @@ void watchdog_create(const char *name, uint8_t idx, uint32_t timeout_ms, FaultID &wd_buffers[wd_count] ); configASSERT(t != NULL); - wd_timers[wd_count] = t; - wd_alive[idx] = true; + wd_timers[idx] = t; wd_fault_ids[idx] = fault_id; wd_count++; #endif @@ -78,7 +87,7 @@ void watchdog_stop_all(void) { void watchdog_received_can_message(uint8_t idx) { #ifndef NODAWG configASSERT(idx < MAX_WD_TIMERS && wd_timers[idx] != NULL); - wd_alive[idx] = true; + xEventGroupSetBits(dogGroup, (0x1 << idx)); xTimerReset(wd_timers[idx], 0); #endif } @@ -86,7 +95,7 @@ void watchdog_received_can_message(uint8_t idx) { void watchdog_received_can_message_ISR(uint8_t idx, BaseType_t *pxHigherPriorityTaskWoken) { #ifndef NODAWG configASSERT(idx < MAX_WD_TIMERS && wd_timers[idx] != NULL); - wd_alive[idx] = true; + xEventGroupClearBitsFromISR(dogGroup, WDOG_BIT(idx)); xTimerResetFromISR(wd_timers[idx], pxHigherPriorityTaskWoken); #endif } @@ -94,7 +103,7 @@ void watchdog_received_can_message_ISR(uint8_t idx, BaseType_t *pxHigherPriority bool watchdog_is_alive(int idx) { #ifndef NODAWG if (idx < 0 || idx >= MAX_WD_TIMERS) return false; - return wd_alive[idx]; + return ((xEventGroupGetBits(dogGroup) >> idx) & 0x1); #else return true; #endif diff --git a/Firmware/Tasks/Inc/PrechargeTask.h b/Firmware/Tasks/Inc/PrechargeTask.h index bfd3484e..66695dd3 100644 --- a/Firmware/Tasks/Inc/PrechargeTask.h +++ b/Firmware/Tasks/Inc/PrechargeTask.h @@ -10,7 +10,7 @@ #include // Precharge thresholds -#define OVERVOLTAGE_THRESHOLD_MV 140000 // 140 V +#define OVERVOLTAGE_THRESHOLD_MV 180000 // 140 V #define UNDERVOLTAGE_THRESHOLD_MV 80000 // 80.0 V // Fixed-point scaling for ratio comparisons diff --git a/Firmware/Tasks/Inc/fsm_table.h b/Firmware/Tasks/Inc/fsm_table.h index 8871fed9..166018ee 100644 --- a/Firmware/Tasks/Inc/fsm_table.h +++ b/Firmware/Tasks/Inc/fsm_table.h @@ -5,7 +5,7 @@ */ #pragma once -#include "FSM.h" +#include "FSMTask.h" extern MocoState_t FSM[NUM_STATES]; diff --git a/Firmware/Tasks/Inc/fsm_table_dnr.h b/Firmware/Tasks/Inc/fsm_table_dnr.h index aa2b035b..2de8245a 100644 --- a/Firmware/Tasks/Inc/fsm_table_dnr.h +++ b/Firmware/Tasks/Inc/fsm_table_dnr.h @@ -79,6 +79,38 @@ MocoState_t FSM[NUM_STATES] = { CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY }}, [FORWARD_DRIVE] = { FORWARD_DRIVE, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -95,23 +127,6 @@ MocoState_t FSM[NUM_STATES] = { FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -127,24 +142,41 @@ MocoState_t FSM[NUM_STATES] = { FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE }}, [NEUTRAL_DRIVE] = { NEUTRAL_DRIVE, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -161,23 +193,6 @@ MocoState_t FSM[NUM_STATES] = { NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -193,24 +208,41 @@ MocoState_t FSM[NUM_STATES] = { NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, FORWARD_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE }}, [REVERSE_DRIVE] = { REVERSE_DRIVE, NULL, { + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -227,23 +259,6 @@ MocoState_t FSM[NUM_STATES] = { NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -259,56 +274,41 @@ MocoState_t FSM[NUM_STATES] = { NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE }}, [REGEN] = { REGEN, NULL, { - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, @@ -343,38 +343,38 @@ MocoState_t FSM[NUM_STATES] = { NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE }}, [CRUISE_CONTROL] = { CRUISE_CONTROL, NULL, { - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, + CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 297c0ae3..270c48e7 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -12,6 +12,7 @@ #include "UpdateVCUInputsTask.h" #include "FaultBits.h" #include "Watchdogs.h" +#include "StatusLEDs.h" #include #include #include @@ -61,6 +62,7 @@ void fsm_init(void) { void fsm_step(void) { fsm_inputs = xEventGroupGetBits(fsmInputGroup); current_state = FSM[current_state.NextStates[fsm_inputs]]; + printf("FSM step: %X inputs, %d curr_state\n\r", fsm_inputs, current_state.stateName); if (current_state.stateHandler) current_state.stateHandler(); } @@ -92,8 +94,8 @@ bool fsm_is_input_set(InputBits_t bit) { // goofy ahh logic, uses lut static float apply_rollover_limit(float requested_current) { - printf("Applying rollover limit, requested current: %.2f, vehicle velocity: %.2f, steering angle: %.1f\r\n", - requested_current, g_data_read->motor_velocity.MC_VehicleVelocity, (float)g_data_read->lws.LWS_Angle / 10.0f); + // printf("Applying rollover limit, requested current: %.2f, vehicle velocity: %.2f, steering angle: %.1f\r\n", + // requested_current, g_data_read->motor_velocity.MC_VehicleVelocity, (float)g_data_read->lws.LWS_Angle / 10.0f); int deg = abs((int)g_data_read->lws.LWS_Angle) / 10; if (deg > (int)ROLLOVER_TABLE_MAX_DEG) deg = (int)ROLLOVER_TABLE_MAX_DEG; @@ -186,9 +188,10 @@ static uint8_t apply_swoc_speed_limit(float speed_mph) { void Task_FSM(void *args __attribute__((unused))) { - TickType_t last = xTaskGetTickCount(); + // TickType_t last = xTaskGetTickCount(); while (1) { fsm_step(); - vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); + vTaskDelay(pdMS_TO_TICKS(250)); + // vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); } } diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index d3ecf4c2..ca7d0c10 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -88,7 +88,7 @@ void Task_FaultHandler(void *args __attribute__((unused))) { clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); clear_MotorSafeBit(MOTOR_PRECHARGE_CONTACTOR_ENABLED); - // fsm_disable(); + fsm_disable(); watchdog_stop_all(); printf("Fault Handler triggered: 0x%02lX\r\n", bits); diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index f7529037..f932dc18 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -39,8 +39,8 @@ void Task_Init() { FSM_TaskInit(); - // watchdog_init(); - // watchdog_start_all(); + watchdog_init(); + watchdog_start_all(); // Required for VCU status testing diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index f3d7896a..76227851 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -55,16 +55,16 @@ void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, c FDCAN_TxHeaderTypeDef tx_header = {0}; tx_header.Identifier = recv_payload.header.Identifier; - tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.IdType = recv_payload.header.IdType; tx_header.TxFrameType = FDCAN_DATA_FRAME; - tx_header.DataLength = FDCAN_DLC_BYTES(CAN_DLC_VCU_STATUS); - tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header.BitRateSwitch = FDCAN_BRS_OFF; - tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.DataLength = recv_payload.header.DataLength; + tx_header.ErrorStateIndicator = recv_payload.header.ErrorStateIndicator; + tx_header.BitRateSwitch = recv_payload.header.BitRateSwitch; + tx_header.FDFormat = recv_payload.header.FDFormat; tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; tx_header.MessageMarker = 0; - can_fd_send_isr(motorfdcan, &tx_header, recv_payload.data, &higherPriorityTaskWoken); + can_fd_send_isr(carfdcan, &tx_header, recv_payload.data, &higherPriorityTaskWoken); } } diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index e2e85fcf..b2b01e21 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -125,6 +125,13 @@ void Task_Precharge() { // Startup state: Closes main contactor and moves to precharging state case PRECHARGE_STATE_INITIAL: printf("Precharge State: Initial\r\n"); + + // dont attempt to close contactors before bps ready + if (!g_data_read->bps_status.HV_Plus_Contactor_State || + !g_data_read->bps_status.HV_Minus_Contactor_State || + g_data_read->bps_status.BPS_Fault) { + break; + } if (contactor_set(MOTOR_CONTACTOR, CLOSED, CALLBACK_BLOCKING_TIME, NORMAL) != SUCCESS) { @@ -220,7 +227,7 @@ void Task_Precharge() { clear_MotorSafeBit(MOTOR_CONTACTOR_ENABLED); } - LED_toggle(HB); + // LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(PRECHARGE_TASK_DELAY_MS)); } } \ No newline at end of file diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index 0024ecb0..a3cedc16 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -1,6 +1,7 @@ #include "UpdateVCUInputsTask.h" #include "Contactors.h" #include "FaultBits.h" +#include "StatusLEDs.h" #include "event_groups.h" #include #include @@ -81,9 +82,9 @@ void UFI_throw_faults() { if (g_data_read->accel_brake.AccelPedal_Main_Fault || g_data_read->accel_brake.AccelPedal_Redundant_Fault || g_data_read->accel_brake.BrakePedal_Main_Fault || - g_data_read->accel_brake.BrakePedal_Redundant_Fault || - fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - - g_data_read->accel_brake.AccelPedal_Redundant_Pos) > ACCEPTABLE_PEDAL_DEVIATION) { + g_data_read->accel_brake.BrakePedal_Redundant_Fault ) {//|| + // fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - + // g_data_read->accel_brake.AccelPedal_Redundant_Pos) > ACCEPTABLE_PEDAL_DEVIATION) { mask |= FAULT_BIT(FAULT_ID_PEDAL_BOARD_FAULT); } @@ -97,8 +98,12 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { TickType_t last = xTaskGetTickCount(); while (1) { + printf("Task_UpdateVCUInputs: %ld", last); // update from can VCUDataIn_t *volatile update = g_data_write; + if (MotorCAN_Recv_Status(&update->motor_status, 0) == CAN_OK) { + LED_toggle(HB); + } MotorCAN_Recv_Status(&update->motor_status, 0); MotorCAN_Recv_Velocity(&update->motor_velocity, 0); MotorCAN_Recv_Control_Src(&update->motor_controls_src, 0); @@ -111,14 +116,16 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { CarCAN_Recv_Driver_Input(&update->driver_input, 0); CarCAN_Recv_LWS(&update->lws, 0); + // printf("Update VCU inputs: about to switch read and write ptrs"); + VCUDataIn_t *volatile tmp; taskENTER_CRITICAL(); tmp = g_data_read; g_data_read = g_data_write; g_data_write = tmp; taskEXIT_CRITICAL(); - - + + // printf("Updated from CAN!"); memcpy(g_data_write, g_data_read, sizeof(VCUDataIn_t)); diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 074f3e9d..14f99236 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -88,7 +88,7 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { CarCAN_Send(&tx_header, buf, sizeof(buf)); - LED_toggle(HB); - vTaskDelay(pdMS_TO_TICKS(100)); + // LED_toggle(HB); + vTaskDelay(pdMS_TO_TICKS(800)); } } \ No newline at end of file diff --git a/Firmware/scripts/fsm_generator.py b/Firmware/scripts/fsm_generator.py index 404fe64b..a7594a0e 100644 --- a/Firmware/scripts/fsm_generator.py +++ b/Firmware/scripts/fsm_generator.py @@ -100,7 +100,7 @@ def transition_dnr(cur, bits): if cur == INIT: return NOT_READY - if curr != DISABLED and not (bits & PC): + if cur != DISABLED and not (bits & PC): return NOT_READY if cur == NOT_READY: diff --git a/Firmware/scripts/voltage_lut_generator.py b/Firmware/scripts/voltage_lut_generator.py new file mode 100644 index 00000000..c32e3d48 --- /dev/null +++ b/Firmware/scripts/voltage_lut_generator.py @@ -0,0 +1,63 @@ +import numpy as np +import os + +def generate_voltage_lut(csv_path, output_path): + # Get the directory where the script itself is located + script_dir = os.path.dirname(os.path.abspath(__file__)) + + adc_max = 4095 # 12-bit ADC + + # Constants + VREF_MV = 3300 + GAIN_NUM = 5 + GAIN_DEN = 2 + R_NUM = 102490 + R_DEN = 2490 + + adc_range = np.arange(4096, dtype=np.uint64) + + # Integer math for voltage calculation + numerator = adc_range * VREF_MV * GAIN_NUM * R_NUM + denominator = adc_max * GAIN_DEN * R_DEN + voltage_milli_v = (numerator + denominator // 2) // denominator # rounded division + + # Prepare C header file content + header_content = [ + "#pragma once", + "", + "#include ", + "", + "/**", + " * @brief Look-up table for voltage ADC counts to voltage.", + " * Index: 12-bit ADC Count (0 - 4095)", + " * Value: Voltage in millivolts (mV)", + " */", + "static const uint32_t voltage_lut[4096] = {" + ] + + # Add array entries formatted for readability (10 per line) + for i in range(0, len(voltage_milli_v), 10): + row = voltage_milli_v[i:i+10] + row_str = " " + ", ".join(f"{val:7d}" for val in row) + if i + 10 < len(voltage_milli_v): + row_str += "," + header_content.append(row_str) + + header_content.append("};") + + # Get the directory where the script itself is located + script_dir = os.path.dirname(os.path.abspath(__file__)) + # Join that directory with your filename + output = os.path.join(script_dir, output_path) + + # Ensure directory exists and write file + os.makedirs(os.path.dirname(output), exist_ok=True) + with open(output, 'w') as f: + f.write("\n".join(header_content)) + + print(f"Successfully generated {output}") + +if __name__ == "__main__": + csv_filename = 'ERTJ1VR.csv' + output_filename = '../voltage_lut.h' + generate_voltage_lut(csv_filename, output_filename) \ No newline at end of file From 6985b47232cb5dec11f1740c20ccb37b337c5622 Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 15 Apr 2026 07:13:40 -0500 Subject: [PATCH 16/27] forwarding works --- Firmware/Tasks/Src/FSMTask.c | 3 +- Firmware/Tasks/Src/InitTask.c | 79 +++++++++++++------------ Firmware/Tasks/Src/MotorTelemetryTask.c | 2 +- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 270c48e7..dfbe6466 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -190,7 +190,8 @@ static uint8_t apply_swoc_speed_limit(float speed_mph) { void Task_FSM(void *args __attribute__((unused))) { // TickType_t last = xTaskGetTickCount(); while (1) { - fsm_step(); + // fsm_step(); + MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 100); vTaskDelay(pdMS_TO_TICKS(250)); // vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); } diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index f932dc18..36fff0d2 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -1,6 +1,7 @@ #include "InitTask.h" #include "StatusLEDs.h" #include "Watchdogs.h" +#include "MotorTelemetryTask.h" StaticTask_t FaultHandler_Task_Buffer; StackType_t FaultHandler_Task_Stack[FAULT_HANDLER_TASK_STACK_SIZE]; @@ -46,25 +47,27 @@ void Task_Init() { // Required for VCU status testing faults_init(); - xTaskCreateStatic( - Task_FaultHandler, - "FaultHandler", - FAULT_HANDLER_TASK_STACK_SIZE, - NULL, - FAULT_HANDLER_THREAD_PRIO, - FaultHandler_Task_Stack, - &FaultHandler_Task_Buffer - ); - - precharge_task_handle = xTaskCreateStatic( - Task_Precharge, - "Precharge", - PRECHARGE_TASK_STACK_SIZE, - NULL, - PRECHARGE_THREAD_PRIO, - Precharge_Task_Stack, - &Precharge_Task_Buffer - ); + MotorTelemetryTask_Init(); + + // xTaskCreateStatic( + // Task_FaultHandler, + // "FaultHandler", + // FAULT_HANDLER_TASK_STACK_SIZE, + // NULL, + // FAULT_HANDLER_THREAD_PRIO, + // FaultHandler_Task_Stack, + // &FaultHandler_Task_Buffer + // ); + + // precharge_task_handle = xTaskCreateStatic( + // Task_Precharge, + // "Precharge", + // PRECHARGE_TASK_STACK_SIZE, + // NULL, + // PRECHARGE_THREAD_PRIO, + // Precharge_Task_Stack, + // &Precharge_Task_Buffer + // ); xTaskCreateStatic( Task_FSM, @@ -76,25 +79,25 @@ void Task_Init() { &FSM_Task_Buffer ); - xTaskCreateStatic( - Task_BroadcastVCUStatus, - "VCU Status Thread", - VCU_STATUS_TASK_STACK_SIZE, - NULL, - VCU_STATUS_THREAD_PRIO, - VCUStatus_Task_Stack, - &VCUStatus_Task_Buffer - ); - - xTaskCreateStatic( - Task_UpdateVCUInputs, - "Update FSM Inputs Thread", - UPDATE_VCU_INPUTS_STACK_SIZE, - NULL, - UPDATE_VCU_INPUTS_THREAD_PRIO, - UpdateVCUInputs_Task_Stack, - &UpdateVCUInputs_Task_Buffer - ); + // xTaskCreateStatic( + // Task_BroadcastVCUStatus, + // "VCU Status Thread", + // VCU_STATUS_TASK_STACK_SIZE, + // NULL, + // VCU_STATUS_THREAD_PRIO, + // VCUStatus_Task_Stack, + // &VCUStatus_Task_Buffer + // ); + + // xTaskCreateStatic( + // Task_UpdateVCUInputs, + // "Update FSM Inputs Thread", + // UPDATE_VCU_INPUTS_STACK_SIZE, + // NULL, + // UPDATE_VCU_INPUTS_THREAD_PRIO, + // UpdateVCUInputs_Task_Stack, + // &UpdateVCUInputs_Task_Buffer + // ); vTaskDelete(NULL); diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index 76227851..c6bf52af 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -41,7 +41,7 @@ void MotorTelemetryTask_Init(void) { void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, can_rx_payload_t recv_payload ){ // only forward motorCAN messages to CarCAN - if(motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance){ + if (motorfdcan != NULL && hfdcan->Instance == motorfdcan->Instance){ BaseType_t higherPriorityTaskWoken = pdFALSE; From 8182ab4f784ea0875c97315436830a8caa9645d5 Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 15 Apr 2026 07:57:29 -0500 Subject: [PATCH 17/27] somestuff --- Firmware/Drivers/Src/CANbus.c | 27 +++++++++++ Firmware/Tasks/Src/FSMTask.c | 26 +++++++--- Firmware/Tasks/Src/InitTask.c | 77 +++++++++++++++--------------- Firmware/Tasks/Src/VCUStatusTask.c | 8 ++-- 4 files changed, 89 insertions(+), 49 deletions(-) diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 58b0fba0..f2dfd176 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -166,6 +166,33 @@ can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t d return result; } +can_status_t MotorCAN_Send_Power_Cmd(float current, TickType_t delay){ + // printf("Motor CAN send drive cmd: %f vel, %f curr", velocity, current); + if (!isfinite(current)) return CAN_EMPTY; + if (g_data_read->motor_controls_src.Motor_Command_Source) return CAN_OK; + + FDCAN_TxHeaderTypeDef header = { + .Identifier = CAN_ID_MC_POWERCOMMAND, + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_POWERCOMMAND), + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, + .BitRateSwitch = FDCAN_BRS_OFF, + .FDFormat = FDCAN_CLASSIC_CAN, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, + .MessageMarker = 0, + }; + + uint8_t moco_power_tx_data[CAN_DLC_MC_POWERCOMMAND] = {0}; + + //first 4 bytes reserved + memcpy(&moco_power_tx_data[4], ¤t, sizeof(float)); + + can_status_t result = + can_fd_send(motorfdcan, &header, moco_power_tx_data, delay); + + return result; +} ///////// Carcan diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index dfbe6466..71e586ff 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -17,7 +17,7 @@ #include #include -#define MAX_VELOCITY 100.0f // meters per second +#define MAX_VELOCITY 12000 #define MAX_CURRENT_PERCENT 100.0f StaticEventGroup_t fsmInputBuffer = {0}; @@ -132,14 +132,26 @@ static void handle_state_regen(void) { MotorCAN_Send_Drive_Cmd(0.0f, 1.0f, 0); } static void handle_state_not_ready(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } static void handle_state_forward(void) { + // if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { + // // if we're actually going backwards, let off the pedal until we slow down + // MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + // warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); + // } else { + // warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); + // MotorCAN_Send_Drive_Cmd( + // MAX_VELOCITY, + // fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), + // apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), + // 0); + // } + if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { // if we're actually going backwards, let off the pedal until we slow down - MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + MotorCAN_Send_Power_Cmd(0.0f, 0); warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); - MotorCAN_Send_Drive_Cmd( - MAX_VELOCITY, + MotorCAN_Send_Power_Cmd( fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), 0); @@ -190,9 +202,9 @@ static uint8_t apply_swoc_speed_limit(float speed_mph) { void Task_FSM(void *args __attribute__((unused))) { // TickType_t last = xTaskGetTickCount(); while (1) { - // fsm_step(); - MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 100); - vTaskDelay(pdMS_TO_TICKS(250)); + fsm_step(); + // MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 100); + vTaskDelay(pdMS_TO_TICKS(90)); // vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); } } diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 36fff0d2..80380531 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -39,6 +39,7 @@ void Task_Init() { CarCAN_Init(); FSM_TaskInit(); + fsm_init(); watchdog_init(); watchdog_start_all(); @@ -49,25 +50,25 @@ void Task_Init() { MotorTelemetryTask_Init(); - // xTaskCreateStatic( - // Task_FaultHandler, - // "FaultHandler", - // FAULT_HANDLER_TASK_STACK_SIZE, - // NULL, - // FAULT_HANDLER_THREAD_PRIO, - // FaultHandler_Task_Stack, - // &FaultHandler_Task_Buffer - // ); - - // precharge_task_handle = xTaskCreateStatic( - // Task_Precharge, - // "Precharge", - // PRECHARGE_TASK_STACK_SIZE, - // NULL, - // PRECHARGE_THREAD_PRIO, - // Precharge_Task_Stack, - // &Precharge_Task_Buffer - // ); + xTaskCreateStatic( + Task_FaultHandler, + "FaultHandler", + FAULT_HANDLER_TASK_STACK_SIZE, + NULL, + FAULT_HANDLER_THREAD_PRIO, + FaultHandler_Task_Stack, + &FaultHandler_Task_Buffer + ); + + precharge_task_handle = xTaskCreateStatic( + Task_Precharge, + "Precharge", + PRECHARGE_TASK_STACK_SIZE, + NULL, + PRECHARGE_THREAD_PRIO, + Precharge_Task_Stack, + &Precharge_Task_Buffer + ); xTaskCreateStatic( Task_FSM, @@ -79,25 +80,25 @@ void Task_Init() { &FSM_Task_Buffer ); - // xTaskCreateStatic( - // Task_BroadcastVCUStatus, - // "VCU Status Thread", - // VCU_STATUS_TASK_STACK_SIZE, - // NULL, - // VCU_STATUS_THREAD_PRIO, - // VCUStatus_Task_Stack, - // &VCUStatus_Task_Buffer - // ); - - // xTaskCreateStatic( - // Task_UpdateVCUInputs, - // "Update FSM Inputs Thread", - // UPDATE_VCU_INPUTS_STACK_SIZE, - // NULL, - // UPDATE_VCU_INPUTS_THREAD_PRIO, - // UpdateVCUInputs_Task_Stack, - // &UpdateVCUInputs_Task_Buffer - // ); + xTaskCreateStatic( + Task_BroadcastVCUStatus, + "VCU Status Thread", + VCU_STATUS_TASK_STACK_SIZE, + NULL, + VCU_STATUS_THREAD_PRIO, + VCUStatus_Task_Stack, + &VCUStatus_Task_Buffer + ); + + xTaskCreateStatic( + Task_UpdateVCUInputs, + "Update FSM Inputs Thread", + UPDATE_VCU_INPUTS_STACK_SIZE, + NULL, + UPDATE_VCU_INPUTS_THREAD_PRIO, + UpdateVCUInputs_Task_Stack, + &UpdateVCUInputs_Task_Buffer + ); vTaskDelete(NULL); diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 14f99236..309efca7 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -33,10 +33,10 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { bool pedals_fault = ((bool)g_data_read->accel_brake.AccelPedal_Main_Fault) || ((bool)g_data_read->accel_brake.AccelPedal_Redundant_Fault) || ((bool)g_data_read->accel_brake.BrakePedal_Main_Fault) || - ((bool)g_data_read->accel_brake.BrakePedal_Redundant_Fault) || - (fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - - g_data_read->accel_brake.AccelPedal_Redundant_Pos) > - ACCEPTABLE_PEDAL_DEVIATION); + ((bool)g_data_read->accel_brake.BrakePedal_Redundant_Fault); //|| + // (fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - + // g_data_read->accel_brake.AccelPedal_Redundant_Pos) < + // ACCEPTABLE_PEDAL_DEVIATION); bool steering_fault = g_data_read->lws.LWS_Fault; buf[1] = (pedals_wdog) | (bps_wdog << 1) | (steering_wdog << 2) | (bps_fault << 3) | From 9d9f0399c1d080073dd76fe7c916cf409ff6e635 Mon Sep 17 00:00:00 2001 From: Lakshay983 <56173382+Lakshay983@users.noreply.github.com> Date: Tue, 21 Apr 2026 01:41:14 -0500 Subject: [PATCH 18/27] mirror send drive on carcan --- Firmware/Drivers/Inc/CANbus.h | 5 ++ Firmware/Drivers/Src/CANbus.c | 65 +++++++++++++++++++------ Firmware/Tasks/Src/FSMTask.c | 61 +++++++++++------------ Firmware/Tasks/Src/MotorTelemetryTask.c | 12 +++-- 4 files changed, 93 insertions(+), 50 deletions(-) diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index fc14a80e..05c7ae6c 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -20,6 +20,7 @@ can_status_t MotorCAN_Recv_Velocity(mc_velocitymeasurement_t *out, TickType_t de can_status_t MotorCAN_Recv_Control_Src(set_motor_cmd_src_t *out, TickType_t delay); can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay); +can_status_t MotorCAN_Send_Power_Cmd(float current, TickType_t delay); can_status_t CarCAN_Init(void); can_status_t CarCAN_Send(FDCAN_TxHeaderTypeDef *header, uint8_t data[], TickType_t delay_ticks); @@ -33,6 +34,10 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t delay); can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, TickType_t delay); +can_status_t CarCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay); + +can_status_t CAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay); + /* HAL MSP hooks implemented in CANbus.c */ void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *fdcanHandle); diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index f2dfd176..4f906aea 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -137,31 +137,66 @@ can_status_t MotorCAN_Recv_Control_Src(set_motor_cmd_src_t *out, TickType_t dela return result; } +static void Pack_Drive_Cmd(FDCAN_TxHeaderTypeDef *header, uint8_t data[], float velocity, float current){ + + header->Identifier = CAN_ID_MC_DRIVECOMMAND; + header->IdType = FDCAN_STANDARD_ID, + header->TxFrameType = FDCAN_DATA_FRAME, + header->DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), + header->ErrorStateIndicator = FDCAN_ESI_ACTIVE, + header->BitRateSwitch = FDCAN_BRS_OFF, + header->FDFormat = FDCAN_CLASSIC_CAN, + header->TxEventFifoControl = FDCAN_NO_TX_EVENTS, + header->MessageMarker = 0, + + memcpy(&data[0], &velocity, sizeof(float)); + memcpy(&data[4], ¤t, sizeof(float)); +} + can_status_t MotorCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay) { // printf("Motor CAN send drive cmd: %f vel, %f curr", velocity, current); if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; if (g_data_read->motor_controls_src.Motor_Command_Source) return CAN_OK; - FDCAN_TxHeaderTypeDef header = { - .Identifier = CAN_ID_MC_DRIVECOMMAND, - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .DataLength = FDCAN_DLC_BYTES(CAN_DLC_MC_DRIVECOMMAND), - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, - .BitRateSwitch = FDCAN_BRS_OFF, - .FDFormat = FDCAN_CLASSIC_CAN, - .TxEventFifoControl = FDCAN_NO_TX_EVENTS, - .MessageMarker = 0, - }; + uint8_t moco_drive_tx_data[CAN_DLC_MC_DRIVECOMMAND] = {0}; + FDCAN_TxHeaderTypeDef header; + + Pack_Drive_Cmd(&header, moco_drive_tx_data, velocity, current); + + can_status_t result = can_fd_send(motorfdcan, &header, moco_drive_tx_data, delay); + + return result; +} + +can_status_t CarCAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay) { + if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; + if (g_data_read->motor_controls_src.Motor_Command_Source) return CAN_OK; uint8_t moco_drive_tx_data[CAN_DLC_MC_DRIVECOMMAND] = {0}; + FDCAN_TxHeaderTypeDef header; + + Pack_Drive_Cmd(&header, moco_drive_tx_data, velocity, current); - memcpy(&moco_drive_tx_data[0], &velocity, sizeof(float)); - memcpy(&moco_drive_tx_data[4], ¤t, sizeof(float)); + can_status_t result = can_fd_send(carfdcan, &header, moco_drive_tx_data, delay); + - can_status_t result = - can_fd_send(motorfdcan, &header, moco_drive_tx_data, delay); + return result; +} + +can_status_t CAN_Send_Drive_Cmd(float velocity, float current, TickType_t delay) { + // printf("Motor CAN send drive cmd: %f vel, %f curr", velocity, current); + if (!isfinite(velocity) || !isfinite(current)) return CAN_EMPTY; + if (g_data_read->motor_controls_src.Motor_Command_Source) return CAN_OK; + + uint8_t moco_drive_tx_data[CAN_DLC_MC_DRIVECOMMAND] = {0}; + FDCAN_TxHeaderTypeDef header; + + Pack_Drive_Cmd(&header, moco_drive_tx_data, velocity, current); + + can_status_t result = can_fd_send(carfdcan, &header, moco_drive_tx_data, delay); + + result = can_fd_send(motorfdcan, &header, moco_drive_tx_data, delay); return result; } diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 71e586ff..56463108 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -126,55 +126,56 @@ float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_ //// state handlers static void handle_state_init(void) { current_state = FSM[CAR_NOT_READY]; } -static void handle_state_neutral(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } -static void handle_state_disabled(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } -static void handle_state_regen(void) { MotorCAN_Send_Drive_Cmd(0.0f, 1.0f, 0); } -static void handle_state_not_ready(void) { MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } +static void handle_state_neutral(void) { CAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } +static void handle_state_disabled(void) { CAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } +static void handle_state_regen(void) { CAN_Send_Drive_Cmd(0.0f, 1.0f, 0); } +static void handle_state_not_ready(void) { CAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } static void handle_state_forward(void) { - // if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { - // // if we're actually going backwards, let off the pedal until we slow down - // MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); - // warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); - // } else { - // warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); - // MotorCAN_Send_Drive_Cmd( - // MAX_VELOCITY, - // fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - // apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), - // 0); - // } - + float velocitySetpoint = 0.0f; + float currentSetpoint = 0.0f; if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { // if we're actually going backwards, let off the pedal until we slow down - MotorCAN_Send_Power_Cmd(0.0f, 0); + velocitySetpoint = 0.0f; + currentSetpoint = 0.0f; warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); - MotorCAN_Send_Power_Cmd( - fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), - 0); + velocitySetpoint = MAX_VELOCITY; + currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), + apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)); } + + printf("Forwards Drive cmd: %f vel, %f curr", velocitySetpoint, currentSetpoint); + + CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); + } static void handle_state_reverse(void) { + + float velocitySetpoint = 0.0f; + float currentSetpoint = 0.0f; + if (g_data_read->motor_velocity.MC_VehicleVelocity > 0.5f) { // if we're actually going forwards, let off the pedal until we slow down - MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 0); + velocitySetpoint = 0.0f; + currentSetpoint = 0.0f; warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { - MotorCAN_Send_Drive_Cmd( - -MAX_VELOCITY, - fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), - 0); + velocitySetpoint = -MAX_VELOCITY; + currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)); } + + CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); + + printf("Backwards Drive cmd: %f vel, %f curr", velocitySetpoint, currentSetpoint); + } static void handle_state_cruise(void) { float velocity = rollover_limit_active ? 0.0f : MAX_VELOCITY; - MotorCAN_Send_Drive_Cmd( + CAN_Send_Drive_Cmd( velocity, fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), @@ -203,7 +204,7 @@ void Task_FSM(void *args __attribute__((unused))) { // TickType_t last = xTaskGetTickCount(); while (1) { fsm_step(); - // MotorCAN_Send_Drive_Cmd(0.0f, 0.0f, 100); + // CAN_Send_Drive_Cmd(0.0f, 0.0f, 100); vTaskDelay(pdMS_TO_TICKS(90)); // vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); } diff --git a/Firmware/Tasks/Src/MotorTelemetryTask.c b/Firmware/Tasks/Src/MotorTelemetryTask.c index c6bf52af..408b6a61 100644 --- a/Firmware/Tasks/Src/MotorTelemetryTask.c +++ b/Firmware/Tasks/Src/MotorTelemetryTask.c @@ -45,11 +45,13 @@ void can_fd_rx_callback_hook(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs, c BaseType_t higherPriorityTaskWoken = pdFALSE; - xQueueSendFromISR( - motorTelemetryQueue, - &recv_payload, - &higherPriorityTaskWoken - ); + if (motorTelemetryQueue != NULL) { + xQueueSendFromISR( + motorTelemetryQueue, + &recv_payload, + &higherPriorityTaskWoken + ); + } // don't yield at the end of this since the rest of the ISR needs to run From 74d4bbcc6fd4b639c46c8fd1e6d32a900259f1e6 Mon Sep 17 00:00:00 2001 From: Ravi Shah Date: Wed, 22 Apr 2026 01:30:55 -0500 Subject: [PATCH 19/27] fix oopsie --- Firmware/Drivers/Src/CANbus.c | 4 ++-- Firmware/Tasks/Inc/InitTask.h | 2 +- Firmware/Tasks/Src/FSMTask.c | 10 +++++----- Firmware/Tasks/Src/PrechargeTask.c | 12 ++++++------ Firmware/Tasks/Src/UpdateVCUInputsTask.c | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index 4f906aea..d20b209f 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -421,7 +421,7 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, TickType_t delay) { - printf("Car CAN send prech voltages: %lu motor_mv, %lu batt_mv\n\r", motor_mv, battery_mv); + // printf("Car CAN send prech voltages: %lu motor_mv, %lu batt_mv\n\r", motor_mv, battery_mv); FDCAN_TxHeaderTypeDef header = { .Identifier = CAN_ID_VCU_PRECHARGE_VOLTAGES, @@ -564,4 +564,4 @@ void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *fdcanHandle) { /* FDCAN3 interrupt Deinit */ HAL_NVIC_DisableIRQ(FDCAN3_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN3_IT1_IRQn); -} \ No newline at end of file +} diff --git a/Firmware/Tasks/Inc/InitTask.h b/Firmware/Tasks/Inc/InitTask.h index c4e77daf..ba40bf56 100644 --- a/Firmware/Tasks/Inc/InitTask.h +++ b/Firmware/Tasks/Inc/InitTask.h @@ -57,4 +57,4 @@ extern TaskHandle_t precharge_task_handle; -void Task_Init(); \ No newline at end of file +void Task_Init(); diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 56463108..3f8b562b 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -62,7 +62,7 @@ void fsm_init(void) { void fsm_step(void) { fsm_inputs = xEventGroupGetBits(fsmInputGroup); current_state = FSM[current_state.NextStates[fsm_inputs]]; - printf("FSM step: %X inputs, %d curr_state\n\r", fsm_inputs, current_state.stateName); + // printf("FSM step: %X inputs, %d curr_state\n\r", fsm_inputs, current_state.stateName); if (current_state.stateHandler) current_state.stateHandler(); } @@ -143,10 +143,10 @@ static void handle_state_forward(void) { warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); velocitySetpoint = MAX_VELOCITY; currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)); + apply_rollover_limit(((float)g_data_read->accel_brake.AccelPedal_Main_Pos)/100.0f)); } - printf("Forwards Drive cmd: %f vel, %f curr", velocitySetpoint, currentSetpoint); + printf("Forwards Drive cmd: %f vel, %f curr\r\n", velocitySetpoint, currentSetpoint); CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); @@ -164,7 +164,7 @@ static void handle_state_reverse(void) { warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { velocitySetpoint = -MAX_VELOCITY; - currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)); + currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), ((float)apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos))/100.0f); } CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); @@ -178,7 +178,7 @@ static void handle_state_cruise(void) { CAN_Send_Drive_Cmd( velocity, fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos)), + apply_rollover_limit(((float)g_data_read->accel_brake.AccelPedal_Main_Pos))/100.0f), 0); } diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index b2b01e21..bdef6f1e 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -106,7 +106,7 @@ void Task_Precharge() { can_send_errors = 0; } - printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); + // printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); PT_check_ign(); @@ -119,12 +119,12 @@ void Task_Precharge() { case PRECHARGE_STATE_WAITING: // Wait for ignition on message from driver input task, // then move to initial precharge state - printf("Precharge State: Waiting for Ignition\r\n"); + // printf("Precharge State: Waiting for Ignition\r\n"); break; // Startup state: Closes main contactor and moves to precharging state case PRECHARGE_STATE_INITIAL: - printf("Precharge State: Initial\r\n"); + // printf("Precharge State: Initial\r\n"); // dont attempt to close contactors before bps ready if (!g_data_read->bps_status.HV_Plus_Contactor_State || @@ -158,7 +158,7 @@ void Task_Precharge() { // Check how long we've been precharging for, fault if not precharged after // PRECHARGE_TIMEOUT_MS const TickType_t timeout_curr_tick = xTaskGetTickCount(); - printf("Precharge State: Precharging\r\n"); + // printf("Precharge State: Precharging\r\n"); // Faults if precharging takes too long if ((timeout_curr_tick - timeout_start_tick) > @@ -204,7 +204,7 @@ void Task_Precharge() { if (printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER) { // prints battery and motor voltage - printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); + // printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); // prints current precharge state PT_print_state(curr_state); @@ -230,4 +230,4 @@ void Task_Precharge() { // LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(PRECHARGE_TASK_DELAY_MS)); } -} \ No newline at end of file +} diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index a3cedc16..b3abcf0f 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -98,7 +98,7 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { TickType_t last = xTaskGetTickCount(); while (1) { - printf("Task_UpdateVCUInputs: %ld", last); + // printf("Task_UpdateVCUInputs: %ld", last); // update from can VCUDataIn_t *volatile update = g_data_write; if (MotorCAN_Recv_Status(&update->motor_status, 0) == CAN_OK) { From b3d6507c15d569e6e77c3d3f96b5ec2e14128705 Mon Sep 17 00:00:00 2001 From: Ravi Shah Date: Wed, 22 Apr 2026 02:23:12 -0500 Subject: [PATCH 20/27] add deadzone --- Firmware/Tasks/Src/FSMTask.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 3f8b562b..c1b7f353 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -18,7 +18,9 @@ #include #define MAX_VELOCITY 12000 -#define MAX_CURRENT_PERCENT 100.0f +#define MAX_CURRENT_PERCENT 1.0f + +#define ACCEL_DEADZONE_MIN 5u // Minimum 5% pedal pressed to register accel input, prevents ghost inputs :P StaticEventGroup_t fsmInputBuffer = {0}; EventGroupHandle_t fsmInputGroup = {0}; @@ -143,7 +145,7 @@ static void handle_state_forward(void) { warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); velocitySetpoint = MAX_VELOCITY; currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - apply_rollover_limit(((float)g_data_read->accel_brake.AccelPedal_Main_Pos)/100.0f)); + apply_rollover_limit(((float)((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0))/100.0f)); } printf("Forwards Drive cmd: %f vel, %f curr\r\n", velocitySetpoint, currentSetpoint); @@ -164,7 +166,7 @@ static void handle_state_reverse(void) { warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { velocitySetpoint = -MAX_VELOCITY; - currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), ((float)apply_rollover_limit(g_data_read->accel_brake.AccelPedal_Main_Pos))/100.0f); + currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), ((float)apply_rollover_limit(((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0)))/100.0f); } CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); From 0d9c562d0f46aabf95ad720af03631f18cf20d67 Mon Sep 17 00:00:00 2001 From: Ravi Shah Date: Thu, 23 Apr 2026 01:50:18 -0500 Subject: [PATCH 21/27] convert m/s to mph for swoc thresh --- Firmware/Tasks/Src/FSMTask.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index c1b7f353..6ff9819b 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -21,6 +21,7 @@ #define MAX_CURRENT_PERCENT 1.0f #define ACCEL_DEADZONE_MIN 5u // Minimum 5% pedal pressed to register accel input, prevents ghost inputs :P +#define METERS_SEC_TO_MPH 2.237 StaticEventGroup_t fsmInputBuffer = {0}; EventGroupHandle_t fsmInputGroup = {0}; @@ -144,7 +145,7 @@ static void handle_state_forward(void) { } else { warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); velocitySetpoint = MAX_VELOCITY; - currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), + currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity * METERS_SEC_TO_MPH), apply_rollover_limit(((float)((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0))/100.0f)); } @@ -166,7 +167,7 @@ static void handle_state_reverse(void) { warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); } else { velocitySetpoint = -MAX_VELOCITY; - currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), ((float)apply_rollover_limit(((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0)))/100.0f); + currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity * METERS_SEC_TO_MPH), ((float)apply_rollover_limit(((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0)))/100.0f); } CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); From 2f77ad9d8c4e0e9945533b630551164fd122f0ad Mon Sep 17 00:00:00 2001 From: Lakshay983 <56173382+Lakshay983@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:02:14 -0500 Subject: [PATCH 22/27] add release artifact workflow --- .github/workflows/release_artifacts.yml | 40 +++++++++++++++++++++++++ Firmware/Embedded-Sharepoint | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release_artifacts.yml diff --git a/.github/workflows/release_artifacts.yml b/.github/workflows/release_artifacts.yml new file mode 100644 index 00000000..10d9875e --- /dev/null +++ b/.github/workflows/release_artifacts.yml @@ -0,0 +1,40 @@ +name: Include Submodules in Release + +on: + release: + types: [published] + +jobs: + flatten-release: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + fetch-depth: 0 + + - name: Remove submodule metadata + run: | + git submodule foreach --quiet ' + echo "Flattening $name at $path..." + git rm --cached -r "$path" || true + rm -rf ".git/modules/$path" + ' + rm -f .gitmodules + + - name: Create release zip + run: | + REPO_NAME=${{ github.event.repository.name }} + TAG_NAME=${{ github.event.release.tag_name }} + ZIP_NAME="${REPO_NAME}-${TAG_NAME}.zip" + echo "Creating zip: $ZIP_NAME" + zip -r "$ZIP_NAME" . -x ".git/*" -x ".github/*" + echo "ZIP created: $ZIP_NAME" + + - name: Upload zip to release + uses: softprops/action-gh-release@v2 + with: + files: "${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.zip" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index 260c8f94..a1eee6d8 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 260c8f9426f3be10e58db60574779992d7b38411 +Subproject commit a1eee6d814af8ab0017646ac7294db12d3ca62a5 From 06655b606bfab2b82b08125f9736854567d4ae0a Mon Sep 17 00:00:00 2001 From: Akshay G Date: Tue, 19 May 2026 20:59:12 -0500 Subject: [PATCH 23/27] some bs --- Firmware/Drivers/Inc/CANbus.h | 2 + Firmware/Drivers/Inc/Watchdogs.h | 14 +- Firmware/Drivers/Src/CANbus.c | 40 ++++ Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Inc/FSMTask.h | 2 +- Firmware/Tasks/Inc/UpdateVCUInputsTask.h | 6 +- Firmware/Tasks/Inc/fsm_table_dnr.h | 64 +++--- Firmware/Tasks/Src/FSMTask.c | 125 +++++++++--- Firmware/Tasks/Src/UpdateVCUInputsTask.c | 10 +- Firmware/config/Inc/BPSCAN_can_msgs.h | 24 +-- Firmware/config/Inc/CarCAN_can_msgs.h | 103 ++++++---- Firmware/config/Inc/ControlsCAN_can_msgs.h | 224 --------------------- Firmware/config/Inc/SteeringCAN_can_msgs.h | 2 +- Firmware/config/Inc/can3_recv_entries.h | 1 - Firmware/scripts/fsm_generator.py | 4 +- 15 files changed, 268 insertions(+), 355 deletions(-) delete mode 100644 Firmware/config/Inc/ControlsCAN_can_msgs.h diff --git a/Firmware/Drivers/Inc/CANbus.h b/Firmware/Drivers/Inc/CANbus.h index 05c7ae6c..52e6b796 100644 --- a/Firmware/Drivers/Inc/CANbus.h +++ b/Firmware/Drivers/Inc/CANbus.h @@ -31,6 +31,8 @@ can_status_t CarCAN_Recv_BPS_Status(bps_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_LWS(lws_standard_t *out, TickType_t delay); can_status_t CarCAN_Recv_Driver_Input(driver_input_status_t *out, TickType_t delay); can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay); +can_status_t CarCAN_Recv_Brake_Pressure1(brake_pressure_1_t *out, TickType_t delay); +can_status_t CarCAN_Recv_Brake_Pressure2(brake_pressure_2_t *out, TickType_t delay); can_status_t CarCAN_Recv_Controls_Status(controls_status_t *out, TickType_t delay); can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, TickType_t delay); diff --git a/Firmware/Drivers/Inc/Watchdogs.h b/Firmware/Drivers/Inc/Watchdogs.h index f049fed7..99304e95 100644 --- a/Firmware/Drivers/Inc/Watchdogs.h +++ b/Firmware/Drivers/Inc/Watchdogs.h @@ -29,12 +29,14 @@ * caused the fault. Just make sure to add the new fault IDs to FaultBits.h as well. */ #define WATCHDOG_LIST(X) \ - X(DRIVER_INPUT, "wd_driver_input", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(ACCEL_BRAKE, "wd_accel_brake", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(STEERING_ANGLE, "wd_steering_angle", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(CONTROLS_STATUS, "wd_controls_status", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(BPS_STATUS, "wd_bps_status", 2000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ - X(MOCO_STATUS, "wd_moco_status", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(DRIVER_INPUT, "wd_driver_input", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(ACCEL_BRAKE, "wd_accel_brake", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(BRAKE_PRESSURE_1, "wd_brake_pressure_1", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(BRAKE_PRESSURE_2, "wd_brake_pressure_2", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(STEERING_ANGLE, "wd_steering_angle", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(CONTROLS_STATUS, "wd_controls_status", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(BPS_STATUS, "wd_bps_status", 2000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ + X(MOCO_STATUS, "wd_moco_status", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) \ X(MOCO_VELOCITY, "wd_moco_velocity", 1000U, FAULT_ID_GENERIC_WATCHDOG_FAULT) typedef enum { diff --git a/Firmware/Drivers/Src/CANbus.c b/Firmware/Drivers/Src/CANbus.c index d20b209f..c550c832 100644 --- a/Firmware/Drivers/Src/CANbus.c +++ b/Firmware/Drivers/Src/CANbus.c @@ -418,6 +418,46 @@ can_status_t CarCAN_Recv_Pedals_Position(pedal_status_t *out, TickType_t delay) return result; } +can_status_t CarCAN_Recv_Brake_Pressure1(brake_pressure_1_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t brake_pressure1_rx_data[CAN_DLC_BRAKE_PRESSURE_1] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_BRAKE_PRESSURE_1, &header, brake_pressure1_rx_data, delay); + + if (result == CAN_OK) { + out->Brake_Pressure = (uint16_t)(brake_pressure1_rx_data[0] | ((uint16_t)brake_pressure1_rx_data[1] << 8)); + out->Brake_Pressure_ADC = (uint16_t)(brake_pressure1_rx_data[2] | ((uint16_t)brake_pressure1_rx_data[3] << 8)); + out->FrameID_Pedals = brake_pressure1_rx_data[4]; + + watchdog_received_can_message(WD_IDX_BRAKE_PRESSURE_1); + } + + return result; +} + +can_status_t CarCAN_Recv_Brake_Pressure2(brake_pressure_2_t *out, TickType_t delay) { + if (out == NULL) return CAN_EMPTY; + + FDCAN_RxHeaderTypeDef header = {0}; + uint8_t brake_pressure2_rx_data[CAN_DLC_BRAKE_PRESSURE_2] = {0}; + + can_status_t result = + can_fd_recv(carfdcan, CAN_ID_BRAKE_PRESSURE_2, &header, brake_pressure2_rx_data, delay); + + if (result == CAN_OK) { + out->Brake_Pressure = (uint16_t)(brake_pressure2_rx_data[0] | ((uint16_t)brake_pressure2_rx_data[1] << 8)); + out->Brake_Pressure_ADC = (uint16_t)(brake_pressure2_rx_data[2] | ((uint16_t)brake_pressure2_rx_data[3] << 8)); + out->FrameID_Pedals = brake_pressure2_rx_data[4]; + + watchdog_received_can_message(WD_IDX_BRAKE_PRESSURE_2); + } + + return result; +} + can_status_t CarCAN_Send_Precharge_Voltages(uint32_t motor_mv, uint32_t battery_mv, TickType_t delay) { diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index a1eee6d8..f8589743 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit a1eee6d814af8ab0017646ac7294db12d3ca62a5 +Subproject commit f8589743848bac04882e644baa0ae41296642027 diff --git a/Firmware/Tasks/Inc/FSMTask.h b/Firmware/Tasks/Inc/FSMTask.h index c184f914..89d83e8f 100644 --- a/Firmware/Tasks/Inc/FSMTask.h +++ b/Firmware/Tasks/Inc/FSMTask.h @@ -79,7 +79,7 @@ extern MocoState_t current_state; */ typedef struct { float speed_mph; - uint8_t max_percent; + float max_current; // 0.0 to 1.0 } swoc_threshold_t; diff --git a/Firmware/Tasks/Inc/UpdateVCUInputsTask.h b/Firmware/Tasks/Inc/UpdateVCUInputsTask.h index 502a6401..f70ab4f6 100644 --- a/Firmware/Tasks/Inc/UpdateVCUInputsTask.h +++ b/Firmware/Tasks/Inc/UpdateVCUInputsTask.h @@ -4,14 +4,16 @@ #include "CANbus.h" #include "FSMTask.h" -#define BRAKE_THRESH 42.0f // percent -#define BRAKE_THRESH_HYST 30.0f // percent +#define BRAKE_THRESH 0.0f // psi +#define BRAKE_THRESH_HYST 0.0f // psi #define ACCEPTABLE_PEDAL_DEVIATION 3 // percent typedef struct { driver_input_status_t driver_input; pedal_status_t accel_brake; + brake_pressure_1_t brake_pressure1; + brake_pressure_2_t brake_pressure2; lws_standard_t lws; controls_status_t controls_status; mc_status_t motor_status; diff --git a/Firmware/Tasks/Inc/fsm_table_dnr.h b/Firmware/Tasks/Inc/fsm_table_dnr.h index 2de8245a..a8b384a2 100644 --- a/Firmware/Tasks/Inc/fsm_table_dnr.h +++ b/Firmware/Tasks/Inc/fsm_table_dnr.h @@ -127,22 +127,22 @@ MocoState_t FSM[NUM_STATES] = { FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - FORWARD_DRIVE, NEUTRAL_DRIVE, FORWARD_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE }}, [NEUTRAL_DRIVE] = { NEUTRAL_DRIVE, NULL, { CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, @@ -259,22 +259,22 @@ MocoState_t FSM[NUM_STATES] = { NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, - NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, REVERSE_DRIVE, REVERSE_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, + NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE, NEUTRAL_DRIVE }}, [REGEN] = { REGEN, NULL, { CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, CAR_NOT_READY, diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 6ff9819b..5295dd85 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -20,8 +20,8 @@ #define MAX_VELOCITY 12000 #define MAX_CURRENT_PERCENT 1.0f -#define ACCEL_DEADZONE_MIN 5u // Minimum 5% pedal pressed to register accel input, prevents ghost inputs :P -#define METERS_SEC_TO_MPH 2.237 +#define ACCEL_DEADZONE_MIN 5u // Minimum 5% pedal pressed to register accel input, prevents ghost inputs :P +#define METERS_SEC_TO_MPH 2.23694f StaticEventGroup_t fsmInputBuffer = {0}; EventGroupHandle_t fsmInputGroup = {0}; @@ -40,8 +40,10 @@ static void handle_state_regen(void); static void handle_state_cruise(void); static void handle_state_disabled(void); +static void handle_drive_state(bool); + static float apply_rollover_limit(float requested_current); -static uint8_t apply_swoc_speed_limit(float speed_mph); +static float apply_swoc_speed_limit(float speed_mph); //must be called Before the FSM task gets called void FSM_TaskInit(){ @@ -111,7 +113,7 @@ static float apply_rollover_limit(float requested_current) { return 0.0f; } - warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); + warning_clear(WARNING_ID_TIPPING_LIMIT_ACTIVE); rollover_limit_active = false; return requested_current; } @@ -126,6 +128,14 @@ float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_ return ((float)(oi * or_) / (float)ir + (float)out_min) / 100.0f; } +static float get_accel_percent(uint8_t pedal_percent) { + if (pedal_percent <= ACCEL_DEADZONE_MIN) { + return 0.0f; + } + + return ((float)pedal_percent) / 100.0f; +} + //// state handlers static void handle_state_init(void) { current_state = FSM[CAR_NOT_READY]; } @@ -134,46 +144,100 @@ static void handle_state_disabled(void) { CAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } static void handle_state_regen(void) { CAN_Send_Drive_Cmd(0.0f, 1.0f, 0); } static void handle_state_not_ready(void) { CAN_Send_Drive_Cmd(0.0f, 0.0f, 0); } -static void handle_state_forward(void) { - float velocitySetpoint = 0.0f; - float currentSetpoint = 0.0f; - if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { - // if we're actually going backwards, let off the pedal until we slow down - velocitySetpoint = 0.0f; - currentSetpoint = 0.0f; - warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); - } else { - warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity * METERS_SEC_TO_MPH), - apply_rollover_limit(((float)((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0))/100.0f)); - } +// static void handle_state_forward(void) { +// float velocitySetpoint = 0.0f; +// float currentSetpoint = 0.0f; +// if (g_data_read->motor_velocity.MC_VehicleVelocity < -0.5f) { +// // if we're actually going backwards, let off the pedal until we slow down +// velocitySetpoint = 0.0f; +// currentSetpoint = 0.0f; +// warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); +// } else { +// warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); +// velocitySetpoint = MAX_VELOCITY; +// currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity * METERS_SEC_TO_MPH), +// apply_rollover_limit(((float)((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0))/100.0f)); +// } - printf("Forwards Drive cmd: %f vel, %f curr\r\n", velocitySetpoint, currentSetpoint); +// printf("Forwards Drive cmd: %f vel, %f curr\r\n", velocitySetpoint, currentSetpoint); - CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); +// CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); + +// } + +// static void handle_state_reverse(void) { + +// float velocitySetpoint = 0.0f; +// float currentSetpoint = 0.0f; +// if (g_data_read->motor_velocity.MC_VehicleVelocity > 0.5f) { +// // if we're actually going forwards, let off the pedal until we slow down +// velocitySetpoint = 0.0f; +// currentSetpoint = 0.0f; +// warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); +// } else { +// velocitySetpoint = -MAX_VELOCITY; +// currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity * METERS_SEC_TO_MPH), ((float)apply_rollover_limit(((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0)))/100.0f); +// } + +// CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); + +// printf("Backwards Drive cmd: %f vel, %f curr", velocitySetpoint, currentSetpoint); + +// } + +static void handle_state_forward(void) { + handle_drive_state(false); } static void handle_state_reverse(void) { + handle_drive_state(true); +} + +static void handle_drive_state(bool reverse) { float velocitySetpoint = 0.0f; float currentSetpoint = 0.0f; - if (g_data_read->motor_velocity.MC_VehicleVelocity > 0.5f) { - // if we're actually going forwards, let off the pedal until we slow down + const float vehicleVelocity = + g_data_read->motor_velocity.MC_VehicleVelocity; + + const bool wrongDirection = + (!reverse && vehicleVelocity < -0.5f) || + ( reverse && vehicleVelocity > 0.5f); + + if (wrongDirection) { + + // If we're moving opposite the requested direction, + // force zero torque until vehicle slows down velocitySetpoint = 0.0f; currentSetpoint = 0.0f; + warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); + } else { - velocitySetpoint = -MAX_VELOCITY; - currentSetpoint = fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity * METERS_SEC_TO_MPH), ((float)apply_rollover_limit(((g_data_read->accel_brake.AccelPedal_Main_Pos > ACCEL_DEADZONE_MIN) ? g_data_read->accel_brake.AccelPedal_Main_Pos : 0)))/100.0f); + + warning_clear(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); + + velocitySetpoint = reverse ? -MAX_VELOCITY : MAX_VELOCITY; + + currentSetpoint = fmin( + apply_swoc_speed_limit(vehicleVelocity * METERS_SEC_TO_MPH), + + apply_rollover_limit( + get_accel_percent( + g_data_read->accel_brake.AccelPedal_Main_Pos + ) + ) + ); } CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); - printf("Backwards Drive cmd: %f vel, %f curr", velocitySetpoint, currentSetpoint); - + printf("%s Drive cmd: %f vel, %f curr\r\n", + reverse ? "Reverse" : "Forward", + velocitySetpoint, + currentSetpoint); } static void handle_state_cruise(void) { @@ -185,15 +249,14 @@ static void handle_state_cruise(void) { 0); } -static const swoc_threshold_t SWOC_THRESHOLDS[] = {{10.0f, 80}, {17.0f, 75}, {20.0f, 70}, - {23.0f, 60}, {25.0f, 50}, {28.5f, 45}}; +static const swoc_threshold_t SWOC_THRESHOLDS[] = {{7.0f, 0.6}, {17.0f, 0.4}, {27.0f, 0.2}}; static const size_t NUM_SWOC_THRESHOLDS = (sizeof(SWOC_THRESHOLDS) / sizeof(SWOC_THRESHOLDS[0])); -static uint8_t apply_swoc_speed_limit(float speed_mph) { - uint8_t cap = MAX_CURRENT_PERCENT; // Default is 100% +static float apply_swoc_speed_limit(float speed_mph) { + float cap = MAX_CURRENT_PERCENT; // Default is 100% for (size_t i = 0; i < NUM_SWOC_THRESHOLDS; ++i) { if (speed_mph >= SWOC_THRESHOLDS[i].speed_mph) { - cap = SWOC_THRESHOLDS[i].max_percent; + cap = SWOC_THRESHOLDS[i].max_current; } } return cap; diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index b3abcf0f..037d08f1 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -35,7 +35,7 @@ static void rebuild_inputs(void) { if (contactor_get_sense(MOTOR_CONTACTOR) && contactor_get_sense(MOTOR_PRE_CONTACTOR)) s |= PRECHARGE_COMPLETE_BIT; - if (g_data_read->accel_brake.BrakePedal_Main_Pos >= brake_threshold) { + if (g_data_read->brake_pressure1.Brake_Pressure >= brake_threshold) { s |= BRAKE_BIT; brake_threshold = BRAKE_THRESH_HYST; } else { @@ -81,10 +81,8 @@ void UFI_throw_faults() { // Pedals faults if (g_data_read->accel_brake.AccelPedal_Main_Fault || g_data_read->accel_brake.AccelPedal_Redundant_Fault || - g_data_read->accel_brake.BrakePedal_Main_Fault || - g_data_read->accel_brake.BrakePedal_Redundant_Fault ) {//|| - // fabs(g_data_read->accel_brake.AccelPedal_Main_Pos - - // g_data_read->accel_brake.AccelPedal_Redundant_Pos) > ACCEPTABLE_PEDAL_DEVIATION) { + g_data_read->accel_brake.Brake_Pressure_1_Fault || + g_data_read->accel_brake.Brake_Pressure_2_Fault) { mask |= FAULT_BIT(FAULT_ID_PEDAL_BOARD_FAULT); } @@ -112,6 +110,8 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { CarCAN_Recv_BPS_Status(&update->bps_status, 0); CarCAN_Recv_Pedals_Position(&update->accel_brake, 0); + CarCAN_Recv_Brake_Pressure1(&update->brake_pressure1, 0); + CarCAN_Recv_Brake_Pressure2(&update->brake_pressure2, 0); CarCAN_Recv_Controls_Status(&update->controls_status, 0); CarCAN_Recv_Driver_Input(&update->driver_input, 0); CarCAN_Recv_LWS(&update->lws, 0); diff --git a/Firmware/config/Inc/BPSCAN_can_msgs.h b/Firmware/config/Inc/BPSCAN_can_msgs.h index adde79c9..b9cb13f2 100644 --- a/Firmware/config/Inc/BPSCAN_can_msgs.h +++ b/Firmware/config/Inc/BPSCAN_can_msgs.h @@ -21,7 +21,7 @@ #define CAN_ID_BPS_VT5_TEMPERATURE_ARR 0x15 #define CAN_ID_BPS_VT6_TEMPERATURE_ARR 0x16 #define CAN_ID_BPS_VT7_TEMPERATURE_ARR 0x17 -#define CAN_ID_BPS_PACK_CURRENT_RAWV 0x755 +#define CAN_ID_BPS_PACK_CURRENT_ADC 0x755 #define CAN_ID_BPS_BALANCE_DISCHARGE 0x7A0 /* ================= CAN Length Macros ================= */ @@ -43,7 +43,7 @@ #define CAN_DLC_BPS_VT5_TEMPERATURE_ARR 7 #define CAN_DLC_BPS_VT6_TEMPERATURE_ARR 7 #define CAN_DLC_BPS_VT7_TEMPERATURE_ARR 7 -#define CAN_DLC_BPS_PACK_CURRENT_RAWV 3 +#define CAN_DLC_BPS_PACK_CURRENT_ADC 3 #define CAN_DLC_BPS_BALANCE_DISCHARGE 1 @@ -285,62 +285,62 @@ typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt0_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt1_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt2_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt3_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt4_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt5_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt6_temperature_arr_t; typedef struct { uint8_t BPS_Tap_idx; int32_t BPS_Temperature_Tap_Data; uint8_t BPS_Temperature_Tap_Fault; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; } bps_vt7_temperature_arr_t; typedef struct { - uint16_t Main_Battery_Current_RawV; + uint16_t Main_Battery_Current_ADC; uint8_t FrameID_Amperes; -} bps_pack_current_rawv_t; +} bps_pack_current_adc_t; typedef struct { uint8_t BPS_Segment_idx; diff --git a/Firmware/config/Inc/CarCAN_can_msgs.h b/Firmware/config/Inc/CarCAN_can_msgs.h index f6ccbf55..be074e12 100644 --- a/Firmware/config/Inc/CarCAN_can_msgs.h +++ b/Firmware/config/Inc/CarCAN_can_msgs.h @@ -36,7 +36,8 @@ #define CAN_ID_MPPT_C_SETOUTPUTVOLTAGELIMIT 0x251 #define CAN_ID_MPPT_C_SETOUTPUTCURRENTLIMIT 0x252 #define CAN_ID_SUPP_BATTERY_STATUS 0x300 -#define CAN_ID_SUPP_CHARGING_STATUS 0x301 +#define CAN_ID_SUPP_CHARGER_STATUS 0x301 +#define CAN_ID_SUPP_VICOR_STATS 0x302 #define CAN_ID_PDU_STATUS_ARR 0x350 #define CAN_ID_PDU_SET_SWITCH_ARR 0x351 #define CAN_ID_PDU_SET_CURRENT_LIMIT_ARR 0x352 @@ -48,11 +49,11 @@ #define CAN_ID_BRAKE_PRESSURE_2 0x651 #define CAN_ID_DISPLAY_STATUS 0x680 #define CAN_ID_TELEMETRY_STATUS 0x700 -#define CAN_ID_BPS_TEMP_RAWV_AGGREGATE_ARR 0x750 -#define CAN_ID_SUPP_MEASUREMENTS_RAWV 0x751 -#define CAN_ID_SUPP_VICOR_MEASUREMENTS_RAWV 0x752 -#define CAN_ID_PEDAL_BRAKE_RAWV 0x753 -#define CAN_ID_PEDAL_ACCEL_RAWV 0x754 +#define CAN_ID_BPS_TEMP_ADC_AGGREGATE_ARR 0x750 +#define CAN_ID_SUPP_MEASUREMENTS_ADC 0x751 +#define CAN_ID_SUPP_VICOR_MEASUREMENTS_ADC 0x752 +#define CAN_ID_PEDAL_BRAKE_ADC 0x753 +#define CAN_ID_PEDAL_ACCEL_ADC 0x754 /* ================= CAN Length Macros ================= */ @@ -88,7 +89,8 @@ #define CAN_DLC_MPPT_C_SETOUTPUTVOLTAGELIMIT 2 #define CAN_DLC_MPPT_C_SETOUTPUTCURRENTLIMIT 2 #define CAN_DLC_SUPP_BATTERY_STATUS 6 -#define CAN_DLC_SUPP_CHARGING_STATUS 6 +#define CAN_DLC_SUPP_CHARGER_STATUS 6 +#define CAN_DLC_SUPP_VICOR_STATS 5 #define CAN_DLC_PDU_STATUS_ARR 5 #define CAN_DLC_PDU_SET_SWITCH_ARR 1 #define CAN_DLC_PDU_SET_CURRENT_LIMIT_ARR 3 @@ -100,11 +102,11 @@ #define CAN_DLC_BRAKE_PRESSURE_2 5 #define CAN_DLC_DISPLAY_STATUS 2 #define CAN_DLC_TELEMETRY_STATUS 8 -#define CAN_DLC_BPS_TEMP_RAWV_AGGREGATE_ARR 4 -#define CAN_DLC_SUPP_MEASUREMENTS_RAWV 5 -#define CAN_DLC_SUPP_VICOR_MEASUREMENTS_RAWV 5 -#define CAN_DLC_PEDAL_BRAKE_RAWV 5 -#define CAN_DLC_PEDAL_ACCEL_RAWV 5 +#define CAN_DLC_BPS_TEMP_ADC_AGGREGATE_ARR 4 +#define CAN_DLC_SUPP_MEASUREMENTS_ADC 5 +#define CAN_DLC_SUPP_VICOR_MEASUREMENTS_ADC 5 +#define CAN_DLC_PEDAL_BRAKE_ADC 5 +#define CAN_DLC_PEDAL_ACCEL_ADC 5 /* ================= Value Table Enums ================= */ @@ -739,11 +741,30 @@ typedef enum { } supp_battery_status_supplemental_battery_fault_e; typedef enum { - SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_CHARGE_DISABLED = 0, - SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_CHARGE_COMPLETE = 1, - SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_CHARGING_ = 2, - SUPP_CHARGING_STATUS_SUPPLEMENTAL_CHARGING_STATUS_FAULT = 3, -} supp_charging_status_supplemental_charging_status_e; + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_CHARGE_DISABLED = 0, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_TRICKLE_CHARGING = 1, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_PRECHARGE = 2, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_FAST_CHARGING = 3, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_TAPER = 4, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_ERROR = 5, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_TOPPING_OFF = 6, + SUPP_CHARGER_STATUS_SUPPLEMENTAL_CHARGER_STATUS_DONE = 7, +} supp_charger_status_supplemental_charger_status_e; + +typedef enum { + SUPP_CHARGER_STATUS_BQ25756E_ERROR_OK = 0, + SUPP_CHARGER_STATUS_BQ25756E_ERROR_I2C_ERROR = 1, + SUPP_CHARGER_STATUS_BQ25756E_ERROR_INPUT_UV = 2, + SUPP_CHARGER_STATUS_BQ25756E_ERROR_INPUT_OV = 3, + SUPP_CHARGER_STATUS_BQ25756E_ERROR_BATTERY_OC = 4, + SUPP_CHARGER_STATUS_BQ25756E_ERROR_BATTERY_OV = 5, + SUPP_CHARGER_STATUS_BQ25756E_ERROR_OVER_TEMPERATURE = 6, +} supp_charger_status_bq25756e_error_e; + +typedef enum { + SUPP_CHARGER_STATUS_BQ25756E_WATCHDOG_NOT_OK = 0, + SUPP_CHARGER_STATUS_BQ25756E_WATCHDOG_OK = 1, +} supp_charger_status_bq25756e_watchdog_e; typedef enum { PDU_STATUS_ARR_HSS_CHANNEL_IDX_VCU = 0, @@ -1144,11 +1165,19 @@ typedef struct { } supp_battery_status_t; typedef struct { - uint8_t Supplemental_Charging_Status; + uint8_t Supplemental_Charger_Status; + uint8_t BQ25756E_Error; + uint8_t BQ25756E_Watchdog; + int16_t Supplemental_Charge_Current; + uint16_t Supp_Charge_Current_Limit; + uint8_t FrameID_Supp_Charger; +} supp_charger_status_t; + +typedef struct { uint16_t Supplemental_Vicor_Voltage; int16_t Supplemental_Vicor_Current; - uint8_t FrameID_Supp_Vicor; -} supp_charging_status_t; + uint8_t FrameID_Supp_Charger; +} supp_vicor_stats_t; typedef struct { uint8_t HSS_Channel_idx; @@ -1200,13 +1229,13 @@ typedef struct { typedef struct { uint16_t Brake_Pressure; - uint16_t Brake_Pressure_RawV; + uint16_t Brake_Pressure_ADC; uint8_t FrameID_Pedals; } brake_pressure_1_t; typedef struct { uint16_t Brake_Pressure; - uint16_t Brake_Pressure_RawV; + uint16_t Brake_Pressure_ADC; uint8_t FrameID_Pedals; } brake_pressure_2_t; @@ -1222,31 +1251,31 @@ typedef struct { typedef struct { uint8_t BPS_Tap_idx; - uint16_t BPS_Temperature_Tap_RawV; + uint16_t BPS_Temperature_Tap_ADC; uint8_t FrameID_BPS_Temperature; -} bps_temp_rawv_aggregate_arr_t; +} bps_temp_adc_aggregate_arr_t; typedef struct { - uint16_t Supp_Battery_Voltage_RawV; - int16_t Supp_Battery_Current_RawV; + uint16_t Supp_Battery_Voltage_ADC; + int16_t Supp_Battery_Current_ADC; uint8_t FrameID_Supp; -} supp_measurements_rawv_t; +} supp_measurements_adc_t; typedef struct { - uint16_t Supp_Vicor_Voltage_RawV; - int16_t Supp_Vicor_Current_RawV; - uint8_t FrameID_Supp_Vicor; -} supp_vicor_measurements_rawv_t; + uint16_t Supp_Vicor_Voltage_ADC; + uint16_t Supp_Vicor_Current_ADC; + uint8_t FrameID_Supp_Charger; +} supp_vicor_measurements_adc_t; typedef struct { - uint16_t BrakePedal_Main_RawV; - uint16_t BrakePedal_Redundant_RawV; + uint16_t BrakePedal_Main_ADC; + uint16_t BrakePedal_Redundant_ADC; uint8_t FrameID_Pedals; -} pedal_brake_rawv_t; +} pedal_brake_adc_t; typedef struct { - uint16_t AccelPedal_Main_RawV; - uint16_t AccelPedal_Redundant_RawV; + uint16_t AccelPedal_Main_ADC; + uint16_t AccelPedal_Redundant_ADC; uint8_t FrameID_Pedals; -} pedal_accel_rawv_t; +} pedal_accel_adc_t; diff --git a/Firmware/config/Inc/ControlsCAN_can_msgs.h b/Firmware/config/Inc/ControlsCAN_can_msgs.h deleted file mode 100644 index ed3b852b..00000000 --- a/Firmware/config/Inc/ControlsCAN_can_msgs.h +++ /dev/null @@ -1,224 +0,0 @@ -#pragma once - -#include - -/* ================= CAN ID Macros ================= */ - -#define CAN_ID_LIGHTING_COMMAND 0x660 -#define CAN_ID_LIGHTING_BOARD0_STATUS 0x670 -#define CAN_ID_LIGHTING_BOARD1_STATUS 0x671 -#define CAN_ID_LIGHTING_BOARD2_STATUS 0x672 -#define CAN_ID_LIGHTING_BOARD3_STATUS 0x673 -#define CAN_ID_LIGHTING_BOARD4_STATUS 0x674 -#define CAN_ID_LIGHTING_BOARD5_STATUS 0x675 -#define CAN_ID_LIGHTING_BOARD6_STATUS 0x676 - -/* ================= CAN Length Macros ================= */ - -#define CAN_DLC_LIGHTING_COMMAND 1 -#define CAN_DLC_LIGHTING_BOARD0_STATUS 8 -#define CAN_DLC_LIGHTING_BOARD1_STATUS 8 -#define CAN_DLC_LIGHTING_BOARD2_STATUS 8 -#define CAN_DLC_LIGHTING_BOARD3_STATUS 8 -#define CAN_DLC_LIGHTING_BOARD4_STATUS 8 -#define CAN_DLC_LIGHTING_BOARD5_STATUS 8 -#define CAN_DLC_LIGHTING_BOARD6_STATUS 8 - - -/* ================= Value Table Enums ================= */ - -typedef enum { - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD0_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board0_status_lighting_board_faults_e; - -typedef enum { - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD1_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board1_status_lighting_board_faults_e; - -typedef enum { - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD2_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board2_status_lighting_board_faults_e; - -typedef enum { - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD3_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board3_status_lighting_board_faults_e; - -typedef enum { - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD4_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board4_status_lighting_board_faults_e; - -typedef enum { - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD5_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board5_status_lighting_board_faults_e; - -typedef enum { - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_CONTROLS_LEADER_WATCHDOG = 7, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED1_OVERCURRENT = 6, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED0_OVERCURRENT = 5, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_OVERCURRENT = 4, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED1_UNDERCURRENT = 3, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_LED0_UNDERCURRENT = 2, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_ADDR_LED_UNDERCURRENT = 1, - LIGHTING_BOARD6_STATUS_LIGHTING_BOARD_FAULTS_NONE = 0, -} lighting_board6_status_lighting_board_faults_e; - -/* ================= Message Structs ================= */ - -typedef struct { - uint8_t Headlights_On; - uint8_t Left_Indicator_On; - uint8_t Right_Indicator_On; - uint8_t Blinker_Sync; - uint8_t Brakelights_On; - uint8_t BPS_Strobe_On; - uint8_t Custom_Mode0_On; - uint8_t Custom_Mode1_On; -} lighting_command_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board0_status_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board1_status_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board2_status_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board3_status_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board4_status_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board5_status_t; - -typedef struct { - uint8_t Lighting_Board_Faults; - uint8_t Light_Headlight_Active; - uint8_t Light_LTurn_Active; - uint8_t Light_RTurn_Active; - uint8_t Light_BPS_Strobe_Active; - uint8_t Light_Brakelight_Active; - uint8_t Light_Custom0_Active; - uint8_t Light_Custom1_Active; - uint8_t Light_Custom2_Active; - uint16_t Addr_LED_Current; - uint16_t LED0_Current; - uint16_t LED1_Current; -} lighting_board6_status_t; - diff --git a/Firmware/config/Inc/SteeringCAN_can_msgs.h b/Firmware/config/Inc/SteeringCAN_can_msgs.h index 60d4c594..ab754e78 100644 --- a/Firmware/config/Inc/SteeringCAN_can_msgs.h +++ b/Firmware/config/Inc/SteeringCAN_can_msgs.h @@ -31,7 +31,7 @@ typedef enum { } lws_standard_lws_trimming_status_e; typedef enum { - LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0Â_ = 3, + LWS_CONFIG_LWS_CCW_SETS_THE_SIGNAL_LWS_ANGLE_TO_0Ã_Â_ = 3, LWS_CONFIG_LWS_CCW_RESETS_CALIBRATION_STATUS = 5, } lws_config_lws_ccw_e; diff --git a/Firmware/config/Inc/can3_recv_entries.h b/Firmware/config/Inc/can3_recv_entries.h index 5b66d561..3cfdf523 100644 --- a/Firmware/config/Inc/can3_recv_entries.h +++ b/Firmware/config/Inc/can3_recv_entries.h @@ -4,7 +4,6 @@ #include "CarCAN_can_msgs.h" #include "SteeringCAN_can_msgs.h" -#include "ControlsCAN_can_msgs.h" #include "BPSCAN_can_msgs.h" CAN_RECV_ENTRY(0x123, 8, true) // testing only, comment later diff --git a/Firmware/scripts/fsm_generator.py b/Firmware/scripts/fsm_generator.py index a7594a0e..77315ded 100644 --- a/Firmware/scripts/fsm_generator.py +++ b/Firmware/scripts/fsm_generator.py @@ -114,7 +114,7 @@ def transition_dnr(cur, bits): return NEUTRAL if cur == FWD_DRIVE: - if (bits & REV) or (bits & NEU): + if (bits & REV) or (bits & NEU) or (bits & BRK): return NEUTRAL return FWD_DRIVE @@ -125,7 +125,7 @@ def transition_dnr(cur, bits): return FWD_DRIVE if cur == REV_DRIVE: - if (bits & REV) and not (bits & FWD): + if (bits & REV) and not (bits & FWD) and not (bits & BRK): return REV_DRIVE return NEUTRAL From bd8a6796f7b2d3fe55e6e49f5760db40ead9deb1 Mon Sep 17 00:00:00 2001 From: Akshay G Date: Mon, 1 Jun 2026 17:36:40 -0500 Subject: [PATCH 24/27] parthiv shit?? --- Firmware/Tasks/Src/FSMTask.c | 44 +++++++++++++++++------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 5295dd85..755b00c4 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -43,7 +43,8 @@ static void handle_state_disabled(void); static void handle_drive_state(bool); static float apply_rollover_limit(float requested_current); -static float apply_swoc_speed_limit(float speed_mph); +static float swoc_max_current(float speed_mph); +static float get_drive_current(float speed_mph, uint8_t accel_percent_0_100); //must be called Before the FSM task gets called void FSM_TaskInit(){ @@ -113,7 +114,7 @@ static float apply_rollover_limit(float requested_current) { return 0.0f; } - warning_clear(WARNING_ID_TIPPING_LIMIT_ACTIVE); + warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); rollover_limit_active = false; return requested_current; } @@ -128,12 +129,13 @@ float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_ return ((float)(oi * or_) / (float)ir + (float)out_min) / 100.0f; } -static float get_accel_percent(uint8_t pedal_percent) { - if (pedal_percent <= ACCEL_DEADZONE_MIN) { - return 0.0f; - } - - return ((float)pedal_percent) / 100.0f; +static float get_drive_current(float speed_mph, uint8_t accel_percent_0_100) { + uint8_t pedal = accel_percent_0_100; + if (pedal <= ACCEL_DEADZONE_MIN) pedal = 0U; + float requested = (float)pedal / 100.0f; + float swoc_cap = swoc_max_current(speed_mph); + float after_rollover = apply_rollover_limit(requested); + return fminf(swoc_cap, after_rollover); } //// state handlers @@ -217,19 +219,12 @@ static void handle_drive_state(bool reverse) { } else { - warning_clear(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); + if (!reverse) warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); velocitySetpoint = reverse ? -MAX_VELOCITY : MAX_VELOCITY; - currentSetpoint = fmin( - apply_swoc_speed_limit(vehicleVelocity * METERS_SEC_TO_MPH), - - apply_rollover_limit( - get_accel_percent( - g_data_read->accel_brake.AccelPedal_Main_Pos - ) - ) - ); + float speed_mph = fabsf(vehicleVelocity) * METERS_SEC_TO_MPH; + currentSetpoint = get_drive_current(speed_mph, g_data_read->accel_brake.AccelPedal_Main_Pos); } CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); @@ -242,18 +237,21 @@ static void handle_drive_state(bool reverse) { static void handle_state_cruise(void) { float velocity = rollover_limit_active ? 0.0f : MAX_VELOCITY; + float speed_mph = fabsf(g_data_read->motor_velocity.MC_VehicleVelocity) * METERS_SEC_TO_MPH; CAN_Send_Drive_Cmd( velocity, - fmin(apply_swoc_speed_limit(g_data_read->motor_velocity.MC_VehicleVelocity), - apply_rollover_limit(((float)g_data_read->accel_brake.AccelPedal_Main_Pos))/100.0f), + get_drive_current(speed_mph, g_data_read->accel_brake.AccelPedal_Main_Pos), 0); } -static const swoc_threshold_t SWOC_THRESHOLDS[] = {{7.0f, 0.6}, {17.0f, 0.4}, {27.0f, 0.2}}; +static const swoc_threshold_t SWOC_THRESHOLDS[] = { + {10.0f, 0.80f}, {17.0f, 0.75f}, {20.0f, 0.70f}, + {23.0f, 0.60f}, {25.0f, 0.50f}, {28.5f, 0.45f} +}; static const size_t NUM_SWOC_THRESHOLDS = (sizeof(SWOC_THRESHOLDS) / sizeof(SWOC_THRESHOLDS[0])); -static float apply_swoc_speed_limit(float speed_mph) { - float cap = MAX_CURRENT_PERCENT; // Default is 100% +static float swoc_max_current(float speed_mph) { + float cap = MAX_CURRENT_PERCENT; for (size_t i = 0; i < NUM_SWOC_THRESHOLDS; ++i) { if (speed_mph >= SWOC_THRESHOLDS[i].speed_mph) { cap = SWOC_THRESHOLDS[i].max_current; From 549af025545a935a912c1546f30fceb1ba93484d Mon Sep 17 00:00:00 2001 From: Akshay G Date: Sat, 6 Jun 2026 21:53:00 -0500 Subject: [PATCH 25/27] some debug --- Firmware/Embedded-Sharepoint | 2 +- Firmware/Tasks/Src/FSMTask.c | 1 + Firmware/Tasks/Src/PrechargeTask.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Firmware/Embedded-Sharepoint b/Firmware/Embedded-Sharepoint index f8589743..489ea138 160000 --- a/Firmware/Embedded-Sharepoint +++ b/Firmware/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit f8589743848bac04882e644baa0ae41296642027 +Subproject commit 489ea138be7f6689cb8dc33dc3b8d95abdf291e5 diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 755b00c4..87cf077d 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -269,6 +269,7 @@ void Task_FSM(void *args __attribute__((unused))) { while (1) { fsm_step(); // CAN_Send_Drive_Cmd(0.0f, 0.0f, 100); + LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(90)); // vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); } diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index bdef6f1e..cb3fb603 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -204,7 +204,7 @@ void Task_Precharge() { if (printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER) { // prints battery and motor voltage - // printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); + printf("Motor: %ld mV | Battery: %ld mV\r\n", motor_voltage, battery_voltage); // prints current precharge state PT_print_state(curr_state); From d7d395760276e325a5716b028cea26ce0d87a063 Mon Sep 17 00:00:00 2001 From: "tonychenjs@gmail.com" Date: Sat, 6 Jun 2026 22:10:49 -0500 Subject: [PATCH 26/27] fixed printf --- Firmware/Tasks/Src/FSMTask.c | 1 + Firmware/Tasks/Src/PrechargeTask.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 87cf077d..4b0aa7ad 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -270,6 +270,7 @@ void Task_FSM(void *args __attribute__((unused))) { fsm_step(); // CAN_Send_Drive_Cmd(0.0f, 0.0f, 100); LED_toggle(HB); + // printf("FSM Task Running\r\n"); vTaskDelay(pdMS_TO_TICKS(90)); // vTaskDelayUntil(&last, pdMS_TO_TICKS(10)); } diff --git a/Firmware/Tasks/Src/PrechargeTask.c b/Firmware/Tasks/Src/PrechargeTask.c index cb3fb603..dd5ee2dd 100644 --- a/Firmware/Tasks/Src/PrechargeTask.c +++ b/Firmware/Tasks/Src/PrechargeTask.c @@ -1,7 +1,7 @@ #include "PrechargeTask.h" #include "UpdateVCUInputsTask.h" -#define PRECHARGE_PRINTF_DEBUG_PERIOD_MS 10000 +#define PRECHARGE_PRINTF_DEBUG_PERIOD_MS 2000 #define PRECHARGE_PRINTF_DEBUG_COUNTER (PRECHARGE_PRINTF_DEBUG_PERIOD_MS / PRECHARGE_TASK_DELAY_MS) uint32_t battery_voltage = 0; @@ -79,7 +79,7 @@ void Fault_Checker(uint32_t Motor_Voltage, uint32_t Battery_Voltage) { } static void PT_print_state(PrechargeState_e state) { - printf("Fault: %s\r\n", precharge_state_names[state]); + printf("Prech_state: %s\r\n", precharge_state_names[state]); } void Task_Precharge() { @@ -201,6 +201,7 @@ void Task_Precharge() { curr_state = g_precharge_state; taskEXIT_CRITICAL(); + printDebugCounter++; if (printDebugCounter >= PRECHARGE_PRINTF_DEBUG_COUNTER) { // prints battery and motor voltage From 9baaa97319e15494eac2215770b56c210a3ad7c6 Mon Sep 17 00:00:00 2001 From: Akshay G Date: Thu, 18 Jun 2026 19:38:54 -0500 Subject: [PATCH 27/27] debugging --- Firmware/Tasks/Inc/FSMTask.h | 1 - Firmware/Tasks/Src/FSMTask.c | 42 ++++++++++-------------- Firmware/Tasks/Src/FaultHandlerTask.c | 11 +++---- Firmware/Tasks/Src/InitTask.c | 1 - Firmware/Tasks/Src/UpdateVCUInputsTask.c | 4 +-- Firmware/Tasks/Src/VCUStatusTask.c | 2 +- 6 files changed, 25 insertions(+), 36 deletions(-) diff --git a/Firmware/Tasks/Inc/FSMTask.h b/Firmware/Tasks/Inc/FSMTask.h index 89d83e8f..99317c16 100644 --- a/Firmware/Tasks/Inc/FSMTask.h +++ b/Firmware/Tasks/Inc/FSMTask.h @@ -94,7 +94,6 @@ uint16_t fsm_get_inputs(void); bool fsm_is_over_rollover_speed(void); -void FSM_TaskInit(); void Task_FSM(void *args); float map_to_percent(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, diff --git a/Firmware/Tasks/Src/FSMTask.c b/Firmware/Tasks/Src/FSMTask.c index 4b0aa7ad..2c8470e6 100644 --- a/Firmware/Tasks/Src/FSMTask.c +++ b/Firmware/Tasks/Src/FSMTask.c @@ -46,11 +46,6 @@ static float apply_rollover_limit(float requested_current); static float swoc_max_current(float speed_mph); static float get_drive_current(float speed_mph, uint8_t accel_percent_0_100); -//must be called Before the FSM task gets called -void FSM_TaskInit(){ - fsmInputGroup = xEventGroupCreateStatic(&fsmInputBuffer); -} - void fsm_init(void) { FSM[STATE_INIT].stateHandler = handle_state_init; FSM[FORWARD_DRIVE].stateHandler = handle_state_forward; @@ -63,6 +58,8 @@ void fsm_init(void) { current_state = FSM[STATE_INIT]; current_state.stateHandler(); + + fsmInputGroup = xEventGroupCreateStatic(&fsmInputBuffer); } void fsm_step(void) { @@ -197,42 +194,37 @@ static void handle_state_reverse(void) { } static void handle_drive_state(bool reverse) { + float velocity_setpoint = 0.0f; + float current_setpoint = 0.0f; - float velocitySetpoint = 0.0f; - float currentSetpoint = 0.0f; - - const float vehicleVelocity = + const float vehicle_velocity = g_data_read->motor_velocity.MC_VehicleVelocity; - const bool wrongDirection = - (!reverse && vehicleVelocity < -0.5f) || - ( reverse && vehicleVelocity > 0.5f); - - if (wrongDirection) { + const bool is_wrong_direction = + (!reverse && vehicle_velocity < -0.5f) || + ( reverse && vehicle_velocity > 0.5f); + if (is_wrong_direction) { // If we're moving opposite the requested direction, // force zero torque until vehicle slows down - velocitySetpoint = 0.0f; - currentSetpoint = 0.0f; - + velocity_setpoint = 0.0f; + current_setpoint = 0.0f; warning_set(WARNING_ID_MOTOR_DIRECTION_CHANGE_LOCKOUT); - } else { - if (!reverse) warning_clear(WARNING_ID_REGEN_NOT_ALLOWED); - velocitySetpoint = reverse ? -MAX_VELOCITY : MAX_VELOCITY; + velocity_setpoint = reverse ? -MAX_VELOCITY : MAX_VELOCITY; - float speed_mph = fabsf(vehicleVelocity) * METERS_SEC_TO_MPH; - currentSetpoint = get_drive_current(speed_mph, g_data_read->accel_brake.AccelPedal_Main_Pos); + float speed_mph = fabsf(vehicle_velocity) * METERS_SEC_TO_MPH; + current_setpoint = get_drive_current(speed_mph, g_data_read->accel_brake.AccelPedal_Main_Pos); } - CAN_Send_Drive_Cmd(velocitySetpoint, currentSetpoint, 0); + CAN_Send_Drive_Cmd(velocity_setpoint, current_setpoint, 0); printf("%s Drive cmd: %f vel, %f curr\r\n", reverse ? "Reverse" : "Forward", - velocitySetpoint, - currentSetpoint); + velocity_setpoint, + current_setpoint); } static void handle_state_cruise(void) { diff --git a/Firmware/Tasks/Src/FaultHandlerTask.c b/Firmware/Tasks/Src/FaultHandlerTask.c index ca7d0c10..11bca983 100644 --- a/Firmware/Tasks/Src/FaultHandlerTask.c +++ b/Firmware/Tasks/Src/FaultHandlerTask.c @@ -94,20 +94,19 @@ void Task_FaultHandler(void *args __attribute__((unused))) { printf("Fault Handler triggered: 0x%02lX\r\n", bits); // Loop to display/handle fault until system reset - // uint32_t print_counter = 0; + uint32_t print_counter = 0; while (true) { - // print_counter++; - // if (print_counter >= FAULT_PRINTF_COUNTER) { + print_counter++; + if (print_counter >= FAULT_PRINTF_COUNTER) { for (int i = 0; i < FAULT_ID_COUNT; i++) { if (bits & FAULT_BIT(i)) { printf("Fault: %s\r\n", fault_names[i]); } } - // print_counter = 0; - // } + print_counter = 0; + } FHT_set_fault_leds(bits); - // LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(FAULT_LOOP_PERIOD_MS)); } } diff --git a/Firmware/Tasks/Src/InitTask.c b/Firmware/Tasks/Src/InitTask.c index 80380531..1e421b92 100644 --- a/Firmware/Tasks/Src/InitTask.c +++ b/Firmware/Tasks/Src/InitTask.c @@ -38,7 +38,6 @@ void Task_Init() { MotorCAN_Init(); CarCAN_Init(); - FSM_TaskInit(); fsm_init(); watchdog_init(); diff --git a/Firmware/Tasks/Src/UpdateVCUInputsTask.c b/Firmware/Tasks/Src/UpdateVCUInputsTask.c index 037d08f1..c1218e01 100644 --- a/Firmware/Tasks/Src/UpdateVCUInputsTask.c +++ b/Firmware/Tasks/Src/UpdateVCUInputsTask.c @@ -116,7 +116,7 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { CarCAN_Recv_Driver_Input(&update->driver_input, 0); CarCAN_Recv_LWS(&update->lws, 0); - // printf("Update VCU inputs: about to switch read and write ptrs"); + printf("Update VCU inputs: about to switch read and write ptrs\r\n"); VCUDataIn_t *volatile tmp; taskENTER_CRITICAL(); @@ -125,7 +125,7 @@ void Task_UpdateVCUInputs(void *args __attribute__((unused))) { g_data_write = tmp; taskEXIT_CRITICAL(); - // printf("Updated from CAN!"); + printf("Updated from CAN!\r\n"); memcpy(g_data_write, g_data_read, sizeof(VCUDataIn_t)); diff --git a/Firmware/Tasks/Src/VCUStatusTask.c b/Firmware/Tasks/Src/VCUStatusTask.c index 309efca7..787a2d2f 100644 --- a/Firmware/Tasks/Src/VCUStatusTask.c +++ b/Firmware/Tasks/Src/VCUStatusTask.c @@ -88,7 +88,7 @@ void Task_BroadcastVCUStatus(void *args __attribute__((unused))) { CarCAN_Send(&tx_header, buf, sizeof(buf)); - // LED_toggle(HB); + LED_toggle(HB); vTaskDelay(pdMS_TO_TICKS(800)); } } \ No newline at end of file