From 68848ab3f916a7a27822ad4d4726f87ee3b5dc96 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Wed, 24 Jun 2026 21:26:24 -0700 Subject: [PATCH 01/10] adc_1 --- src/VCF_Tasks.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/VCF_Tasks.cpp b/src/VCF_Tasks.cpp index 8782e58..6ef66c3 100644 --- a/src/VCF_Tasks.cpp +++ b/src/VCF_Tasks.cpp @@ -38,7 +38,7 @@ HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const H .brake_1 = static_cast(ADCInterfaceInstance::instance().brake_1().conversion), .brake_2 = static_cast(ADCInterfaceInstance::instance().brake_2().conversion) }); - + return HT_TASK::TaskResponse::YIELD; } @@ -282,7 +282,7 @@ HT_TASK::TaskResponse run_dash_GPIOs_task(const unsigned long& sys_micros, const { VCRInterfaceInstance::instance().disable_calibration_state(); } - + if (!current_state.data_btn_is_pressed) { VCRInterfaceInstance::instance().disable_steering_calibration_state(); @@ -326,7 +326,7 @@ namespace async_tasks void handle_async_recvs() { // ethernet, etc... - + handle_async_CAN_receive(); } @@ -372,7 +372,7 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: Serial.print(PedalsSystemInstance::instance().get_brake_params().max_pedal_1); Serial.print("\t"); Serial.print(PedalsSystemInstance::instance().get_brake_params().min_pedal_2); Serial.print("\t"); Serial.println(PedalsSystemInstance::instance().get_brake_params().max_pedal_2); - + /* Steering System Data */ Serial.println("Steering Sensor Data: "); Serial.print("analog adc: "); @@ -417,7 +417,7 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: Serial.println(SteeringSystemInstance::instance().get_steering_system_data().both_sensors_fail); Serial.print("interface_sensor_error: "); Serial.println(SteeringSystemInstance::instance().get_steering_system_data().interface_sensor_error); - + /* ADC Values */ Serial.println("\nADC Vals:"); // ADC 0 @@ -616,7 +616,7 @@ void setup_all_interfaces() { .digital_tolerance = VCFSystemConstants::DIGITAL_TOLERANCE, .max_dtheta_threshold = VCFSystemConstants::MAX_DTHETA_THRESHOLD, .error_between_sensors_tolerance = VCFSystemConstants::ERROR_BETWEEN_SENSORS_TOLERANCE - + }; steering_params.span_signal_analog = steering_params.max_steering_signal_analog - steering_params.min_steering_signal_analog; steering_params.analog_midpoint = (steering_params.max_steering_signal_analog + steering_params.min_steering_signal_analog) / 2; @@ -625,8 +625,8 @@ void setup_all_interfaces() { SteeringSystemInstance::create(steering_params); // NOLINT thinks steering params is not initialized // Create Digital Steering Sensor singleton - OrbisBRInstance::create(&Serial2); - + // OrbisBRInstance::create(&Serial2); + // Create dashboard singleton DashboardGPIOs_s dashboard_gpios = { .BRIGHTNESS_CONTROL_PIN = VCFInterfaceConstants::BRIGHTNESS_CONTROL_PIN, From 0d292c85280186c95dbfc2af0d09b415ccb91e39 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Wed, 24 Jun 2026 21:07:59 -0700 Subject: [PATCH 02/10] CAN interface rev1 --- lib/interfaces/include/NeopixelController.h | 6 +- lib/interfaces/include/VCFCANInterfaceImpl.h | 108 ++++++++++--------- lib/interfaces/src/NeopixelController.cpp | 18 ++-- lib/interfaces/src/VCFCANInterfaceImpl.cpp | 45 ++++---- src/VCF_Tasks.cpp | 10 +- 5 files changed, 100 insertions(+), 87 deletions(-) diff --git a/lib/interfaces/include/NeopixelController.h b/lib/interfaces/include/NeopixelController.h index ffcb3f9..a7e257a 100644 --- a/lib/interfaces/include/NeopixelController.h +++ b/lib/interfaces/include/NeopixelController.h @@ -71,15 +71,15 @@ class NeopixelController {}; NeopixelController() = delete; - + void init_neopixels(); void dim_neopixels(); void set_neopixel(uint16_t id, uint32_t c); - void refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces &interfaces); + void refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces_s &interfaces); void set_neopixel_color(LED_ID_e led, LED_color_e color); private: - + Adafruit_NeoPixel _neopixels; uint8_t _current_brightness; uint8_t _neopixel_count; diff --git a/lib/interfaces/include/VCFCANInterfaceImpl.h b/lib/interfaces/include/VCFCANInterfaceImpl.h index 2968a78..3a19714 100644 --- a/lib/interfaces/include/VCFCANInterfaceImpl.h +++ b/lib/interfaces/include/VCFCANInterfaceImpl.h @@ -1,71 +1,83 @@ #ifndef VCFCANINTERFACEIMPL_H #define VCFCANINTERFACEIMPL_H - -#include "FlexCAN_T4.h" - +/* ETL Library */ #include "etl/delegate.h" #include "etl/singleton.h" +/* External Includes */ +#include "FlexCAN_T4.h" #include "CANInterface.h" +#include "SharedFirmwareTypes.h" +#include "hytech.h" -#include "DashboardInterface.h" +/* Local Interface Includes */ #include "ACUInterface.h" -#include "VCRInterface.h" #include "BrakeRotorTemp.h" - -#include "SharedFirmwareTypes.h" - -#include "hytech.h" // generated CAN library +#include "DashboardInterface.h" +#include "VCRInterface.h" /* Globally accessible types */ -using CANRXBufferType = Circular_Buffer; -using CANTXBufferType = Circular_Buffer; - -// Definitions of VCF CAN bus types -using TelemCAN_t = FlexCAN_T4; -using FrontAuxCAN_t = FlexCAN_T4; +constexpr size_t CAN_MSG_SIZE = sizeof(CAN_message_t); +using CANRXBuffer_t = Circular_Buffer; +using CANTXBuffer_t = Circular_Buffer; + +template +using FlexCAN_t = FlexCAN_T4; + + +/** + * @brief This struct holds references to the interface objects that use decoded CAN messages. References only! + */ +struct CANInterfaces_s +{ + explicit CANInterfaces_s(ACUInterface &acu_int, BrakeRotorTemp &brake_rotor_temp_int, DashboardInterface &dash_int, VCRInterface &vcr_int) + : acu_interface(acu_int), + brake_rotor_temp_interface(brake_rotor_temp_int), + dash_interface(dash_int), + vcr_interface(vcr_int) + {} -/* Interfaces accessible to this one */ -struct CANInterfaces { - explicit CANInterfaces(DashboardInterface &dash_int, ACUInterface &acu_int, VCRInterface &vcr_int, BrakeRotorTemp &brake_rotor_temp_int) - : dash_interface(dash_int), - acu_interface(acu_int), - vcr_interface(vcr_int), - brake_rotor_temp_interface(brake_rotor_temp_int) {} - - DashboardInterface &dash_interface; ACUInterface &acu_interface; - VCRInterface &vcr_interface; BrakeRotorTemp &brake_rotor_temp_interface; + DashboardInterface &dash_interface; + VCRInterface &vcr_interface; }; -using CANInterfacesInstance = etl::singleton; - -struct VCFCANInterface { - VCFCANInterface(etl::delegate recv_switch_func) - : can_recv_switch(recv_switch_func) - {} - - TelemCAN_t TELEM_CAN; - - CANRXBufferType telem_can_rx_buffer; - CANTXBufferType telem_can_tx_buffer; +using CANInterfacesInstance = etl::singleton; + +/** + * @brief This struct holds the FlexCAN peripheral instances and their associated RX/TX ring buffers. + */ +struct VCFCANInterface +{ + explicit VCFCANInterface(etl::delegate recv_switch_func) + : can_recv_switch(recv_switch_func) + {} + + FlexCAN_t TELEM_CAN; + CANRXBuffer_t telem_can_rx_buffer; + CANTXBuffer_t telem_can_tx_buffer; + + FlexCAN_t FRONT_AUX_CAN; + CANRXBuffer_t front_aux_can_rx_buffer; + CANTXBuffer_t front_aux_can_tx_buffer; + + etl::delegate can_recv_switch; +}; +using VCFCANInterfaceInstance = etl::singleton; - FrontAuxCAN_t FRONT_AUX_CAN; +namespace VCFCANInterfaceImpl +{ + void on_telem_can_recv(const CAN_message_t &msg); - CANRXBufferType front_aux_can_rx_buffer; - CANTXBufferType front_aux_can_tx_buffer; + void on_front_aux_can_recv(const CAN_message_t &msg); - etl::delegate can_recv_switch; -}; -using VCFCANInterfaceInstance = etl::singleton; + /** + * @brief Routes a decoded message to the appropriate interface based on CANID + */ + void vcf_recv_switch(CANInterfaces_s &interfaces, const CAN_message_t &msg, uint32_t millis, CANInterfaceType_e interface_type); -namespace VCFCANInterfaceImpl { - void on_main_can_recv(const CAN_message_t &msg); - void on_faux_can_recv(const CAN_message_t &msg); - - void vcf_recv_switch(CANInterfaces &interfaces, const CAN_message_t &msg, unsigned long millis, CANInterfaceType_e interface_type); //vcf can receive - void send_all_CAN_msgs(CANTXBufferType &buffer, FlexCAN_T4_Base *can_interface); + void send_all_CAN_msgs(CANTXBuffer_t &buffer, FlexCAN_T4_Base *can_interface); } #endif // VCFCANINTERFACEIMPL_H diff --git a/lib/interfaces/src/NeopixelController.cpp b/lib/interfaces/src/NeopixelController.cpp index eb0e203..4afaa1d 100644 --- a/lib/interfaces/src/NeopixelController.cpp +++ b/lib/interfaces/src/NeopixelController.cpp @@ -4,14 +4,14 @@ void NeopixelController::init_neopixels() { _neopixels.begin(); _neopixels.setBrightness(_current_brightness); //set init color for every led - for (int i = 0; i < _neopixel_count; i++) + for (int i = 0; i < _neopixel_count; i++) { // BMS and IMD are off according to rules - if (i == LED_ID_e::BMS || i == LED_ID_e::IMD || i == LED_ID_e::BMS_WING || i == LED_ID_e::IMD_WING) + if (i == LED_ID_e::BMS || i == LED_ID_e::IMD || i == LED_ID_e::BMS_WING || i == LED_ID_e::IMD_WING) { _neopixels.setPixelColor(i, (uint32_t) LED_color_e::OFF); - } - else + } + else { _neopixels.setPixelColor(i, (uint32_t) LED_color_e::INIT_COLOR); } @@ -20,7 +20,7 @@ void NeopixelController::init_neopixels() { _neopixels.show(); } -void NeopixelController::dim_neopixels() +void NeopixelController::dim_neopixels() { _current_brightness -= STEP_BRIGHTNESS; // set current brightness to 0xFF (255) if less than min brightness - sid :) DO NOT CHANGE @@ -28,12 +28,12 @@ void NeopixelController::dim_neopixels() _neopixels.setBrightness(_current_brightness); } -void NeopixelController::set_neopixel(uint16_t id, uint32_t c) +void NeopixelController::set_neopixel(uint16_t id, uint32_t c) { _neopixels.setPixelColor(id, c); } -void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces &interfaces) +void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces_s &interfaces) { // If we are in pedals recalibration state, LIGHT UP DASHBOARD ALL RED. if (interfaces.vcr_interface.is_in_pedals_calibration_state() || interfaces.vcr_interface.is_in_steering_calibration_state()) { @@ -132,7 +132,7 @@ void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data } bool hv_present = interfaces.vcr_interface.get_dc_bus_voltage().voltage.FL > _hv_threshold_voltage || - interfaces.vcr_interface.get_dc_bus_voltage().voltage.FR > _hv_threshold_voltage || + interfaces.vcr_interface.get_dc_bus_voltage().voltage.FR > _hv_threshold_voltage || interfaces.vcr_interface.get_dc_bus_voltage().voltage.RL > _hv_threshold_voltage || interfaces.vcr_interface.get_dc_bus_voltage().voltage.RR > _hv_threshold_voltage; @@ -146,7 +146,7 @@ void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data set_neopixel_color(LED_ID_e::SHUTDOWN, LED_color_e::OFF); // Unused for now set_neopixel_color(LED_ID_e::IMD_WING, interfaces.dash_interface.imd_ok ? LED_color_e::GREEN : LED_color_e::RED); set_neopixel_color(LED_ID_e::BMS_WING, interfaces.dash_interface.bms_ok ? LED_color_e::GREEN : LED_color_e::RED); - + /* DRIVETRAIN LEDS */ set_neopixel_color(LED_ID_e::BRAKE, brake_light_color); set_neopixel_color(LED_ID_e::INVERTER_ERR, interfaces.vcr_interface.get_inverter_error() ? LED_color_e::RED : LED_color_e::GREEN); diff --git a/lib/interfaces/src/VCFCANInterfaceImpl.cpp b/lib/interfaces/src/VCFCANInterfaceImpl.cpp index 48481fd..3c5727a 100644 --- a/lib/interfaces/src/VCFCANInterfaceImpl.cpp +++ b/lib/interfaces/src/VCFCANInterfaceImpl.cpp @@ -1,41 +1,41 @@ #include "VCFCANInterfaceImpl.h" -#include "BuzzerController.h" -namespace VCFCANInterfaceImpl { - void on_main_can_recv(const CAN_message_t &msg) +namespace VCFCANInterfaceImpl +{ + void on_telem_can_recv(const CAN_message_t &msg) { - uint8_t buf[sizeof(CAN_message_t)]; - memmove(buf, &msg, sizeof(msg)); // NOLINT (memory operations are fine) - VCFCANInterfaceInstance::instance().telem_can_rx_buffer.push_back(buf, sizeof(CAN_message_t)); + std::array buf; + memmove(buf.data(), &msg, CAN_MSG_SIZE); + VCFCANInterfaceInstance::instance().telem_can_rx_buffer.push_back(buf.data(), CAN_MSG_SIZE); } - void on_faux_can_recv(const CAN_message_t &msg) + void on_front_aux_can_recv(const CAN_message_t &msg) { // VCFCANInterfaceInstance::instance().TELEM_CAN.write(msg); //immediately forward onto telem can to view data - uint8_t buf[sizeof(CAN_message_t)]; - memmove(buf, &msg, sizeof(msg)); // NOLINT (memory operations are fine) - VCFCANInterfaceInstance::instance().front_aux_can_rx_buffer.push_back(buf, sizeof(CAN_message_t)); + std::array buf; + memmove(buf.data(), &msg, CAN_MSG_SIZE); + VCFCANInterfaceInstance::instance().front_aux_can_rx_buffer.push_back(buf.data(), CAN_MSG_SIZE); } - void vcf_recv_switch(CANInterfaces &interfaces, const CAN_message_t &msg, unsigned long millis, CANInterfaceType_e interface_type) + void vcf_recv_switch(CANInterfaces_s &interfaces, const CAN_message_t &msg, uint32_t millis, CANInterfaceType_e interface_type) { - switch (msg.id) + switch (msg.id) { case DASHBOARD_BUZZER_CONTROL_CANID: { interfaces.vcr_interface.receive_dash_control_data(msg); break; - } + } case BMS_VOLTAGES_CANID: { interfaces.acu_interface.receive_ACU_voltages(msg); break; } - case ACU_OK_CANID: + case ACU_OK_CANID: { interfaces.dash_interface.receive_ACU_OK(msg); break; - } + } case CAR_STATES_CANID: { interfaces.vcr_interface.receive_car_states_data(msg); @@ -74,21 +74,22 @@ namespace VCFCANInterfaceImpl { interfaces.brake_rotor_temp_interface.receiveBrakeRotorTempData(msg); break; default: + { break; } + } } - void send_all_CAN_msgs(CANTXBufferType &buffer, FlexCAN_T4_Base *can_interface) + void send_all_CAN_msgs(CANTXBuffer_t &buffer, FlexCAN_T4_Base *can_interface) { CAN_message_t msg; - while (buffer.available()) { - CAN_message_t msg; - uint8_t buf[sizeof(CAN_message_t)]; - buffer.pop_front(buf, sizeof(CAN_message_t)); - memmove(&msg, buf, sizeof(msg)); // NOLINT (memory operations are fine) + while (buffer.available()) + { + std::array buf; + buffer.pop_front(buf.data(), CAN_MSG_SIZE); + memmove(&msg, buf.data(), CAN_MSG_SIZE); can_interface->write(msg); } } - } diff --git a/src/VCF_Tasks.cpp b/src/VCF_Tasks.cpp index 6ef66c3..6ae8daa 100644 --- a/src/VCF_Tasks.cpp +++ b/src/VCF_Tasks.cpp @@ -167,7 +167,7 @@ HT_TASK::TaskResponse handle_CAN_send(const unsigned long& sysMicros, const HT_T HT_TASK::TaskResponse send_dash_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - CANInterfaces can_interfaces = CANInterfacesInstance::instance(); + CANInterfaces_s can_interfaces = CANInterfacesInstance::instance(); DashInputState_s dash_outputs = can_interfaces.dash_interface.get_dashboard_outputs(); DASH_INPUT_t msg_out; @@ -641,10 +641,10 @@ void setup_all_interfaces() { VCRInterfaceInstance::create(); // Create CAN singletons - CANInterfacesInstance::create(DashboardInterfaceInstance::instance(), ACUInterfaceInstance::instance(), VCRInterfaceInstance::instance(), BrakeRotorTempInstance::instance()); - VCFCANInterfaceInstance::create(etl::delegate::create()); - handle_CAN_setup(VCFCANInterfaceInstance::instance().TELEM_CAN, VCFInterfaceConstants::TELEM_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_main_can_recv); - handle_CAN_setup(VCFCANInterfaceInstance::instance().FRONT_AUX_CAN, VCFInterfaceConstants::FAUX_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_faux_can_recv); + CANInterfacesInstance::create(ACUInterfaceInstance::instance(), BrakeRotorTempInstance::instance(), DashboardInterfaceInstance::instance(), VCRInterfaceInstance::instance()); + VCFCANInterfaceInstance::create(etl::delegate::create()); + handle_CAN_setup(VCFCANInterfaceInstance::instance().TELEM_CAN, VCFInterfaceConstants::TELEM_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_telem_can_recv); + handle_CAN_setup(VCFCANInterfaceInstance::instance().FRONT_AUX_CAN, VCFInterfaceConstants::FAUX_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_front_aux_can_recv); // Create Ethernet singletons EthernetIPDefsInstance::create(); From 2172ab6c95d70fafebe7e5a0f4e103e0423abab6 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Wed, 24 Jun 2026 22:41:35 -0700 Subject: [PATCH 03/10] CAN interface rev2 --- lib/interfaces/src/VCFCANInterfaceImpl.cpp | 162 ++++++++++----------- 1 file changed, 80 insertions(+), 82 deletions(-) diff --git a/lib/interfaces/src/VCFCANInterfaceImpl.cpp b/lib/interfaces/src/VCFCANInterfaceImpl.cpp index 3c5727a..b36a3e2 100644 --- a/lib/interfaces/src/VCFCANInterfaceImpl.cpp +++ b/lib/interfaces/src/VCFCANInterfaceImpl.cpp @@ -1,95 +1,93 @@ #include "VCFCANInterfaceImpl.h" -namespace VCFCANInterfaceImpl +void VCFCANInterfaceImpl::on_telem_can_recv(const CAN_message_t &msg) { - void on_telem_can_recv(const CAN_message_t &msg) - { - std::array buf; - memmove(buf.data(), &msg, CAN_MSG_SIZE); - VCFCANInterfaceInstance::instance().telem_can_rx_buffer.push_back(buf.data(), CAN_MSG_SIZE); - } + std::array buf; + memmove(buf.data(), &msg, CAN_MSG_SIZE); + VCFCANInterfaceInstance::instance().telem_can_rx_buffer.push_back(buf.data(), CAN_MSG_SIZE); +} - void on_front_aux_can_recv(const CAN_message_t &msg) - { - // VCFCANInterfaceInstance::instance().TELEM_CAN.write(msg); //immediately forward onto telem can to view data - std::array buf; - memmove(buf.data(), &msg, CAN_MSG_SIZE); - VCFCANInterfaceInstance::instance().front_aux_can_rx_buffer.push_back(buf.data(), CAN_MSG_SIZE); - } +void VCFCANInterfaceImpl::on_front_aux_can_recv(const CAN_message_t &msg) +{ + // VCFCANInterfaceInstance::instance().TELEM_CAN.write(msg); //immediately forward onto telem can to view data + std::array buf; + memmove(buf.data(), &msg, CAN_MSG_SIZE); + VCFCANInterfaceInstance::instance().front_aux_can_rx_buffer.push_back(buf.data(), CAN_MSG_SIZE); +} - void vcf_recv_switch(CANInterfaces_s &interfaces, const CAN_message_t &msg, uint32_t millis, CANInterfaceType_e interface_type) +void VCFCANInterfaceImpl::vcf_recv_switch(CANInterfaces_s &interfaces, const CAN_message_t &msg, uint32_t millis, CANInterfaceType_e interface_type) +{ + switch (msg.id) { - switch (msg.id) + case DASHBOARD_BUZZER_CONTROL_CANID: { - case DASHBOARD_BUZZER_CONTROL_CANID: - { - interfaces.vcr_interface.receive_dash_control_data(msg); - break; - } - case BMS_VOLTAGES_CANID: - { - interfaces.acu_interface.receive_ACU_voltages(msg); - break; - } - case ACU_OK_CANID: - { - interfaces.dash_interface.receive_ACU_OK(msg); - break; - } - case CAR_STATES_CANID: - { - interfaces.vcr_interface.receive_car_states_data(msg); - break; - } - case INV1_STATUS_CANID: - { - interfaces.vcr_interface.receive_inverter_status_1(msg); - break; - } - case INV2_STATUS_CANID: - { - interfaces.vcr_interface.receive_inverter_status_2(msg); - break; - } - case INV3_STATUS_CANID: - { - interfaces.vcr_interface.receive_inverter_status_3(msg); - break; - } - case INV4_STATUS_CANID: - { - interfaces.vcr_interface.receive_inverter_status_4(msg); - break; - } - case FL_BRAKE_ROTOR_SENSOR_TEMP_CANID: - case FL_BRAKE_ROTOR_TEMP_CH1_CH4_CANID: - case FL_BRAKE_ROTOR_TEMP_CH5_CH8_CANID: - case FL_BRAKE_ROTOR_TEMP_CH9_CH12_CANID: - case FL_BRAKE_ROTOR_TEMP_CH13_CH16_CANID: - case FR_BRAKE_ROTOR_SENSOR_TEMP_CANID: - case FR_BRAKE_ROTOR_TEMP_CH1_CH4_CANID: - case FR_BRAKE_ROTOR_TEMP_CH5_CH8_CANID: - case FR_BRAKE_ROTOR_TEMP_CH9_CH12_CANID: - case FR_BRAKE_ROTOR_TEMP_CH13_CH16_CANID: - interfaces.brake_rotor_temp_interface.receiveBrakeRotorTempData(msg); - break; - default: - { - break; - } + interfaces.vcr_interface.receive_dash_control_data(msg); + break; + } + case BMS_VOLTAGES_CANID: + { + interfaces.acu_interface.receive_ACU_voltages(msg); + break; + } + case ACU_OK_CANID: + { + interfaces.dash_interface.receive_ACU_OK(msg); + break; + } + case CAR_STATES_CANID: + { + interfaces.vcr_interface.receive_car_states_data(msg); + break; + } + case INV1_STATUS_CANID: + { + interfaces.vcr_interface.receive_inverter_status_1(msg); + break; + } + case INV2_STATUS_CANID: + { + interfaces.vcr_interface.receive_inverter_status_2(msg); + break; + } + case INV3_STATUS_CANID: + { + interfaces.vcr_interface.receive_inverter_status_3(msg); + break; + } + case INV4_STATUS_CANID: + { + interfaces.vcr_interface.receive_inverter_status_4(msg); + break; + } + case FL_BRAKE_ROTOR_SENSOR_TEMP_CANID: + case FL_BRAKE_ROTOR_TEMP_CH1_CH4_CANID: + case FL_BRAKE_ROTOR_TEMP_CH5_CH8_CANID: + case FL_BRAKE_ROTOR_TEMP_CH9_CH12_CANID: + case FL_BRAKE_ROTOR_TEMP_CH13_CH16_CANID: + case FR_BRAKE_ROTOR_SENSOR_TEMP_CANID: + case FR_BRAKE_ROTOR_TEMP_CH1_CH4_CANID: + case FR_BRAKE_ROTOR_TEMP_CH5_CH8_CANID: + case FR_BRAKE_ROTOR_TEMP_CH9_CH12_CANID: + case FR_BRAKE_ROTOR_TEMP_CH13_CH16_CANID: + interfaces.brake_rotor_temp_interface.receiveBrakeRotorTempData(msg); + break; + default: + { + break; } - } - void send_all_CAN_msgs(CANTXBuffer_t &buffer, FlexCAN_T4_Base *can_interface) +} + +void VCFCANInterfaceImpl::send_all_CAN_msgs(CANTXBuffer_t &buffer, FlexCAN_T4_Base *can_interface) +{ + CAN_message_t msg; + while (buffer.available()) { - CAN_message_t msg; - while (buffer.available()) - { - std::array buf; - buffer.pop_front(buf.data(), CAN_MSG_SIZE); - memmove(&msg, buf.data(), CAN_MSG_SIZE); - can_interface->write(msg); - } + std::array buf; + buffer.pop_front(buf.data(), CAN_MSG_SIZE); + memmove(&msg, buf.data(), CAN_MSG_SIZE); + can_interface->write(msg); } } + From 623f7bb8b6d4c9730eb40d4a9529aae451725a5b Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Thu, 25 Jun 2026 10:27:37 -0700 Subject: [PATCH 04/10] CAN interface rev3 --- lib/interfaces/include/VCFCANInterfaceImpl.h | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/interfaces/include/VCFCANInterfaceImpl.h b/lib/interfaces/include/VCFCANInterfaceImpl.h index 3a19714..60cce15 100644 --- a/lib/interfaces/include/VCFCANInterfaceImpl.h +++ b/lib/interfaces/include/VCFCANInterfaceImpl.h @@ -31,11 +31,16 @@ using FlexCAN_t = FlexCAN_T4; */ struct CANInterfaces_s { - explicit CANInterfaces_s(ACUInterface &acu_int, BrakeRotorTemp &brake_rotor_temp_int, DashboardInterface &dash_int, VCRInterface &vcr_int) - : acu_interface(acu_int), - brake_rotor_temp_interface(brake_rotor_temp_int), - dash_interface(dash_int), - vcr_interface(vcr_int) + explicit CANInterfaces_s( + ACUInterface &acu_int, + BrakeRotorTemp &brake_rotor_temp_int, + DashboardInterface &dash_int, + VCRInterface &vcr_int + ) : + acu_interface(acu_int), + brake_rotor_temp_interface(brake_rotor_temp_int), + dash_interface(dash_int), + vcr_interface(vcr_int) {} ACUInterface &acu_interface; @@ -48,11 +53,9 @@ using CANInterfacesInstance = etl::singleton; /** * @brief This struct holds the FlexCAN peripheral instances and their associated RX/TX ring buffers. */ -struct VCFCANInterface +struct VCFCANInterface_s { - explicit VCFCANInterface(etl::delegate recv_switch_func) - : can_recv_switch(recv_switch_func) - {} + explicit VCFCANInterface_s(etl::delegate recv_switch_func) : can_recv_switch(recv_switch_func) {} FlexCAN_t TELEM_CAN; CANRXBuffer_t telem_can_rx_buffer; @@ -64,7 +67,7 @@ struct VCFCANInterface etl::delegate can_recv_switch; }; -using VCFCANInterfaceInstance = etl::singleton; +using VCFCANInterfaceInstance = etl::singleton; namespace VCFCANInterfaceImpl { From 2bfae0aef0fe8f77091b7d6474db377f06568ba6 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Thu, 25 Jun 2026 12:54:00 -0700 Subject: [PATCH 05/10] Ethernet and split Tasks into interface and systems --- include/VCF_Constants.h | 336 +++++++++--------- include/{VCF_Tasks.h => VCF_InterfaceTasks.h} | 36 +- include/VCF_SystemTasks.h | 0 ...eRotorTemp.h => BrakeRotorTempInterface.h} | 14 +- .../include/{Orbis_BR.h => OrbisInterface.h} | 3 - .../include/SteeringEncoderInterface.h | 17 - lib/interfaces/include/VCFCANInterfaceImpl.h | 6 +- lib/interfaces/include/VCFEthernetInterface.h | 55 ++- ...orTemp.cpp => BrakeRotorTempInterface.cpp} | 17 +- .../src/{Orbis_BR.cpp => OrbisInterface.cpp} | 0 lib/interfaces/src/VCFEthernetInterface.cpp | 142 +++++--- .../include/EEPROMUtils.h} | 0 .../include/NeopixelController.h | 0 .../src/NeopixelController.cpp | 0 src/{VCF_Tasks.cpp => VCF_InterfaceTasks.cpp} | 44 +-- src/VCF_SystemTasks.cpp | 0 16 files changed, 336 insertions(+), 334 deletions(-) rename include/{VCF_Tasks.h => VCF_InterfaceTasks.h} (91%) create mode 100644 include/VCF_SystemTasks.h rename lib/interfaces/include/{BrakeRotorTemp.h => BrakeRotorTempInterface.h} (85%) rename lib/interfaces/include/{Orbis_BR.h => OrbisInterface.h} (96%) delete mode 100644 lib/interfaces/include/SteeringEncoderInterface.h rename lib/interfaces/src/{BrakeRotorTemp.cpp => BrakeRotorTempInterface.cpp} (96%) rename lib/interfaces/src/{Orbis_BR.cpp => OrbisInterface.cpp} (100%) rename lib/{interfaces/include/EEPROMUtilities.h => systems/include/EEPROMUtils.h} (100%) rename lib/{interfaces => systems}/include/NeopixelController.h (100%) rename lib/{interfaces => systems}/src/NeopixelController.cpp (100%) rename src/{VCF_Tasks.cpp => VCF_InterfaceTasks.cpp} (96%) create mode 100644 src/VCF_SystemTasks.cpp diff --git a/include/VCF_Constants.h b/include/VCF_Constants.h index 1ee9c2f..26bb991 100644 --- a/include/VCF_Constants.h +++ b/include/VCF_Constants.h @@ -1,225 +1,217 @@ #ifndef VCF_CONSTANTS #define VCF_CONSTANTS -#include +#include +#include -// hardware connections constants -namespace VCFInterfaceConstants { - /* Teensy 4.1 GPIO pins */ +using degree = float; + +namespace VCFInterfaceConstants +{ + /* Serial */ + constexpr size_t SERIAL_BAUDRATE = 115200; + + /* IIR Filter Alphas */ + constexpr float LOADCELL_IIR_FILTER_ALPHA = 0.01f; + /* ADC chip selects */ + constexpr int ADC0_CS = 10; // MCP3208 — steering, sus pots, load cells + constexpr int ADC1_CS = 38; // MCP3208 — pedal position sensors + + /* ADC Versions*/ + /* Channels on ADC_0 */ + // constexpr int UNUSED_CHANNEL = 0; + constexpr int PEDAL_REF_2V5_CHANNEL = 1; + constexpr int STEERING_1_CHANNEL = 2; + constexpr int STEERING_2_CHANNEL = 3; + constexpr int ACCEL_1_CHANNEL = 4; + constexpr int ACCEL_2_CHANNEL = 5; + constexpr int BRAKE_1_CHANNEL = 6; + constexpr int BRAKE_2_CHANNEL = 7; + + /* Channels on ADC_1 */ + constexpr int SHDN_H_CHANNEL = 0; + constexpr int SHDN_D_CHANNEL = 1; + constexpr int FL_LOADCELL_CHANNEL = 2; + constexpr int FR_LOADCELL_CHANNEL = 3; + constexpr int FR_SUS_POT_CHANNEL = 4; + constexpr int FL_SUS_POT_CHANNEL = 5; + constexpr int BRAKE_PRESSURE_FRONT_CHANNEL = 6; + constexpr int BRAKE_PRESSURE_REAR_CHANNEL = 7; + + /* ADC scaling and offsets */ + constexpr float PEDAL_REF_2V5_SCALE = 1.0f; + constexpr float PEDAL_REF_2V5_OFFSET = 0.0f; + + constexpr float STEERING_1_SCALE = 1.0f; // TODO: calibrate + constexpr float STEERING_1_OFFSET = 0.0f; + constexpr float STEERING_2_SCALE = 1.0f; // TODO: calibrate + constexpr float STEERING_2_OFFSET = 0.0f; + + constexpr float ACCEL_1_SCALE = 1.0f; // TODO: calibrate + constexpr float ACCEL_1_OFFSET = 0.0f; + constexpr float ACCEL_2_SCALE = 1.0f; + constexpr float ACCEL_2_OFFSET = 0.0f; + + constexpr float BRAKE_1_SCALE = 1.0f; + constexpr float BRAKE_1_OFFSET = 0.0f; + constexpr float BRAKE_2_SCALE = 1.0f; + constexpr float BRAKE_2_OFFSET = 0.0f; + + constexpr float SHDN_D_SCALE = 0.00697841165926f; + constexpr float SHDN_D_OFFSET = 0.0f; + constexpr float SHDN_H_SCALE = 0.00697841165926f; // ADC read → shutdown voltage + constexpr float SHDN_H_OFFSET = 0.0f; + + constexpr float FL_LOADCELL_SCALE = 1.0f; // TODO: calibrate + constexpr float FL_LOADCELL_OFFSET = 0.0f; + constexpr float FR_LOADCELL_SCALE = 1.0f; // TODO: calibrate + constexpr float FR_LOADCELL_OFFSET = 0.0f; + + constexpr float FR_SUS_POT_SCALE = 0.01396f; // mm between mounting bolts + constexpr float FR_SUS_POT_OFFSET = 150.8f; + constexpr float FL_SUS_POT_SCALE = 0.01396f; + constexpr float FL_SUS_POT_OFFSET = 150.8f; + + constexpr float BRAKE_PRESSURE_FRONT_SCALE = 1.0f; + constexpr float BRAKE_PRESSURE_FRONT_OFFSET = 0.0f; + constexpr float BRAKE_PRESSURE_REAR_SCALE = 1.0f; + constexpr float BRAKE_PRESSURE_REAR_OFFSET = 0.0f; + /* Not on Schematic // constexpr int BTN_DIM_READ = 28; // Currently used for steering system recalibration TODO: change pin // constexpr int BTN_PRESET_READ = 31; // constexpr int BTN_MODE_READ = 27; // USED TO BE 26. */ - /* Dashboard Buttons */ - constexpr int BTN_MC_CYCLE_READ = 31; // DB/MC_RESET on schematic - constexpr int BTN_START_READ = 29; // RTD on schematic - constexpr int BTN_DATA_READ = 30; // DATA_MARK on schematic - constexpr int BUZZER_CONTROL_PIN = 32; - constexpr int BRIGHTNESS_CONTROL_PIN = 26; //BUTTON_1 on schematic - constexpr int BUTTON_2 = 27; // BUTTON_2 on schematic - constexpr int BTN_PRESET_READ = 28; // Pedals recal button (brightness control on schematic) - - /* Dashboard IOExpander Setup */ - constexpr uint8_t IO_EXPANDER_ADDR = 0x20; - - constexpr int NEOPIXEL_CONTROL_PIN = 33; - constexpr int NEOPIXEL_COUNT = 16; // 16 neopixeles on dashboard - + + /* Dashboard GPIO */ + constexpr int BRIGHTNESS_CONTROL_PIN = 26; // BUTTON_1 on schematic + constexpr int BUTTON_2 = 27; // BUTTON_2 on schematic + constexpr int BTN_PRESET_READ = 28; // Pedals recal button + constexpr int BTN_START_READ = 29; // RTD on schematic + constexpr int BTN_DATA_READ = 30; // DATA_MARK on schematic + constexpr int BTN_MC_CYCLE_READ = 31; // DB/MC_RESET on schematic + constexpr int BUZZER_CONTROL_PIN = 32; + // watchdog pins constexpr int WATCHDOG_PIN = 36; constexpr int SOFTWARE_OK_PIN = 37; // Watchdog's !MR pin - + // watchdog kick interval constexpr unsigned long WATCHDOG_KICK_INTERVAL_MS = 10UL; // 10 ms = 100 Hz - - //ADC Pins - constexpr int ADC0_CS = 10; // MCP3208. ADC0 in VCF schematic. Used for steering, sus pots, and load cells. - constexpr int ADC1_CS = 38; // MCP3208. ADC1 in VCF schematic. Used for pedal position sensors. - - /* Channels on ADC_0 */ - // constexpr int UNUSED_CHANNEL = 0; - constexpr int PEDAL_REF_2V5_CHANNEL = 1; // 2.5V reference used for improved pedal calibration - constexpr int STEERING_1_CHANNEL = 2; // Analog steering sensor 1 - constexpr int STEERING_2_CHANNEL = 3; // Analog steering sensor 2 - constexpr int ACCEL_1_CHANNEL = 4; // Accel pedal sensor 1 - constexpr int ACCEL_2_CHANNEL = 5; // Accel pedal sensor 2 - constexpr int BRAKE_1_CHANNEL = 6; // Brake pedal sensor 1 - constexpr int BRAKE_2_CHANNEL = 7; // Brake pedal sensor 2 - /* Channels on ADC_1 */ - constexpr int SHDN_H_CHANNEL = 0; // SHDN_H sense - constexpr int SHDN_D_CHANNEL = 1; // SHDN_D sense - constexpr int FL_LOADCELL_CHANNEL = 2; // Front left load cell - constexpr int FR_LOADCELL_CHANNEL = 3; // Front right load cell - constexpr int FR_SUS_POT_CHANNEL = 4; // Front right suspension potentiometer - constexpr int FL_SUS_POT_CHANNEL = 5; // Front left suspension potentiometer - constexpr int BRAKE_PRESSURE_FRONT_CHANNEL = 6; // Front brake pressure sensor - constexpr int BRAKE_PRESSURE_REAR_CHANNEL = 7; // Rear brake pressure sensor - - //ADC configs - /* Scaling and offset */ - constexpr float PEDAL_REF_2V5_SCALE = 1.0; - constexpr float PEDAL_REF_2V5_OFFSET = 0; - - constexpr float STEERING_1_SCALE = 1.0; // TODO: Figure out what these mean - constexpr float STEERING_1_OFFSET = 0; - constexpr float STEERING_2_SCALE = 1.0; // TODO: Figure out if steering 2 = steering 1 - constexpr float STEERING_2_OFFSET = 0; - // Scale for steering sensor = 0.02197265 . Offset has to be mechanically determined - - constexpr float ACCEL_1_SCALE = 1.0; // TODO: Figure out what these should be - constexpr float ACCEL_1_OFFSET = 0; - constexpr float ACCEL_2_SCALE = 1.0; - constexpr float ACCEL_2_OFFSET = 0; - - constexpr float BRAKE_1_SCALE = 1.0; - constexpr float BRAKE_1_OFFSET = 0; - constexpr float BRAKE_2_SCALE = 1.0; - constexpr float BRAKE_2_OFFSET = 0; - - constexpr float SHDN_H_SCALE = 0.00697841165926; // Conversion from ADC read to shutdown voltage based on schematic - maps reading of 3439 to 24V - constexpr float SHDN_H_OFFSET = 0; - constexpr float SHDN_D_SCALE = 0.00697841165926; // Conversion from ADC read to shutdown voltage based on schematic - maps reading of 3439 to 24V - constexpr float SHDN_D_OFFSET = 0; - - // constexpr float FL_LOADCELL_SCALE = 0.63; - // constexpr float FL_LOADCELL_OFFSET = -3.9; - // constexpr float FR_LOADCELL_SCALE = 0.81; //Values are from the old MCU rev15 // TODO: Calibrate load cells - // constexpr float FR_LOADCELL_OFFSET = 36.8; - - constexpr float FL_LOADCELL_SCALE = 1.0; //Values - constexpr float FL_LOADCELL_OFFSET = 0.0; - constexpr float FR_LOADCELL_SCALE = 1.0; //Values - constexpr float FR_LOADCELL_OFFSET = 0.0; - - constexpr float FR_SUS_POT_SCALE = 0.01396; // Calibrated for mm between mounting bolts - constexpr float FR_SUS_POT_OFFSET = 150.8; - constexpr float FL_SUS_POT_SCALE = 0.01396; // Same as FR - constexpr float FL_SUS_POT_OFFSET = 150.8; - - constexpr float BRAKE_PRESSURE_FRONT_SCALE = 1.0; - constexpr float BRAKE_PRESSURE_FRONT_OFFSET = 0; - constexpr float BRAKE_PRESSURE_REAR_SCALE = 1.0; - constexpr float BRAKE_PRESSURE_REAR_OFFSET = 0; - - /* VCF CAN Constants */ + /* CAN baudrates */ constexpr uint32_t TELEM_CAN_BAUDRATE = 1000000; // 1 000 000 = 1 Mbit/s constexpr uint32_t FAUX_CAN_BAUDRATE = 500000; // 500 000 = 500 Kbit/s } // calibration and processing constants -namespace VCFSystemConstants { - constexpr float LBS_TO_NEWTONS = 4.4482216153; +namespace VCFSystemConstants +{ - // EEPROM addresses for min and max calibration values + /* EEPROM addresses */ constexpr uint32_t ACCEL_1_MIN_ADDR = 0; constexpr uint32_t ACCEL_2_MIN_ADDR = 4; constexpr uint32_t ACCEL_1_MAX_ADDR = 8; constexpr uint32_t ACCEL_2_MAX_ADDR = 12; - constexpr float ACCEL_ACTIVATION_PERCENTAGE = 0.10f; - constexpr uint32_t ACCEL_MIN_SENSOR_PEDAL_1 = 90; - constexpr uint32_t ACCEL_MIN_SENSOR_PEDAL_2 = 90; - constexpr uint32_t ACCEL_MAX_SENSOR_PEDAL_1 = 4000; - constexpr uint32_t ACCEL_MAX_SENSOR_PEDAL_2 = 4000; - constexpr float ACCEL_DEADZONE_MARGIN = 0.03f; - constexpr float ACCEL_MECHANICAL_ACTIVATION_PERCENTAGE = 0.05f; constexpr uint32_t BRAKE_1_MIN_ADDR = 16; constexpr uint32_t BRAKE_2_MIN_ADDR = 20; constexpr uint32_t BRAKE_1_MAX_ADDR = 24; constexpr uint32_t BRAKE_2_MAX_ADDR = 28; - constexpr float BRAKE_ACTIVATION_PERCENTAGE = 0.50f; - constexpr uint32_t BRAKE_MIN_SENSOR_PEDAL_1 = 90; - constexpr uint32_t BRAKE_MIN_SENSOR_PEDAL_2 = 90; - constexpr uint32_t BRAKE_MAX_SENSOR_PEDAL_1 = 4000; - constexpr uint32_t BRAKE_MAX_SENSOR_PEDAL_2 = 4000; - constexpr float BRAKE_DEADZONE_MARGIN = 0.04f; - constexpr float BRAKE_MECHANICAL_ACTIVATION_PERCENTAGE = 0.5f; // Steering System Constants - constexpr uint32_t MIN_STEERING_SIGNAL_ANALOG_ADDR = 56; //Raw ADC value from analog sensor at minimum (left) steering angle (calibration) - constexpr uint32_t MAX_STEERING_SIGNAL_ANALOG_ADDR = 60; //Raw ADC value from analog sensor at maximum (right) steering angle - constexpr uint32_t MIN_STEERING_SIGNAL_DIGITAL_ADDR = 32; //Raw ADC value from digital sensor at minimum (left) steering angle - constexpr uint32_t MAX_STEERING_SIGNAL_DIGITAL_ADDR = 36; //Raw ADC value from digital sensor at maximum (right) steering angle + + /* Steering */ + constexpr float ANALOG_TOLERANCE = 0.05f; // +/- 5% sensor tolerance + constexpr float DIGITAL_TOLERANCE = 0.05f; // +/- 0.2 degree error + constexpr degree ERROR_BETWEEN_SENSORS_TOLERANCE = 5.0f; // degrees + constexpr degree MAX_DTHETA_THRESHOLD = 50.0f; // max angle change per sample (degrees) + constexpr degree DEG_PER_COUNT_DIGITAL = 360.0f / 16384.0f; + constexpr degree DEG_PER_COUNT_ANALOG = 360.0f / 3686.4f; + + constexpr uint32_t MIN_STEERING_SIGNAL_ANALOG_ADDR = 56; + constexpr uint32_t MAX_STEERING_SIGNAL_ANALOG_ADDR = 60; + constexpr uint32_t MIN_STEERING_SIGNAL_DIGITAL_ADDR = 32; + constexpr uint32_t MAX_STEERING_SIGNAL_DIGITAL_ADDR = 36; constexpr int32_t ANALOG_MIN_WITH_MARGINS_ADDR = 40; constexpr int32_t ANALOG_MAX_WITH_MARGINS_ADDR = 44; constexpr int32_t DIGITAL_MIN_WITH_MARGINS_ADDR = 48; constexpr int32_t DIGITAL_MAX_WITH_MARGINS_ADDR = 52; + /* Pedals System */ + constexpr float ACCEL_ACTIVATION_PERCENTAGE = 0.10f; + constexpr float ACCEL_DEADZONE_MARGIN = 0.03f; + constexpr float ACCEL_MECHANICAL_ACTIVATION_PERCENTAGE = 0.05f; + constexpr float BRAKE_ACTIVATION_PERCENTAGE = 0.50f; + constexpr float BRAKE_DEADZONE_MARGIN = 0.04f; + constexpr float BRAKE_MECHANICAL_ACTIVATION_PERCENTAGE = 0.5f; - // implausibility values - constexpr float ANALOG_TOLERANCE = 0.05f; //+- 0.5% error (analog sensor tolerance according to datasheet) - constexpr float DIGITAL_TOLERANCE = 0.05f; // +- 0.2 degrees error - constexpr float ERROR_BETWEEN_SENSORS_TOLERANCE = 5.0f; - - // rate of angle change - constexpr float MAX_DTHETA_THRESHOLD = 50.0f; //maximum change in angle since last reading to consider the reading valid + /* Load cells */ + constexpr float LBS_TO_NEWTONS = 4.4482216153f; - // degrees per bit - constexpr float DEG_PER_COUNT_DIGITAL = 360.0f / 16384.0f; - constexpr float DEG_PER_COUNT_ANALOG = 360.0f / 3686.4f; + + /* IO Expander */ + constexpr uint8_t IO_EXPANDER_ADDR = 0x20; + + /* Neopixel */ + constexpr int NEOPIXEL_CONTROL_PIN = 33; + constexpr int NEOPIXEL_COUNT = 16; // 16 neopixeles on dashboard } // software configuration constants -namespace VCFTaskConstants { - const size_t SERIAL_BAUDRATE = 115200; +namespace VCFConstants +{ - // task priorities and periods - constexpr unsigned long MAIN_TASK_PRIORITY = 5; - constexpr unsigned long MAIN_TASK_PERIOD = 100; // 100 us = 10 kHz + /* Task Times */ + constexpr uint16_t WATCHDOG_PRIORITY = 1; + constexpr uint32_t WATCHDOG_KICK_PERIOD_US = 10000; // 10 000 us = 100 Hz - constexpr unsigned long CAN_SEND_PRIORITY = 10; - constexpr unsigned long CAN_SEND_PERIOD = 2000; // 2 000 us = 500 Hz + constexpr uint16_t PEDALS_SAMPLE_PRIORITY = 2; + constexpr uint32_t PEDALS_SAMPLE_PERIOD_US = 500; // 500 us = 2 kHz - - constexpr unsigned long BUZZER_PRIORITY = 20; - constexpr unsigned long BUZZER_WRITE_PERIOD = 100000; // 100 000 us = 10 Hz - - constexpr unsigned long DASH_SAMPLE_PRIORITY = 21; - constexpr unsigned long DASH_SAMPLE_PERIOD = 100000; // 100 000 us = 10 Hz - - constexpr unsigned long DASH_SEND_PRIORITY = 7; - constexpr unsigned long DASH_SEND_PERIOD = 100000; // 100 000 us = 10 Hz - - constexpr unsigned long DEBUG_PRIORITY = 100; - constexpr unsigned long DEBUG_PERIOD = 10000; // 10 000 us = 2 Hz - - constexpr unsigned long NEOPIXEL_UPDATE_PRIORITY = 90; - constexpr unsigned long NEOPIXEL_UPDATE_PERIOD = 100000; // 100 000 us = 10 Hz - - - constexpr unsigned long LOADCELL_SAMPLE_PRIORITY = 24; - constexpr unsigned long LOADCELL_SAMPLE_PERIOD = 250; // 250 us = 4 kHz - constexpr unsigned long LOADCELL_SEND_PRIORITY = 25; - constexpr unsigned long LOADCELL_SEND_PERIOD = 4000; // 4 000 us = 250 Hz - - constexpr unsigned long ETHERNET_SEND_PRIORITY = 20; - constexpr unsigned long ETHERNET_SEND_PERIOD = 100000; // 100 000 us = 10Hz - - constexpr unsigned long PEDALS_PRIORITY = 5; - constexpr unsigned long PEDALS_SEND_PERIOD = 4000; // 4 000 us = 250 Hz - constexpr unsigned long PEDALS_SAMPLE_PERIOD = 500; // 500 us = 2 kHz - - constexpr unsigned long PEDALS_RECALIBRATION_PRIORITY = 150; - constexpr unsigned long PEDALS_RECALIBRATION_PERIOD = 100000; // 100 000 us = 10 Hz + constexpr uint16_t STEERING_SAMPLE_PRIORITY = 3; + constexpr uint32_t STEERING_SAMPLE_PERIOD_US = 1000; // 1 000 us = 1 kHz - constexpr unsigned long STEERING_SEND_PRIORITY = 25; - constexpr unsigned long STEERING_SEND_PERIOD = 4000; // 4 000 us = 250 Hz - - constexpr unsigned long STEERING_SAMPLE_PERIOD = 1000; // 2000 us = 500 Hz - constexpr unsigned long STEERING_SAMPLE_PRIORITY = 10; - - constexpr unsigned long STEERING_RECALIBRATION_PRIORITY = 150; - constexpr unsigned long STEERING_RECALIBRATION_PERIOD = 100000; + constexpr uint16_t LOADCELL_SAMPLE_PRIORITY = 4; + constexpr uint32_t LOADCELL_SAMPLE_PERIOD_US = 250; // 250 us = 4 kHz - // IIR filter alphas - constexpr float LOADCELL_IIR_FILTER_ALPHA = 0.01f; + constexpr uint16_t PEDALS_SEND_PRIORITY = 5; + constexpr uint32_t PEDALS_SEND_PERIOD_US = 4000; // 4 000 us = 250 Hz + + constexpr uint16_t STEERING_SEND_PRIORITY = 6; + constexpr uint32_t STEERING_SEND_PERIOD_US = 4000; // 4 000 us = 250 Hz + + constexpr uint16_t LOADCELL_SEND_PRIORITY = 7; + constexpr uint32_t LOADCELL_SEND_PERIOD_US = 4000; // 4 000 = 250 Hz + + constexpr uint16_t CAN_SEND_PRIORITY = 8; + constexpr uint32_t CAN_SEND_PERIOD_US = 2000; // 2 000 us = 500 Hz + + constexpr uint16_t DASH_SEND_PRIORITY = 9; + constexpr uint32_t DASH_SEND_PERIOD_US = 100000; // 100 000 us = 10 Hz + + constexpr uint16_t DASH_SAMPLE_PRIORITY = 10; + constexpr uint32_t DASH_SAMPLE_PERIOD_US = 100000; // 100 000 us = 10 Hz + + constexpr uint16_t ETHERNET_SEND_PRIORITY = 11; + constexpr uint32_t ETHERNET_SEND_PERIOD = 100000; // 100 000 us = 10Hz + + constexpr uint16_t BUZZER_PRIORITY = 12; + constexpr uint32_t BUZZER_WRITE_PERIOD_US = 100000; // 100 000 us = 10 Hz + + constexpr uint16_t NEOPIXEL_UPDATE_PRIORITY_US = 13; + constexpr uint32_t NEOPIXEL_UPDATE_PERIOD_US = 100000; // 100 000 us = 10 Hz + + constexpr uint16_t PEDALS_RECALIBRATION_PRIORITY = 20; + constexpr uint32_t PEDALS_RECALIBRATION_PERIOD = 100000; // 100 000 us = 10 Hz + + constexpr uint16_t STEERING_RECALIBRATION_PRIORITY = 21; + constexpr uint32_t STEERING_RECALIBRATION_PERIOD = 100000; // 100 000 us = 10 Hz - constexpr unsigned long WATCHDOG_PRIORITY = 1; - constexpr unsigned long WATCHDOG_KICK_PERIOD = 10000; // 10 000 us = 100 Hz + constexpr uint16_t DEBUG_PRIORITY = 50; + constexpr uint32_t DEBUG_PERIOD_US = 10000; // 10 000 us = 2 Hz } #endif /* VCF_CONSTANTS */ diff --git a/include/VCF_Tasks.h b/include/VCF_InterfaceTasks.h similarity index 91% rename from include/VCF_Tasks.h rename to include/VCF_InterfaceTasks.h index 5803ec4..b2ca95a 100644 --- a/include/VCF_Tasks.h +++ b/include/VCF_InterfaceTasks.h @@ -27,26 +27,34 @@ * functions, too) */ -#ifndef VCF_TASKS -#define VCF_TASKS +#ifndef VCF_INTERFACETASKS +#define VCF_INTERFACETASKS +#include "VCF_Constants.h" #include "SharedFirmwareTypes.h" + +/* Local Interface Includes */ +#include "ACUInterface.h" +#include "ADCInterface.h" +#include "BrakeRotorTempInterface.h" +#include "DashboardInterface.h" +#include "OrbisInterface.h" +#include "SystemTimeInterface.h" #include "VCFCANInterfaceImpl.h" #include "VCFEthernetInterface.h" -#include "PedalsSystem.h" -#include "SteeringSystem.h" +#include "VCRInterface.h" + +/* Scheduling */ #include "ht_sched.hpp" -#include "ht_task.hpp" -#include "BuzzerController.h" -#include "IOExpanderUtils.h" -#include "NeopixelController.h" -#include "WatchdogSystem.h" -#include "ADCInterface.h" -#include "CANInterface.h" -#include "SteeringEncoderInterface.h" +#include /** - * The read_adc0 task will command the ADCInterface to sample, convert, and store + * Init Functions - to be called in setup@ + */ +void initialize_all_interfaces(); + +/** + * The read_adc0 task will command the ADCInterface to sample, convert, and store * data from all eight channels of adc0. */ HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); @@ -103,4 +111,4 @@ namespace async_tasks { void setup_all_interfaces(); -#endif /* VCF_TASKS */ +#endif diff --git a/include/VCF_SystemTasks.h b/include/VCF_SystemTasks.h new file mode 100644 index 0000000..e69de29 diff --git a/lib/interfaces/include/BrakeRotorTemp.h b/lib/interfaces/include/BrakeRotorTempInterface.h similarity index 85% rename from lib/interfaces/include/BrakeRotorTemp.h rename to lib/interfaces/include/BrakeRotorTempInterface.h index 35a47d1..f4f80d8 100644 --- a/lib/interfaces/include/BrakeRotorTemp.h +++ b/lib/interfaces/include/BrakeRotorTempInterface.h @@ -1,5 +1,5 @@ -#ifndef BRAKEROTORTEMP_H -#define BRAKEROTORTEMP_H +#ifndef BRAKEROTORTEMPINTERFACE_H +#define BRAKEROTORTEMPINTERFACE_H /* External libraries */ #include "FlexCAN_T4.h" @@ -25,31 +25,31 @@ struct BrakeTempData_s { /** * Interface to receive messages from the Izze Racing IRTS-60deg-v3 sensor */ -class BrakeRotorTemp +class BrakeRotorTempInterface { public: // default empty constructor will init state to zeros - BrakeRotorTemp() {} + BrakeRotorTempInterface() {} /** * Retrieves the latest data that has been sent from the sensors * @return the latest temp data */ BrakeTempData_s getBrakeRotorTempData() const; - + /** * CAN receive function to parse the new CAN msg and update internal state * Called by VCF's recv switch * @param msg the CAN msg to parse */ void receiveBrakeRotorTempData(const CAN_message_t &msg); - + private: BrakeTempData_s _temp_data; void _updateCalculatedValues(bool FR); }; -using BrakeRotorTempInstance = etl::singleton; +using BrakeRotorTempInterfaceInstance = etl::singleton; #endif // BRAKEROTORTEMP_H \ No newline at end of file diff --git a/lib/interfaces/include/Orbis_BR.h b/lib/interfaces/include/OrbisInterface.h similarity index 96% rename from lib/interfaces/include/Orbis_BR.h rename to lib/interfaces/include/OrbisInterface.h index 9dbc5c0..29140ec 100644 --- a/lib/interfaces/include/Orbis_BR.h +++ b/lib/interfaces/include/OrbisInterface.h @@ -4,7 +4,6 @@ /* Library Includes */ #include #include -#include "SteeringEncoderInterface.h" /* --- Constants --- */ namespace OrbisConstants { @@ -82,14 +81,12 @@ class OrbisBR : public SteeringEncoderInterface OrbisBR(HardwareSerial* serial); //Fields - SteeringEncoderReading_s getLastReading() override; // Override a virtual function from the base class. OrbisErrorFlags_s getOrbisDetailedErrors() const { return _orbisErrors; } // Functions bool performSelfCalibration(); void setEncoderOffset(); void saveConfiguration(); - void sample() override; void factoryReset(); diff --git a/lib/interfaces/include/SteeringEncoderInterface.h b/lib/interfaces/include/SteeringEncoderInterface.h deleted file mode 100644 index f65ef2b..0000000 --- a/lib/interfaces/include/SteeringEncoderInterface.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef STEERING_ENCODER_INTERFACE_H -#define STEERING_ENCODER_INTERFACE_H -#include "SharedFirmwareTypes.h" - -class SteeringEncoderInterface -{ -public: -// Functions - /// @brief Reads current position from the physical sensor and stores the result. - virtual void sample() = 0; - /// @brief Returns the most recently stored reading. - /// @note DOES NOT SAMPLE/COMMUNICATE WITH SENSOR - /// @return Struct containing angle, raw value, status, and error flags - virtual SteeringEncoderReading_s getLastReading() = 0; -}; - -#endif /* STEERING_ENCODER_INTERFACE_H */ diff --git a/lib/interfaces/include/VCFCANInterfaceImpl.h b/lib/interfaces/include/VCFCANInterfaceImpl.h index 60cce15..ed01cfa 100644 --- a/lib/interfaces/include/VCFCANInterfaceImpl.h +++ b/lib/interfaces/include/VCFCANInterfaceImpl.h @@ -13,7 +13,7 @@ /* Local Interface Includes */ #include "ACUInterface.h" -#include "BrakeRotorTemp.h" +#include "BrakeRotorTempInterface.h" #include "DashboardInterface.h" #include "VCRInterface.h" @@ -33,7 +33,7 @@ struct CANInterfaces_s { explicit CANInterfaces_s( ACUInterface &acu_int, - BrakeRotorTemp &brake_rotor_temp_int, + BrakeRotorTempInterface &brake_rotor_temp_int, DashboardInterface &dash_int, VCRInterface &vcr_int ) : @@ -44,7 +44,7 @@ struct CANInterfaces_s {} ACUInterface &acu_interface; - BrakeRotorTemp &brake_rotor_temp_interface; + BrakeRotorTempInterface &brake_rotor_temp_interface; DashboardInterface &dash_interface; VCRInterface &vcr_interface; }; diff --git a/lib/interfaces/include/VCFEthernetInterface.h b/lib/interfaces/include/VCFEthernetInterface.h index 43cb7cf..c3ee136 100644 --- a/lib/interfaces/include/VCFEthernetInterface.h +++ b/lib/interfaces/include/VCFEthernetInterface.h @@ -1,47 +1,66 @@ #ifndef VCF_ETHERNET_INTERFACE_H #define VCF_ETHERNET_INTERFACE_H -#include "QNEthernet.h" +/* External Includes */ #include "hytech_msgs.pb.h" +#include "hytech_msgs_version.h" +#include "ht_can_version.h" +#include "QNEthernet.h" +#include "EthernetAddressDefs.h" +#include "ProtobufMsgInterface.h" #include "SharedFirmwareTypes.h" +#include "device_fw_version.h" + +/* Local Interface Includes */ #include "ADCInterface.h" #include "DashboardInterface.h" #include "PedalsSystem.h" -#include "BrakeRotorTemp.h" +#include "BrakeRotorTempInterface.h" #include "SteeringSystem.h" -namespace VCFEthernetInterface +using namespace qindesign::network; + +class VCFEthernetInterface { +public: + VCFEthernetInterface() = default; + + void init_ethernet_device(); + /** * Function to transform our struct from shared_data_types into the protoc struct hytech_msgs_VCFData_s. - * + * * @param shared_state The current VCF state, which includes both interface and system data. * @return A populated instance of the outgoing protoc struct. */ - // hytech_msgs_VCFData_s make_vcf_data_msg(VCFData_s &shared_state); - hytech_msgs_VCFData_s make_vcf_data_msg(ADCInterface &ADCInterfaceInstance, - DashboardInterface &dashInstance, - PedalsSystem &pedalsInstance, - SteeringSystem &steeringInstance, - BrakeRotorTemp &brakeRotorTempInstance); + hytech_msgs_VCFData_s make_vcf_data_msg( + ADCInterface &adc_int, + DashboardInterface &dash_int, + PedalsSystem &pedals_sys, + SteeringSystem &steering_sys, + BrakeRotorTempInterface &brake_rotor_temp_int + ); /** * Function to take a populated protoc struct from VCR and update the VCF state. This is ONLY critical * for buzzer control! - * + * * @param msg_in A reference to a populated protoc struct. * @param shared_state A reference to the VCF state. - * + * * @post After this function completes, shared_state will contain the updated buzzer control. */ void receive_pb_msg_vcr(const hytech_msgs_VCRData_s &msg_in, VCFData_s &shared_state, unsigned long curr_millis); - constexpr const size_t ver_hash_len = 9; - constexpr float SHDN_HIGH_THRESHOLD = 12.0; // threshold for shutdown being considered high + void handle_send_ethernet_vcf_data(const hytech_msgs_VCFData_s &data); + +private: + static constexpr size_t VER_HASH_LEN = 9; + static constexpr float SHDN_HIGH_THRESHOLD = 12.0f; // threshold for shutdown being considered high - /* Ethernet sockets */ - extern qindesign::network::EthernetUDP VCF_socket; - extern qindesign::network::EthernetUDP VCR_socket; -} + /* Ethernet Sockets */ + EthernetUDP _vcf_send_socket; + EthernetUDP _vcr_recv_socket; +}; #endif /* VCF_ETHERNET_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/src/BrakeRotorTemp.cpp b/lib/interfaces/src/BrakeRotorTempInterface.cpp similarity index 96% rename from lib/interfaces/src/BrakeRotorTemp.cpp rename to lib/interfaces/src/BrakeRotorTempInterface.cpp index e852449..4a2e88a 100644 --- a/lib/interfaces/src/BrakeRotorTemp.cpp +++ b/lib/interfaces/src/BrakeRotorTempInterface.cpp @@ -1,12 +1,11 @@ -#include "BrakeRotorTemp.h" - +#include "BrakeRotorTempInterface.h" #include "hytech.h" -BrakeTempData_s BrakeRotorTemp::getBrakeRotorTempData() const { +BrakeTempData_s BrakeRotorTempInterface::getBrakeRotorTempData() const { return _temp_data; } -void BrakeRotorTemp::receiveBrakeRotorTempData(const CAN_message_t &msg) { +void BrakeRotorTempInterface::receiveBrakeRotorTempData(const CAN_message_t &msg) { switch (msg.id) { case FL_BRAKE_ROTOR_TEMP_CH1_CH4_CANID: { @@ -143,25 +142,25 @@ void BrakeRotorTemp::receiveBrakeRotorTempData(const CAN_message_t &msg) { _updateCalculatedValues(true); break; } - + default: break; } } /** - * Helper method to update the calculated values of max and avg temps for each sensor after new data is + * Helper method to update the calculated values of max and avg temps for each sensor after new data is * received. Will only update for the specified sensor. * @param sensor corresponds to which sensor was updated. FL = 0, FR = 1 */ -void BrakeRotorTemp::_updateCalculatedValues(bool FR) { +void BrakeRotorTempInterface::_updateCalculatedValues(bool FR) { if (FR) { // check if FR needs to be updated auto begin_iterator = _temp_data.fr_sensor.channel_data.begin(); auto end_iterator = _temp_data.fr_sensor.channel_data.end(); // update maximum value _temp_data.fr_sensor.max_temp = *std::max_element(begin_iterator, end_iterator); - + // update avg value float sum = std::accumulate(begin_iterator, end_iterator, 0.0f); // find sum _temp_data.fr_sensor.avg_temp = sum / static_cast(BrakeRotorTempDefaultParams::channels_within_brake_temp_sensor); @@ -171,7 +170,7 @@ void BrakeRotorTemp::_updateCalculatedValues(bool FR) { // update maximum value _temp_data.fl_sensor.max_temp = *std::max_element(begin_iterator, end_iterator); - + // update avg value float sum = std::accumulate(begin_iterator, end_iterator, 0.0f); // find sum _temp_data.fl_sensor.avg_temp = sum / static_cast(BrakeRotorTempDefaultParams::channels_within_brake_temp_sensor); diff --git a/lib/interfaces/src/Orbis_BR.cpp b/lib/interfaces/src/OrbisInterface.cpp similarity index 100% rename from lib/interfaces/src/Orbis_BR.cpp rename to lib/interfaces/src/OrbisInterface.cpp diff --git a/lib/interfaces/src/VCFEthernetInterface.cpp b/lib/interfaces/src/VCFEthernetInterface.cpp index d20d714..81279dc 100644 --- a/lib/interfaces/src/VCFEthernetInterface.cpp +++ b/lib/interfaces/src/VCFEthernetInterface.cpp @@ -1,10 +1,24 @@ #include "VCFEthernetInterface.h" -#include "SharedFirmwareTypes.h" -#include "ht_can_version.h" -#include "hytech_msgs_version.h" -#include "device_fw_version.h" -hytech_msgs_VCFData_s VCFEthernetInterface::make_vcf_data_msg(ADCInterface &ADCInterfaceInstance, DashboardInterface &dashInstance, PedalsSystem &pedalsInstance, SteeringSystem &steeringInstance, BrakeRotorTemp &brakeRotorTempInstance) +void VCFEthernetInterface::init_ethernet_device() +{ + EthernetIPDefsInstance::create(); + Ethernet.begin( + EthernetIPDefsInstance::instance().vcf_ip, + EthernetIPDefsInstance::instance().car_subnet, + EthernetIPDefsInstance::instance().default_gateway + ); + _vcf_send_socket.begin(EthernetIPDefsInstance::instance().VCFData_port); + _vcr_recv_socket.begin(EthernetIPDefsInstance::instance().VCRData_port); +} + +hytech_msgs_VCFData_s VCFEthernetInterface::make_vcf_data_msg( + ADCInterface &adc_int, + DashboardInterface &dash_int, + PedalsSystem &pedals_sys, + SteeringSystem &steering_sys, + BrakeRotorTempInterface &brake_rotor_temp_int +) { hytech_msgs_VCFData_s out; @@ -21,44 +35,44 @@ hytech_msgs_VCFData_s VCFEthernetInterface::make_vcf_data_msg(ADCInterface &ADCI out.has_brake_rotor_temp_data = true; // Load cells - out.front_loadcell_data.FL_loadcell_analog = static_cast(ADCInterfaceInstance.get_filtered_FL_load_cell()); - out.front_loadcell_data.FR_loadcell_analog = static_cast(ADCInterfaceInstance.get_filtered_FR_load_cell()); + out.front_loadcell_data.FL_loadcell_analog = static_cast(adc_int.get_filtered_FL_load_cell()); + out.front_loadcell_data.FR_loadcell_analog = static_cast(adc_int.get_filtered_FR_load_cell()); // Sus pots - out.front_suspot_data.FL_sus_pot_analog = static_cast(ADCInterfaceInstance.get_filtered_FL_sus_pot()); - out.front_suspot_data.FR_sus_pot_analog = static_cast(ADCInterfaceInstance.get_filtered_FR_sus_pot()); + out.front_suspot_data.FL_sus_pot_analog = static_cast(adc_int.get_filtered_FL_sus_pot()); + out.front_suspot_data.FR_sus_pot_analog = static_cast(adc_int.get_filtered_FR_sus_pot()); // Steering - out.steering_data.analog_steering_degrees = ADCInterfaceInstance.get_steering_degrees_cw().conversion; - out.steering_data.digital_steering_analog = ADCInterfaceInstance.get_steering_degrees_ccw().conversion; - + out.steering_data.analog_steering_degrees = adc_int.get_steering_degrees_cw().conversion; + out.steering_data.digital_steering_analog = adc_int.get_steering_degrees_ccw().conversion; + //SteeringSystem - out.steering_system_data.analog_raw = steeringInstance.get_steering_system_data().analog_raw; - out.steering_system_data.digital_raw = steeringInstance.get_steering_system_data().digital_raw; - out.steering_system_data.analog_steering_angle = steeringInstance.get_steering_system_data().analog_steering_angle; - out.steering_system_data.digital_steering_angle = steeringInstance.get_steering_system_data().digital_steering_angle; - out.steering_system_data.output_steering_angle = steeringInstance.get_steering_system_data().output_steering_angle; - out.steering_system_data.analog_steering_velocity_deg_s = steeringInstance.get_steering_system_data().analog_steering_velocity_deg_s; - out.steering_system_data.digital_steering_velocity_deg_s = steeringInstance.get_steering_system_data().digital_steering_velocity_deg_s; - out.steering_system_data.digital_oor_implausibility = steeringInstance.get_steering_system_data().digital_oor_implausibility; - out.steering_system_data.analog_oor_implausibility = steeringInstance.get_steering_system_data().analog_oor_implausibility; - out.steering_system_data.sensor_disagreement_implausibility = steeringInstance.get_steering_system_data().sensor_disagreement_implausibility; - out.steering_system_data.dtheta_exceeded_analog = steeringInstance.get_steering_system_data().dtheta_exceeded_analog; - out.steering_system_data.dtheta_exceeded_digital = steeringInstance.get_steering_system_data().dtheta_exceeded_digital; - out.steering_system_data.both_sensors_fail = steeringInstance.get_steering_system_data().both_sensors_fail; - out.steering_system_data.interface_sensor_error = steeringInstance.get_steering_system_data().interface_sensor_error; + out.steering_system_data.analog_raw = steering_sys.get_steering_system_data().analog_raw; + out.steering_system_data.digital_raw = steering_sys.get_steering_system_data().digital_raw; + out.steering_system_data.analog_steering_angle = steering_sys.get_steering_system_data().analog_steering_angle; + out.steering_system_data.digital_steering_angle = steering_sys.get_steering_system_data().digital_steering_angle; + out.steering_system_data.output_steering_angle = steering_sys.get_steering_system_data().output_steering_angle; + out.steering_system_data.analog_steering_velocity_deg_s = steering_sys.get_steering_system_data().analog_steering_velocity_deg_s; + out.steering_system_data.digital_steering_velocity_deg_s = steering_sys.get_steering_system_data().digital_steering_velocity_deg_s; + out.steering_system_data.digital_oor_implausibility = steering_sys.get_steering_system_data().digital_oor_implausibility; + out.steering_system_data.analog_oor_implausibility = steering_sys.get_steering_system_data().analog_oor_implausibility; + out.steering_system_data.sensor_disagreement_implausibility = steering_sys.get_steering_system_data().sensor_disagreement_implausibility; + out.steering_system_data.dtheta_exceeded_analog = steering_sys.get_steering_system_data().dtheta_exceeded_analog; + out.steering_system_data.dtheta_exceeded_digital = steering_sys.get_steering_system_data().dtheta_exceeded_digital; + out.steering_system_data.both_sensors_fail = steering_sys.get_steering_system_data().both_sensors_fail; + out.steering_system_data.interface_sensor_error = steering_sys.get_steering_system_data().interface_sensor_error; //TODO: MODIFY ETH STRUCT // Dash - out.dash_input_state.dim_btn_is_pressed = dashInstance.get_dashboard_outputs().brightness_ctrl_btn_is_pressed; - out.dash_input_state.preset_btn_is_pressed = dashInstance.get_dashboard_outputs().preset_btn_is_pressed; - out.dash_input_state.mc_reset_btn_is_pressed = dashInstance.get_dashboard_outputs().mc_reset_btn_is_pressed; + out.dash_input_state.dim_btn_is_pressed = dash_int.get_dashboard_outputs().brightness_ctrl_btn_is_pressed; + out.dash_input_state.preset_btn_is_pressed = dash_int.get_dashboard_outputs().preset_btn_is_pressed; + out.dash_input_state.mc_reset_btn_is_pressed = dash_int.get_dashboard_outputs().mc_reset_btn_is_pressed; out.dash_input_state.mode_btn_is_pressed = 0; - out.dash_input_state.start_btn_is_pressed = dashInstance.get_dashboard_outputs().start_btn_is_pressed; - out.dash_input_state.data_btn_is_pressed = dashInstance.get_dashboard_outputs().data_btn_is_pressed; + out.dash_input_state.start_btn_is_pressed = dash_int.get_dashboard_outputs().start_btn_is_pressed; + out.dash_input_state.data_btn_is_pressed = dash_int.get_dashboard_outputs().data_btn_is_pressed; out.dash_input_state.left_paddle_is_pressed = 0; - out.dash_input_state.right_paddle_is_pressed = dashInstance.get_dashboard_outputs().BUTTON_2; - out.dash_input_state.dial_state = (hytech_msgs_ControllerMode_e) (dashInstance.get_dashboard_outputs().dial_state); + out.dash_input_state.right_paddle_is_pressed = dash_int.get_dashboard_outputs().BUTTON_2; + out.dash_input_state.dial_state = (hytech_msgs_ControllerMode_e) (dash_int.get_dashboard_outputs().dial_state); // Ethernet link data /*** Ethernet link data values initialized to 1 in VCFDataInstance_s ***/ @@ -67,53 +81,65 @@ hytech_msgs_VCFData_s VCFEthernetInterface::make_vcf_data_msg(ADCInterface &ADCI out.vcf_ethernet_link_data.dash_link = 1; // Pedals system - out.pedals_system_data.accel_is_implausible = pedalsInstance.get_pedals_system_data().accel_is_implausible; - out.pedals_system_data.brake_is_implausible = pedalsInstance.get_pedals_system_data().brake_is_implausible; - out.pedals_system_data.brake_is_pressed = pedalsInstance.get_pedals_system_data().brake_is_pressed; - out.pedals_system_data.accel_is_pressed = pedalsInstance.get_pedals_system_data().accel_is_pressed; - out.pedals_system_data.mech_brake_is_active = pedalsInstance.get_pedals_system_data().mech_brake_is_active; - out.pedals_system_data.brake_and_accel_pressed_implausibility_high = pedalsInstance.get_pedals_system_data().brake_and_accel_pressed_implausibility_high; - out.pedals_system_data.implausibility_has_exceeded_max_duration = pedalsInstance.get_pedals_system_data().implausibility_has_exceeded_max_duration; - out.pedals_system_data.accel_percent = pedalsInstance.get_pedals_system_data().accel_percent; - out.pedals_system_data.brake_percent = pedalsInstance.get_pedals_system_data().brake_percent; - out.pedals_system_data.regen_percent = pedalsInstance.get_pedals_system_data().regen_percent; + out.pedals_system_data.accel_is_implausible = pedals_sys.get_pedals_system_data().accel_is_implausible; + out.pedals_system_data.brake_is_implausible = pedals_sys.get_pedals_system_data().brake_is_implausible; + out.pedals_system_data.brake_is_pressed = pedals_sys.get_pedals_system_data().brake_is_pressed; + out.pedals_system_data.accel_is_pressed = pedals_sys.get_pedals_system_data().accel_is_pressed; + out.pedals_system_data.mech_brake_is_active = pedals_sys.get_pedals_system_data().mech_brake_is_active; + out.pedals_system_data.brake_and_accel_pressed_implausibility_high = pedals_sys.get_pedals_system_data().brake_and_accel_pressed_implausibility_high; + out.pedals_system_data.implausibility_has_exceeded_max_duration = pedals_sys.get_pedals_system_data().implausibility_has_exceeded_max_duration; + out.pedals_system_data.accel_percent = pedals_sys.get_pedals_system_data().accel_percent; + out.pedals_system_data.brake_percent = pedals_sys.get_pedals_system_data().brake_percent; + out.pedals_system_data.regen_percent = pedals_sys.get_pedals_system_data().regen_percent; // Brake pressure - out.brake_pressure_data.front_brake_pressure = ADCInterfaceInstance.get_brake_pressure_front().conversion; - out.brake_pressure_data.rear_brake_pressure = ADCInterfaceInstance.get_brake_pressure_rear().conversion; + out.brake_pressure_data.front_brake_pressure = adc_int.get_brake_pressure_front().conversion; + out.brake_pressure_data.rear_brake_pressure = adc_int.get_brake_pressure_rear().conversion; // Brake rotor temps - out.brake_rotor_temp_data.fl_max_brake_rotor_temp = brakeRotorTempInstance.getBrakeRotorTempData().fl_sensor.max_temp; - out.brake_rotor_temp_data.fl_avg_brake_rotor_temp = brakeRotorTempInstance.getBrakeRotorTempData().fl_sensor.avg_temp; - out.brake_rotor_temp_data.fr_max_brake_rotor_temp = brakeRotorTempInstance.getBrakeRotorTempData().fr_sensor.max_temp; - out.brake_rotor_temp_data.fr_avg_brake_rotor_temp = brakeRotorTempInstance.getBrakeRotorTempData().fr_sensor.avg_temp; + out.brake_rotor_temp_data.fl_max_brake_rotor_temp = brake_rotor_temp_int.getBrakeRotorTempData().fl_sensor.max_temp; + out.brake_rotor_temp_data.fl_avg_brake_rotor_temp = brake_rotor_temp_int.getBrakeRotorTempData().fl_sensor.avg_temp; + out.brake_rotor_temp_data.fr_max_brake_rotor_temp = brake_rotor_temp_int.getBrakeRotorTempData().fr_sensor.max_temp; + out.brake_rotor_temp_data.fr_avg_brake_rotor_temp = brake_rotor_temp_int.getBrakeRotorTempData().fr_sensor.avg_temp; // Shutdown Senses - out.vcf_shutdown_data.d_inertia_switch_out_read = ADCInterfaceInstance.shdn_d().conversion; - out.vcf_shutdown_data.d_inertia_switch = ADCInterfaceInstance.shdn_d().conversion > SHDN_HIGH_THRESHOLD ? true : false; - out.vcf_shutdown_data.h_driver_brb_out_read = ADCInterfaceInstance.shdn_h().conversion; - out.vcf_shutdown_data.h_driver_brb = ADCInterfaceInstance.shdn_h().conversion > SHDN_HIGH_THRESHOLD ? true : false; + out.vcf_shutdown_data.d_inertia_switch_out_read = adc_int.shdn_d().conversion; + out.vcf_shutdown_data.d_inertia_switch = adc_int.shdn_d().conversion > SHDN_HIGH_THRESHOLD ? true : false; + out.vcf_shutdown_data.h_driver_brb_out_read = adc_int.shdn_h().conversion; + out.vcf_shutdown_data.h_driver_brb = adc_int.shdn_h().conversion > SHDN_HIGH_THRESHOLD ? true : false; /* Firmware Version */ out.has_firmware_version_info = true; out.firmware_version_info.project_is_dirty = device_status_t::project_is_dirty; out.firmware_version_info.project_on_main_or_master = device_status_t::project_on_main_or_master; - std::array ver_hash = convert_version_to_char_arr(device_status_t::firmware_version); + std::array ver_hash = convert_version_to_char_arr(device_status_t::firmware_version); std::copy(ver_hash.begin(), ver_hash.end(), std::begin(out.firmware_version_info.git_hash)); out.has_msg_versions = true; out.msg_versions.ht_can_version = HT_CAN_LIB_VERSION; // working with bytes in nanopb std::string_view version_view(version); - const size_t version_len = [&]() -> size_t { - return std::min(version_view.size(), sizeof(out.msg_versions.ht_proto_version.bytes)); - }(); + const size_t version_len = std::min(version_view.size(), sizeof(out.msg_versions.ht_proto_version.bytes)); out.msg_versions.ht_proto_version.size = version_len; std::copy(version_view.begin(), version_view.begin() + version_len, std::begin(out.msg_versions.ht_proto_version.bytes)); return out; } -void VCFEthernetInterface::receive_pb_msg_vcr(const hytech_msgs_VCRData_s &msg_in, VCFData_s &shared_state, unsigned long curr_millis) { +void VCFEthernetInterface::receive_pb_msg_vcr(const hytech_msgs_VCRData_s &msg_in, VCFData_s &shared_state, unsigned long curr_millis) +{ shared_state.system_data.buzzer_is_active = msg_in.buzzer_is_active; } + +void VCFEthernetInterface::handle_send_ethernet_vcf_data(const hytech_msgs_VCFData_s &data) +{ + handle_ethernet_socket_send_pb( + EthernetIPDefsInstance::instance().vcr_ip, + EthernetIPDefsInstance::instance().VCFData_port, + &_vcf_send_socket, + data, + hytech_msgs_VCFData_s_fields + ); +} + +#define hytech_msgs_VCFData_s_fields &hytech_msgs_VCFData_s_msg \ No newline at end of file diff --git a/lib/interfaces/include/EEPROMUtilities.h b/lib/systems/include/EEPROMUtils.h similarity index 100% rename from lib/interfaces/include/EEPROMUtilities.h rename to lib/systems/include/EEPROMUtils.h diff --git a/lib/interfaces/include/NeopixelController.h b/lib/systems/include/NeopixelController.h similarity index 100% rename from lib/interfaces/include/NeopixelController.h rename to lib/systems/include/NeopixelController.h diff --git a/lib/interfaces/src/NeopixelController.cpp b/lib/systems/src/NeopixelController.cpp similarity index 100% rename from lib/interfaces/src/NeopixelController.cpp rename to lib/systems/src/NeopixelController.cpp diff --git a/src/VCF_Tasks.cpp b/src/VCF_InterfaceTasks.cpp similarity index 96% rename from src/VCF_Tasks.cpp rename to src/VCF_InterfaceTasks.cpp index 6ae8daa..168f447 100644 --- a/src/VCF_Tasks.cpp +++ b/src/VCF_InterfaceTasks.cpp @@ -1,31 +1,10 @@ -#include "VCF_Tasks.h" -#include "SharedFirmwareTypes.h" -#include "EthernetAddressDefs.h" -#include "VCF_Constants.h" -#include -#include "ProtobufMsgInterface.h" -#include "EEPROMUtilities.h" -#include "ht_task.hpp" -#include "hytech.h" -#include "hytech_msgs.pb.h" -#include "VCFCANInterfaceImpl.h" -#include "CANInterface.h" -#include "VCRInterface.h" -#include "SystemTimeInterface.h" -#include "PedalsSystem.h" -#include "SteeringSystem.h" -#include "WatchdogSystem.h" -#include "DashboardInterface.h" -#include "VCFEthernetInterface.h" -#include "ACUInterface.h" -#include -#include "FlexCAN_T4.h" -#include "Orbis_BR.h" -#include "BrakeRotorTemp.h" -#include "SteeringEncoderInterface.h" - -#include "WatchdogSystem.h" -#include "Arduino.h" +#include "VCF_InterfaceTasks.h" + +void initialize_all_interfaces() +{ + + +} HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { @@ -221,10 +200,9 @@ HT_TASK::TaskResponse enqueue_steering_data(const unsigned long& sysMicros, cons return HT_TASK::TaskResponse::YIELD; } -HT_TASK::TaskResponse init_handle_send_vcf_ethernet_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - qindesign::network::Ethernet.begin(EthernetIPDefsInstance::instance().vcf_ip, EthernetIPDefsInstance::instance().car_subnet, EthernetIPDefsInstance::instance().default_gateway); - VCFEthernetInterface::VCF_socket.begin(EthernetIPDefsInstance::instance().VCFData_port); - +HT_TASK::TaskResponse init_handle_send_vcf_ethernet_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) +{ + VCFEthernetInterfaceInstance::instance().init_ethernet_device(); return HT_TASK::TaskResponse::YIELD; } @@ -602,7 +580,7 @@ void setup_all_interfaces() { PedalsSystemInstance::create(accel_params, brake_params); //pass in the two different params SteeringParams_s steering_params = { - .min_steering_signal_analog = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_ANALOG_ADDR), + .min_steering_signal_analog = EEPROMUtils::read_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_ANALOG_ADDR), .max_steering_signal_analog = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MAX_STEERING_SIGNAL_ANALOG_ADDR), .min_steering_signal_digital = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_DIGITAL_ADDR), .max_steering_signal_digital = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MAX_STEERING_SIGNAL_DIGITAL_ADDR), diff --git a/src/VCF_SystemTasks.cpp b/src/VCF_SystemTasks.cpp new file mode 100644 index 0000000..e69de29 From 625fe8a26d4c87412f376f462e0e11310771a89c Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Thu, 25 Jun 2026 14:01:46 -0700 Subject: [PATCH 06/10] Dash interface --- lib/interfaces/include/ACUInterface.h | 20 ++--- lib/interfaces/include/DashboardInterface.h | 89 ++++++++----------- lib/interfaces/src/DashboardInterface.cpp | 98 +++++++++++++-------- src/VCF_InterfaceTasks.cpp | 4 + 4 files changed, 109 insertions(+), 102 deletions(-) diff --git a/lib/interfaces/include/ACUInterface.h b/lib/interfaces/include/ACUInterface.h index 43c4d26..542c5d7 100644 --- a/lib/interfaces/include/ACUInterface.h +++ b/lib/interfaces/include/ACUInterface.h @@ -7,25 +7,21 @@ #include "hytech.h" #include "FlexCAN_T4.h" -class ACUInterface +class ACUInterface { - public: +public: - ACUCoreData_s get_last_recvd_data() {return _last_recvd_data;} + ACUCoreData_s get_last_recvd_data() {return _last_recvd_data;} - float get_cell_voltage() {return _min_cell_voltage;} + float get_cell_voltage() {return _min_cell_voltage;} - void receive_ACU_voltages(const CAN_message_t &can_msg); - - private: + void receive_ACU_voltages(const CAN_message_t &can_msg); - ACUCoreData_s _last_recvd_data; - float _min_cell_voltage = 0; +private: + ACUCoreData_s _last_recvd_data; + float _min_cell_voltage = 0; }; - - - using ACUInterfaceInstance = etl::singleton; #endif /* ACU_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/include/DashboardInterface.h b/lib/interfaces/include/DashboardInterface.h index f3a097f..8c556ac 100644 --- a/lib/interfaces/include/DashboardInterface.h +++ b/lib/interfaces/include/DashboardInterface.h @@ -1,22 +1,24 @@ #ifndef DASHBOARD_INTERFACE_H #define DASHBOARD_INTERFACE_H -#include "Arduino.h" +/* ETL Library */ #include "etl/singleton.h" + +/* External Includes */ #include "MCP23017.h" #include #include "FlexCAN_T4.h" - -#include "hytech_msgs.pb.h" -#include "SharedFirmwareTypes.h" #include "hytech.h" +#include "SharedFirmwareTypes.h" +/* Local Includes */ #include "SystemTimeInterface.h" +#include "IOExpanderUtils.h" // Struct representing dashboard gpios -struct DashboardGPIOs_s { - +struct DashboardGPIOs_s +{ // GPIO uint8_t BRIGHTNESS_CONTROL_PIN; uint8_t PRESET_BUTTON; @@ -26,72 +28,51 @@ struct DashboardGPIOs_s { uint8_t BUTTON_2; }; -class DashboardInterface +class DashboardInterface { - public: - DashboardInterface() = delete; - - DashboardInterface(DashboardGPIOs_s gpios, - uint8_t io_expander_addr, TwoWire &i2c_bus) - : _dashboard_gpios(gpios), _io_expander(MCP23017(io_expander_addr, i2c_bus)) - { - pinMode(_dashboard_gpios.START_BUTTON, INPUT_PULLUP); - pinMode(_dashboard_gpios.PRESET_BUTTON, INPUT_PULLUP); - pinMode(_dashboard_gpios.MC_CYCLE_BUTTON, INPUT_PULLUP); - pinMode(_dashboard_gpios.BRIGHTNESS_CONTROL_PIN, INPUT_PULLUP); - pinMode(_dashboard_gpios.DATA_BUTTON, INPUT_PULLUP); - pinMode(_dashboard_gpios.BUTTON_2, INPUT_PULLUP); - - _dash_created_millis = sys_time::hal_millis(); - - i2c_bus.begin(); - _initIOExpander(); - } - - // Reading gpios - DashInputState_s get_dashboard_outputs(); + public: + DashboardInterface( + DashboardGPIOs_s gpios, + uint8_t io_expander_addr, + TwoWire &i2c_bus + ) : + _dashboard_gpios(gpios), + _io_expander(MCP23017(io_expander_addr, i2c_bus)), + _i2c_bus(i2c_bus) + {} - // Stores outputs - DashInputState_s get_dashboard_stored_state(); - /** - * Syncs stored outputs with last read outputs. - * Used to store previous state of buttons to determine if they are clicked or not. - * In other words, to find the falling edge. + * @brief Initializes GPIO pins and IO expander. */ - void sync_dashboard_stored_state(); + void init(); - // Receiving - void receive_ACU_OK(const CAN_message_t &can_msg); + /** + * @brief Syncs stored outputs with last read outputs. + */ + void sync_dashboard_stored_state(); bool bms_ok = true; bool imd_ok = true; + void receive_ACU_OK(const CAN_message_t &can_msg); void set_dial_state(ControllerMode_e mode); void read_ioexpander(); - - private: - DashboardGPIOs_s _dashboard_gpios; - DashInputState_s _dashboard_outputs; - DashInputState_s _dashboard_stored_state; + DashInputState_s get_dashboard_outputs(); + DashInputState_s get_dashboard_stored_state(); - MCP23017 _io_expander; + private: + DashboardGPIOs_s _dashboard_gpios; + DashInputState_s _dashboard_outputs; // curr state, what the buttons are doing right now + DashInputState_s _dashboard_stored_state; // previous state, what the buttons were doing last tick + MCP23017 _io_expander; + TwoWire &_i2c_bus; unsigned long _dash_created_millis; - inline void _initIOExpander() { - _io_expander.init(); - - _io_expander.portMode(MCP23017Port::A, 0b00000000); // 0b0000 0000 = 0 - _io_expander.portMode(MCP23017Port::B, 0b01111111); // 0b0111 1111 = 127 - - _io_expander.writeRegister(MCP23017Register::GPPU_B, 0xFF); // Internal pull-ups - _io_expander.writeRegister(MCP23017Register::IPOL_B, 0xFF); // Polarity (inverted) - } + void _init_ioexpander(); }; - using DashboardInterfaceInstance = etl::singleton; #endif /* DASHBOARD_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/src/DashboardInterface.cpp b/lib/interfaces/src/DashboardInterface.cpp index e7ac81a..64e6e71 100644 --- a/lib/interfaces/src/DashboardInterface.cpp +++ b/lib/interfaces/src/DashboardInterface.cpp @@ -1,72 +1,80 @@ -#include "SharedFirmwareTypes.h" - #include "DashboardInterface.h" -#include "CANInterface.h" -#include "VCFCANInterfaceImpl.h" -#include "IOExpanderUtils.h" +void DashboardInterface::init() +{ + pinMode(_dashboard_gpios.START_BUTTON, INPUT_PULLUP); + pinMode(_dashboard_gpios.PRESET_BUTTON, INPUT_PULLUP); + pinMode(_dashboard_gpios.MC_CYCLE_BUTTON, INPUT_PULLUP); + pinMode(_dashboard_gpios.BRIGHTNESS_CONTROL_PIN, INPUT_PULLUP); + pinMode(_dashboard_gpios.DATA_BUTTON, INPUT_PULLUP); + pinMode(_dashboard_gpios.BUTTON_2, INPUT_PULLUP); -/* Button reads */ -DashInputState_s DashboardInterface::get_dashboard_outputs() + _dash_created_millis = sys_time::hal_millis(); + + _i2c_bus.begin(); + + _io_expander.init(); + _io_expander.portMode(MCP23017Port::A, 0b00000000); // 0b0000 0000 = 0 + _io_expander.portMode(MCP23017Port::B, 0b01111111); // 0b0111 1111 = 127 + _io_expander.writeRegister(MCP23017Register::GPPU_B, 0xFF); // Internal pull-ups + _io_expander.writeRegister(MCP23017Register::IPOL_B, 0xFF); // Polarity (inverted) +} + +void DashboardInterface::sync_dashboard_stored_state() { - _dashboard_outputs.brightness_ctrl_btn_is_pressed = !digitalRead(_dashboard_gpios.BRIGHTNESS_CONTROL_PIN); - _dashboard_outputs.preset_btn_is_pressed = !digitalRead(_dashboard_gpios.PRESET_BUTTON); - _dashboard_outputs.mc_reset_btn_is_pressed = !digitalRead(_dashboard_gpios.MC_CYCLE_BUTTON); - _dashboard_outputs.start_btn_is_pressed = !digitalRead(_dashboard_gpios.START_BUTTON); - _dashboard_outputs.data_btn_is_pressed = !digitalRead(_dashboard_gpios.DATA_BUTTON); - _dashboard_outputs.BUTTON_2 = !digitalRead(_dashboard_gpios.BUTTON_2); - - return _dashboard_outputs; + _dashboard_stored_state = _dashboard_outputs; } -void DashboardInterface::receive_ACU_OK(const CAN_message_t &can_msg) +void DashboardInterface::receive_ACU_OK(const CAN_message_t &can_msg) { ACU_OK_t unpacked_msg; Unpack_ACU_OK_hytech(&unpacked_msg, can_msg.buf, can_msg.len); // NOLINT (implicitly decay pointer) - constexpr uint32_t acu_ok_init_timeout_ms = 2000; - bms_ok = unpacked_msg.bms_ok; imd_ok = unpacked_msg.imd_ok; } -void DashboardInterface::set_dial_state(ControllerMode_e mode) { - _dashboard_outputs.dial_state = mode; -} - -DashInputState_s DashboardInterface::get_dashboard_stored_state() +void DashboardInterface::set_dial_state(ControllerMode_e mode) { - return _dashboard_stored_state; + _dashboard_outputs.dial_state = mode; } -void DashboardInterface::sync_dashboard_stored_state() +void DashboardInterface::read_ioexpander() { - _dashboard_stored_state = _dashboard_outputs; -} - -void DashboardInterface::read_ioexpander() { uint16_t data = _io_expander.read(); // read data from IOExpander ControllerMode_e new_mode = ControllerMode_e::MODE_0; // default to mode 0 // check for value of dial - if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 0)) { // NOLINT 0 is pos of bit + if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 0)) // NOLINT 0 is pos of bit + { new_mode = ControllerMode_e::MODE_0; - } else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 1)) { // NOLINT 1 is pos of bit + } + else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 1)) // NOLINT 1 is pos of bit + { new_mode = ControllerMode_e::MODE_1; - } else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 2)) { // NOLINT 2 is pos of bit + } + else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 2)) // NOLINT 2 is pos of bit + { new_mode = ControllerMode_e::MODE_2; - } else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 3)) { // NOLINT 3 is pos of bit + } + else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 3)) // NOLINT 3 is pos of bit + { new_mode = ControllerMode_e::MODE_3; - } else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 4)) { // NOLINT 4 is pos of bit + } + else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 4)) // NOLINT 4 is pos of bit + { new_mode = ControllerMode_e::MODE_4; - } else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 5)) { // NOLINT 5 is pos of bit + } + else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 5)) // NOLINT 5 is pos of bit + { new_mode = ControllerMode_e::MODE_5; } _dashboard_outputs.dial_state = new_mode; // set new mode // write to 8-seg display based on current mode - switch (_dashboard_outputs.dial_state) { + switch (_dashboard_outputs.dial_state) + { case ControllerMode_e::MODE_0: { _io_expander.writePort(MCP23017Port::A, 0b00000010); // NOLINT 0b0000 0010 = 2 @@ -103,4 +111,22 @@ void DashboardInterface::read_ioexpander() { break; } } +} + +/* Button reads */ +DashInputState_s DashboardInterface::get_dashboard_outputs() +{ + _dashboard_outputs.brightness_ctrl_btn_is_pressed = !digitalRead(_dashboard_gpios.BRIGHTNESS_CONTROL_PIN); + _dashboard_outputs.preset_btn_is_pressed = !digitalRead(_dashboard_gpios.PRESET_BUTTON); + _dashboard_outputs.mc_reset_btn_is_pressed = !digitalRead(_dashboard_gpios.MC_CYCLE_BUTTON); + _dashboard_outputs.start_btn_is_pressed = !digitalRead(_dashboard_gpios.START_BUTTON); + _dashboard_outputs.data_btn_is_pressed = !digitalRead(_dashboard_gpios.DATA_BUTTON); + _dashboard_outputs.BUTTON_2 = !digitalRead(_dashboard_gpios.BUTTON_2); + + return _dashboard_outputs; +} + +DashInputState_s DashboardInterface::get_dashboard_stored_state() +{ + return _dashboard_stored_state; } \ No newline at end of file diff --git a/src/VCF_InterfaceTasks.cpp b/src/VCF_InterfaceTasks.cpp index 168f447..d7d7f00 100644 --- a/src/VCF_InterfaceTasks.cpp +++ b/src/VCF_InterfaceTasks.cpp @@ -4,6 +4,10 @@ void initialize_all_interfaces() { + /* Dashboard Interface */ + DashboardInterfaceInstance::create(); + DashboardInterfaceInstance::instance().init(); + } HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) From 09f9b6102c0bce890e20f6a04edd34860a0c4c57 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Thu, 25 Jun 2026 14:27:33 -0700 Subject: [PATCH 07/10] format --- .../include/BrakeRotorTempInterface.h | 18 ++++++++----- lib/systems/include/EEPROMUtils.h | 3 +++ lib/systems/include/IOExpanderUtils.h | 3 ++- lib/systems/include/NeopixelController.h | 16 +++++++----- lib/systems/include/PedalsSystem.h | 26 ++++++++++--------- lib/systems/src/NeopixelController.cpp | 11 +++++--- 6 files changed, 48 insertions(+), 29 deletions(-) diff --git a/lib/interfaces/include/BrakeRotorTempInterface.h b/lib/interfaces/include/BrakeRotorTempInterface.h index f4f80d8..21ec360 100644 --- a/lib/interfaces/include/BrakeRotorTempInterface.h +++ b/lib/interfaces/include/BrakeRotorTempInterface.h @@ -1,23 +1,27 @@ #ifndef BRAKEROTORTEMPINTERFACE_H #define BRAKEROTORTEMPINTERFACE_H -/* External libraries */ -#include "FlexCAN_T4.h" +/* ETL Library */ #include "etl/singleton.h" +/* External Includes */ +#include "FlexCAN_T4.h" + -namespace BrakeRotorTempDefaultParams { +namespace brake_rotor_temp_default_params +{ constexpr size_t channels_within_brake_temp_sensor = 16; // TODO: check if our sensors are actually 16 channel } -struct BrakeTempSensorData_s { +struct BrakeTempSensorData_s +{ float max_temp; float avg_temp; - - std::array channel_data; + std::array channel_data; }; -struct BrakeTempData_s { +struct BrakeTempData_s +{ BrakeTempSensorData_s fl_sensor; BrakeTempSensorData_s fr_sensor; }; diff --git a/lib/systems/include/EEPROMUtils.h b/lib/systems/include/EEPROMUtils.h index 10ae9b9..806d07f 100644 --- a/lib/systems/include/EEPROMUtils.h +++ b/lib/systems/include/EEPROMUtils.h @@ -1,7 +1,10 @@ #ifndef EEPROM_UTILITIES_H #define EEPROM_UTILITIES_H +/* Standard Library */ #include + +/* External Includes */ #include #include "Logger.h" diff --git a/lib/systems/include/IOExpanderUtils.h b/lib/systems/include/IOExpanderUtils.h index 5f8ddb4..b8e87a2 100644 --- a/lib/systems/include/IOExpanderUtils.h +++ b/lib/systems/include/IOExpanderUtils.h @@ -1,10 +1,11 @@ #ifndef IO_EXPANDER_UTILS_H #define IO_EXPANDER_UTILS_H -/* Standard int library */ +/* Standard Library */ #include #include + namespace IOExpanderUtils { /** diff --git a/lib/systems/include/NeopixelController.h b/lib/systems/include/NeopixelController.h index a7e257a..185c338 100644 --- a/lib/systems/include/NeopixelController.h +++ b/lib/systems/include/NeopixelController.h @@ -1,7 +1,7 @@ #ifndef NEOPIXEL_CONTROLLER_H #define NEOPIXEL_CONTROLLER_H -/* Neopixel controller defines */ +/* Neopixel Controller Defines */ #define MAX_BRIGHTNESS 255 #define MIN_BRIGHTNESS 3 #define BRIGHTNESS_STEPS 4 @@ -13,11 +13,17 @@ // define a new type of struct, add an arg to the constructor, etc. // - this is how it was implemented on STM32 dash and I want to be fast :) +/* ETL Library */ +#include "etl/singleton.h" + +/* External Includes */ #include "Adafruit_NeoPixel.h" #include "SharedFirmwareTypes.h" -#include "etl/singleton.h" + +/* Local Interface Includes */ #include "VCFCANInterfaceImpl.h" + struct MinCellMonitoringThresholds_s { float max_level = 3.85; @@ -63,22 +69,20 @@ enum class LED_color_e class NeopixelController { - public: +public: NeopixelController(uint32_t neopixel_count, uint32_t neopixel_pin) : _neopixels(neopixel_count, neopixel_pin, NEO_GRBW + NEO_KHZ800), _current_brightness(64), _neopixel_count(neopixel_count) {}; - NeopixelController() = delete; - void init_neopixels(); void dim_neopixels(); void set_neopixel(uint16_t id, uint32_t c); void refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces_s &interfaces); void set_neopixel_color(LED_ID_e led, LED_color_e color); - private: +private: Adafruit_NeoPixel _neopixels; uint8_t _current_brightness; diff --git a/lib/systems/include/PedalsSystem.h b/lib/systems/include/PedalsSystem.h index 5768352..868b313 100644 --- a/lib/systems/include/PedalsSystem.h +++ b/lib/systems/include/PedalsSystem.h @@ -1,10 +1,12 @@ #ifndef PEDALSSYSTEM #define PEDALSSYSTEM -#include -#include -#include +/* ETL Library */ +#include +/* External Includes */ +#include +#include #include "SharedFirmwareTypes.h" @@ -15,7 +17,7 @@ const float ACCELERATION_PERCENT_LIMIT = static_cast(0.05); // accelerati /** * Pedals params struct that holds min/max values that will be used for evaluation. The accel and brake sensors * will each have one version of PedalsParam. - * + * * NOTE: Please take note of the meaning of min/max! They are not the min/max outputs of the pedal sensor, they * the values at min/max travel. So, for negative slope coefficient sensors, "min" will be greater than "max". */ @@ -47,16 +49,17 @@ class PedalsSystem /// @param accelParams Accel pedal parameters. By rules, 2 sensors must be used for redundancy and evaluated w.r.t each other /// @param brakeParams Brake pedal params. When used with only one pedal sensor, the pedal parameter evaluation for brakes only looks at the min and max for min_pedal_1 / max_pedal_1 - PedalsSystem(const PedalsParams &accelParams, - const PedalsParams &brakeParams) : _accelParams(accelParams), _brakeParams(brakeParams), _implausibilityStartTime(0) - { } + PedalsSystem(const PedalsParams &accelParams, const PedalsParams &brakeParams) : + _accelParams(accelParams), + _brakeParams(brakeParams), + _implausibilityStartTime(0) + {}; - void set_params(const PedalsParams &accelParams, - const PedalsParams &brakeParams) + void set_params(const PedalsParams &accelParams, const PedalsParams &brakeParams) { _accelParams = accelParams; _brakeParams = brakeParams; - + } void set_pedals_sensor_data(const PedalSensorData_s &pedal_data) @@ -216,7 +219,7 @@ class PedalsSystem /// @param check_mech_activation if this is true, function will check percentages against the mechanical activation percentage /// @return true or false accordingly bool _pedal_is_active(float pedal1ConvertedData, float pedal2ConvertedData, const PedalsParams ¶ms, bool check_mech_activation); - + private: PedalsSystemData_s _systemData{}; PedalSensorData_s _sensorData{}; @@ -229,4 +232,3 @@ class PedalsSystem using PedalsSystemInstance = etl::singleton; #endif /* PEDALSSYSTEM */ - \ No newline at end of file diff --git a/lib/systems/src/NeopixelController.cpp b/lib/systems/src/NeopixelController.cpp index 4afaa1d..6a96471 100644 --- a/lib/systems/src/NeopixelController.cpp +++ b/lib/systems/src/NeopixelController.cpp @@ -1,8 +1,10 @@ #include "NeopixelController.h" -void NeopixelController::init_neopixels() { +void NeopixelController::init_neopixels() +{ _neopixels.begin(); _neopixels.setBrightness(_current_brightness); + //set init color for every led for (int i = 0; i < _neopixel_count; i++) { @@ -54,9 +56,12 @@ void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data } LED_color_e brake_light_color = LED_color_e::OFF; - if (pedals_data.brake_is_pressed && !pedals_data.implausibility_has_exceeded_max_duration) { + if (pedals_data.brake_is_pressed && !pedals_data.implausibility_has_exceeded_max_duration) + { brake_light_color = LED_color_e::GREEN; - } else if (pedals_data.implausibility_has_exceeded_max_duration) { + } + else if (pedals_data.implausibility_has_exceeded_max_duration) + { brake_light_color = LED_color_e::RED; } From b6aebf9a9771baf5ac60c49ff5e6121f9a43dd96 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Thu, 25 Jun 2026 16:04:22 -0700 Subject: [PATCH 08/10] Steering System --- .../src/BrakeRotorTempInterface.cpp | 4 +- lib/systems/include/SteeringSystem.h | 140 +++++---- lib/systems/src/SteeringSystem.cpp | 275 ++++++++++-------- 3 files changed, 218 insertions(+), 201 deletions(-) diff --git a/lib/interfaces/src/BrakeRotorTempInterface.cpp b/lib/interfaces/src/BrakeRotorTempInterface.cpp index 4a2e88a..71bd782 100644 --- a/lib/interfaces/src/BrakeRotorTempInterface.cpp +++ b/lib/interfaces/src/BrakeRotorTempInterface.cpp @@ -163,7 +163,7 @@ void BrakeRotorTempInterface::_updateCalculatedValues(bool FR) { // update avg value float sum = std::accumulate(begin_iterator, end_iterator, 0.0f); // find sum - _temp_data.fr_sensor.avg_temp = sum / static_cast(BrakeRotorTempDefaultParams::channels_within_brake_temp_sensor); + _temp_data.fr_sensor.avg_temp = sum / static_cast(brake_rotor_temp_default_params::channels_within_brake_temp_sensor); } else { // otherwise update FL auto begin_iterator = _temp_data.fl_sensor.channel_data.begin(); auto end_iterator = _temp_data.fl_sensor.channel_data.end(); @@ -173,6 +173,6 @@ void BrakeRotorTempInterface::_updateCalculatedValues(bool FR) { // update avg value float sum = std::accumulate(begin_iterator, end_iterator, 0.0f); // find sum - _temp_data.fl_sensor.avg_temp = sum / static_cast(BrakeRotorTempDefaultParams::channels_within_brake_temp_sensor); + _temp_data.fl_sensor.avg_temp = sum / static_cast(brake_rotor_temp_default_params::channels_within_brake_temp_sensor); } } \ No newline at end of file diff --git a/lib/systems/include/SteeringSystem.h b/lib/systems/include/SteeringSystem.h index e2cf992..c0aff29 100644 --- a/lib/systems/include/SteeringSystem.h +++ b/lib/systems/include/SteeringSystem.h @@ -1,123 +1,121 @@ #ifndef STEERING_SYSTEM_H #define STEERING_SYSTEM_H - -#include + +/* Standard Library */ #include +/* ETL Library */ +#include + +/* External Includes */ +#include #include "SharedFirmwareTypes.h" -struct SteeringParams_s { - // raw ADC input signals - uint32_t min_steering_signal_analog; //Raw ADC value from analog sensor at minimum (left) steering angle (calibration) - uint32_t max_steering_signal_analog; //Raw ADC value from analog sensor at maximum (right) steering angle + +struct SteeringParams_s +{ + /* Raw ADC Input Signals */ + uint32_t min_steering_signal_analog; //Raw ADC value from analog sensor at minimum (left) steering angle (calibration) + uint32_t max_steering_signal_analog; //Raw ADC value from analog sensor at maximum (right) steering angle uint32_t min_steering_signal_digital; //Raw ADC value from digital sensor at minimum (left) steering angle uint32_t max_steering_signal_digital; //Raw ADC value from digital sensor at maximum (right) steering angle - int32_t analog_min_with_margins; // Added margins to min raw value - int32_t analog_max_with_margins; // Added margins to max raw value + /* Boundaries with tolerance margins applied */ + int32_t analog_min_with_margins; // Added margins to min raw value + int32_t analog_max_with_margins; // Added margins to max raw value int32_t digital_min_with_margins; // Added margins to min raw value int32_t digital_max_with_margins; // Added margins to max raw value - uint32_t span_signal_analog; // range of the analog sensor in counts + /* Derived span and midpoint values */ + uint32_t span_signal_analog; // range of the analog sensor in counts uint32_t span_signal_digital; // range of the digital sensor in counts - uint32_t digital_midpoint; // midpoint of raw values - uint32_t analog_midpoint; // midpoint of raw values + uint32_t digital_midpoint; // midpoint of raw values + uint32_t analog_midpoint; // midpoint of raw values - // conversion rates - // float deg_per_count_analog = 0.0439f; //hard coded for analog (180) + /* Conversion Rates */ + // float deg_per_count_analog = 0.0439f; // hard coded for analog sensor that is 180 float deg_per_count_analog; float deg_per_count_digital; //based on digital readings - // implausibility values - float analog_tolerance; //+- 0.5% error + /* Implausibility Tolerances */ + float analog_tolerance; //+- 0.5% error float digital_tolerance; // +- 0.2 degrees error float analog_tol_deg; - float digital_tol_deg; // +- 0.2 degrees error - - // rate of angle change - float max_dtheta_threshold; //maximum change in angle since last reading to consider the reading valid - - // difference rating - float error_between_sensors_tolerance; //maximum difference between digital and analog sensor allowed + float digital_tol_deg; // +- 0.2 degrees error + float max_dtheta_threshold; // Maximum change in angle since last reading to consider the reading valid + float error_between_sensors_tolerance; // Max allowed disagreement between sensors (degrees) }; -class SteeringSystem { +class SteeringSystem +{ public: - SteeringSystem(const SteeringParams_s &steeringParams) : _steeringParams(steeringParams) {} + SteeringSystem(const SteeringParams_s ¶ms) : _params(params) {} - // Functions void recalibrate_steering_digital(); - void evaluate_steering(const uint32_t analog_raw, const SteeringEncoderReading_s digital_data, const uint32_t current_millis); + void update_observed_steering_limits(const uint32_t analog_raw, const uint32_t digital_raw); - // Getters - const SteeringParams_s &get_steering_params() const { - return _steeringParams; - } - - const SteeringSystemData_s &get_steering_system_data() const { - return _steeringSystemData; - } - - float get_unfiltered_analog_steering_deg() const { - return _analog_angle_unfiltered; - } - - // Setters - void set_steering_params(const SteeringParams_s &steeringParams) { - _steeringParams = steeringParams; - } + /* Getters */ + const SteeringParams_s &get_steering_params() const { return _params; } + const SteeringSystemData_s &get_steering_system_data() const { return _system_data; } + float get_unfiltered_analog_steering_deg() const { return _analog_angle_unfiltered; } - void set_steering_system_data(const SteeringSystemData_s &steeringSystemData) { - _steeringSystemData = steeringSystemData; - } - void update_observed_steering_limits(const uint32_t analog_raw, const uint32_t digital_raw); + /* Setters */ + void set_steering_params(const SteeringParams_s ¶ms) { _params = params; } + void set_steering_system_data(const SteeringSystemData_s &system_data) { _system_data = system_data; } - //DELETE - const uint32_t get_min_observed_analog() const { - return min_observed_analog; - } - const uint32_t get_max_observed_analog() const { - return max_observed_analog; - } private: + float _convert_digital_sensor(const uint32_t digital_raw); - float _convert_analog_sensor(const uint32_t analog_raw); - - //returns true if steering_analog is outside of the range defined by min and max sensor values + float _filter_analog_angle(float x); + + /** + * @brief returns true if steering_analog is outside of the range defined by min and max sensor values + */ bool _evaluate_steering_oor_analog(const uint32_t steering_analog); - - //returns true if steering_digital is outside the range defined by min and max sensor values + + /** + * @brief returns true if steering_digital is outside the range defined by min and max sensor values + */ bool _evaluate_steering_oor_digital(const uint32_t steering_digital); - //returns true if change in angle exceeds maximum change per reading ( max_dtheta_threshold ) + /** + * @brief returns true if change in angle exceeds maximum change per reading ( max_dtheta_threshold ) + */ bool _evaluate_steering_dtheta_exceeded(float dtheta); - SteeringSystemData_s _steeringSystemData {}; - SteeringParams_s _steeringParams; - //track the state of our system from the previous tick to compare against current state for implausibility checks + SteeringSystemData_s _system_data {}; + SteeringParams_s _params; + + // Track the state of system at the previous tick to compare against current state for implausibility checks + uint32_t _prev_timestamp = 0; + uint32_t _min_observed_analog = UINT32_MAX; + uint32_t _max_observed_analog = 0; + uint32_t _min_observed_digital = UINT32_MAX; + uint32_t _max_observed_digital = 0; float _analog_angle_unfiltered = 0.0f; float _prev_analog_angle = 0.0f; float _prev_digital_angle = 0.0f; float _prev_digital_vel_angle = 0.0f; float _prev_analog_vel_angle = 0.0f; - uint32_t _prev_timestamp = 0; bool _calibrating = false; bool _finished_calibrating = false; bool _first_run = true; // skip dTheta check on the very first tick - uint32_t min_observed_analog = UINT32_MAX; - uint32_t max_observed_analog = 0; - uint32_t min_observed_digital = UINT32_MAX; - uint32_t max_observed_digital = 0; - - // 2nd-order Butterworth IIR low-pass on the analog angle. + + /* 2nd-order Butterworth IIR low-pass on the analog angle. */ // Designed for fc = 8 Hz at fs = 500 Hz. Direct Form II Transposed. - float _filter_analog_angle(float x); float _bw_z1 = 0.0f; float _bw_z2 = 0.0f; bool _bw_initialized = false; float _last_filtered_analog_angle = 0.0f; + + /* Coefficients */ + static constexpr float kBwB0 = 0.00235721f; + static constexpr float kBwB1 = 0.00471442f; + static constexpr float kBwB2 = 0.00235721f; + static constexpr float kBwA1 = -1.85804330f; + static constexpr float kBwA2 = 0.86747213f; }; using SteeringSystemInstance = etl::singleton; diff --git a/lib/systems/src/SteeringSystem.cpp b/lib/systems/src/SteeringSystem.cpp index a25a081..0c36c4c 100644 --- a/lib/systems/src/SteeringSystem.cpp +++ b/lib/systems/src/SteeringSystem.cpp @@ -1,197 +1,216 @@ -#include - #include "SteeringSystem.h" -constexpr float kBwB0 = 0.00235721f; -constexpr float kBwB1 = 0.00471442f; -constexpr float kBwB2 = 0.00235721f; -constexpr float kBwA1 = -1.85804330f; -constexpr float kBwA2 = 0.86747213f; - -void SteeringSystem::recalibrate_steering_digital() { - _steeringParams.min_steering_signal_analog = min_observed_analog; - _steeringParams.max_steering_signal_analog = max_observed_analog; - _steeringParams.min_steering_signal_digital = min_observed_digital; - _steeringParams.max_steering_signal_digital = max_observed_digital; - // swaps min & max in the params if sensor is flipped - if (_steeringParams.min_steering_signal_digital > _steeringParams.max_steering_signal_digital) { - std::swap(_steeringParams.min_steering_signal_digital, _steeringParams.max_steering_signal_digital); +void SteeringSystem::recalibrate_steering_digital() +{ + _params.min_steering_signal_analog = _min_observed_analog; + _params.max_steering_signal_analog = _max_observed_analog; + _params.min_steering_signal_digital = _min_observed_digital; + _params.max_steering_signal_digital = _max_observed_digital; + + // Swap min & max in the params if sensor is flipped + if (_params.min_steering_signal_digital > _params.max_steering_signal_digital) + { + std::swap(_params.min_steering_signal_digital, _params.max_steering_signal_digital); } - if (_steeringParams.min_steering_signal_analog > _steeringParams.max_steering_signal_analog) { - std::swap(_steeringParams.min_steering_signal_analog, _steeringParams.max_steering_signal_analog); + if (_params.min_steering_signal_analog > _params.max_steering_signal_analog) + { + std::swap(_params.min_steering_signal_analog, _params.max_steering_signal_analog); } - _steeringParams.span_signal_digital = _steeringParams.max_steering_signal_digital-_steeringParams.min_steering_signal_digital; - _steeringParams.analog_tol_deg = static_cast(_steeringParams.span_signal_analog) * _steeringParams.analog_tolerance * _steeringParams.deg_per_count_analog; - _steeringParams.digital_tol_deg = static_cast(_steeringParams.span_signal_digital) *_steeringParams.digital_tolerance * _steeringParams.deg_per_count_digital; - _steeringParams.digital_midpoint = (_steeringParams.max_steering_signal_digital + _steeringParams.min_steering_signal_digital) / 2; - _steeringParams.analog_midpoint = (_steeringParams.max_steering_signal_analog + _steeringParams.min_steering_signal_analog) / 2; - _steeringParams.analog_min_with_margins = static_cast(_steeringParams.min_steering_signal_analog - _steeringParams.analog_tol_deg); // NOLINT - _steeringParams.analog_max_with_margins = static_cast(_steeringParams.max_steering_signal_analog + _steeringParams.analog_tol_deg); // NOLINT - _steeringParams.digital_min_with_margins = static_cast(_steeringParams.min_steering_signal_digital - _steeringParams.digital_tol_deg); // NOLINT - _steeringParams.digital_max_with_margins = static_cast(_steeringParams.max_steering_signal_digital + _steeringParams.digital_tol_deg); // NOLINT - - if (max_observed_analog > min_observed_analog && _steeringParams.span_signal_analog > 2500) // NOLINT with 360 deg analog sensor, typical span is about 2000 + + _params.span_signal_analog = _params.max_steering_signal_analog - _params.min_steering_signal_analog; + _params.span_signal_digital = _params.max_steering_signal_digital-_params.min_steering_signal_digital; + + _params.analog_tol_deg = static_cast(_params.span_signal_analog) * _params.analog_tolerance * _params.deg_per_count_analog; + _params.digital_tol_deg = static_cast(_params.span_signal_digital) *_params.digital_tolerance * _params.deg_per_count_digital; + + _params.analog_midpoint = (_params.max_steering_signal_analog + _params.min_steering_signal_analog) / 2; + _params.digital_midpoint = (_params.max_steering_signal_digital + _params.min_steering_signal_digital) / 2; + + _params.analog_min_with_margins = static_cast(_params.min_steering_signal_analog - _params.analog_tol_deg); // NOLINT + _params.analog_max_with_margins = static_cast(_params.max_steering_signal_analog + _params.analog_tol_deg); // NOLINT + _params.digital_min_with_margins = static_cast(_params.min_steering_signal_digital - _params.digital_tol_deg); // NOLINT + _params.digital_max_with_margins = static_cast(_params.max_steering_signal_digital + _params.digital_tol_deg); // NOLINT + + if (_max_observed_analog > _min_observed_analog && _params.span_signal_analog > 2500) // NOLINT with 360 deg analog sensor, typical span is about 2000 { - min_observed_analog = UINT32_MAX; // after calculating params, if the range is marginally greater than half the steering wheel adc, likely the min and max are clinging to a prior run that is not applicable, meaning we will need to reset the boundaries. - max_observed_analog = 0; + _min_observed_analog = UINT32_MAX; // after calculating params, if the range is marginally greater than half the steering wheel adc, likely the min and max are clinging to a prior run that is not applicable, meaning we will need to reset the boundaries. + _max_observed_analog = 0; } - if (max_observed_digital > min_observed_digital && _steeringParams.span_signal_digital > 9000) // NOLINT with digital sensor, typical span is about 9000 + if (_max_observed_digital > _min_observed_digital && _params.span_signal_digital > 9000) // NOLINT with digital sensor, typical span is about 9000 { - min_observed_digital = UINT32_MAX; - max_observed_digital = 0; + _min_observed_digital = UINT32_MAX; + _max_observed_digital = 0; } - } -void SteeringSystem::evaluate_steering(const uint32_t analog_raw, const SteeringEncoderReading_s digital_data, const uint32_t current_millis) { +void SteeringSystem::evaluate_steering(const uint32_t analog_raw, const SteeringEncoderReading_s digital_data, const uint32_t current_millis) +{ // Reset flags - _steeringSystemData.digital_oor_implausibility = false; - _steeringSystemData.analog_oor_implausibility = false; - _steeringSystemData.sensor_disagreement_implausibility = false; - _steeringSystemData.dtheta_exceeded_analog = false; - _steeringSystemData.dtheta_exceeded_digital = false; - _steeringSystemData.both_sensors_fail = false; + _system_data.digital_oor_implausibility = false; + _system_data.analog_oor_implausibility = false; + _system_data.sensor_disagreement_implausibility = false; + _system_data.dtheta_exceeded_analog = false; + _system_data.dtheta_exceeded_digital = false; + _system_data.both_sensors_fail = false; const uint32_t digital_raw = digital_data.rawValue; + _system_data.interface_sensor_error = (digital_data.status == SteeringEncoderStatus_e::ERROR); + _system_data.digital_raw = digital_raw; - SteeringEncoderStatus_e digital_status = digital_data.status; - bool digital_fault = (digital_status == SteeringEncoderStatus_e::ERROR); - _steeringSystemData.interface_sensor_error = digital_fault; - _steeringSystemData.digital_raw = digital_raw; - - _steeringSystemData.analog_raw = analog_raw; + _system_data.analog_raw = analog_raw; _analog_angle_unfiltered = _convert_analog_sensor(analog_raw); - //Conversion from raw ADC to degrees - _steeringSystemData.digital_steering_angle = _convert_digital_sensor(digital_raw); + // Conversion from raw ADC to degrees + _system_data.digital_steering_angle = _convert_digital_sensor(digital_raw); uint32_t dt = 0; - if (current_millis - _prev_timestamp > 2) { + if (current_millis - _prev_timestamp >= 2) + { dt = current_millis - _prev_timestamp; //current_millis is seperate data input   } - if (!_first_run) { //check that we not on the first run which would mean no previous data - - - if (dt >= 2) { + if (!_first_run) // Check that we not on the first run which would mean no previous data + { + if (dt >= 2) + { float filtered_analog_angle = _filter_analog_angle(_analog_angle_unfiltered); - _steeringSystemData.analog_steering_angle = filtered_analog_angle; // update the angle to the filtered value for downstream use and velocity calculation + _system_data.analog_steering_angle = filtered_analog_angle; // Update the angle to the filtered value for downstream use and velocity calculation float dtheta_analog = filtered_analog_angle - _prev_analog_vel_angle; - float dtheta_digital = _steeringSystemData.digital_steering_angle - _prev_digital_vel_angle; - - _steeringSystemData.analog_steering_velocity_deg_s = (dtheta_analog / static_cast(dt)) * 1000.0f; // NOLINT 1000.0f is result of converting dt in millis to seconds + float dtheta_digital = _system_data.digital_steering_angle - _prev_digital_vel_angle; - _steeringSystemData.digital_steering_velocity_deg_s = (dtheta_digital / static_cast(dt)) * 1000.0f; // NOLINT 1000.0f is result of converting dt in millis to seconds + _system_data.analog_steering_velocity_deg_s = (dtheta_analog / static_cast(dt)) * 1000.0f; // NOLINT 1000.0f is result of converting dt in millis to seconds + _system_data.digital_steering_velocity_deg_s = (dtheta_digital / static_cast(dt)) * 1000.0f; // NOLINT 1000.0f is result of converting dt in millis to seconds _last_filtered_analog_angle = filtered_analog_angle; - } else { - _steeringSystemData.analog_steering_angle = _last_filtered_analog_angle; + } + else + { + _system_data.analog_steering_angle = _last_filtered_analog_angle; } - - //Check if either sensor moved too much in one tick - _steeringSystemData.dtheta_exceeded_analog = _evaluate_steering_dtheta_exceeded(_steeringSystemData.analog_steering_velocity_deg_s); - _steeringSystemData.dtheta_exceeded_digital = _evaluate_steering_dtheta_exceeded(_steeringSystemData.digital_steering_velocity_deg_s); // use digital velocity for dtheta check since it's more precise and we are concerned about large changes in angle that could be caused by noise in the analog sensor - - //Check if either sensor is out of range (pass in raw) - _steeringSystemData.analog_oor_implausibility = _evaluate_steering_oor_analog(static_cast(analog_raw)); - _steeringSystemData.digital_oor_implausibility = _evaluate_steering_oor_digital(static_cast(digital_raw)); - - //Check if there is too much of a difference between sensor values - float sensor_difference = std::fabs(_steeringSystemData.analog_steering_angle - _steeringSystemData.digital_steering_angle); - bool sensors_agree = (sensor_difference <= _steeringParams.error_between_sensors_tolerance); //steeringParams.error - _steeringSystemData.sensor_disagreement_implausibility = !sensors_agree; - - //create an algorithm/ checklist to determine which sensor we trust more, - //or, if we should have an algorithm to have a weighted calculation based on both values - bool analog_valid = !_steeringSystemData.analog_oor_implausibility && !_steeringSystemData.dtheta_exceeded_analog; - bool digital_valid = !_steeringSystemData.digital_oor_implausibility && !_steeringSystemData.dtheta_exceeded_digital && !_steeringSystemData.interface_sensor_error; - - if (analog_valid && digital_valid) { - //if sensors have acceptable difference, use digital as steering angle - if (sensors_agree) { - _steeringSystemData.output_steering_angle = _steeringSystemData.digital_steering_angle; - } else { - _steeringSystemData.output_steering_angle = _steeringSystemData.digital_steering_angle; //default to original, but we need to consider what we really want to put here + // Check if either sensor moved too much in one tick + _system_data.dtheta_exceeded_analog = _evaluate_steering_dtheta_exceeded(_system_data.analog_steering_velocity_deg_s); + _system_data.dtheta_exceeded_digital = _evaluate_steering_dtheta_exceeded(_system_data.digital_steering_velocity_deg_s); // use digital velocity for dtheta check since it's more precise and we are concerned about large changes in angle that could be caused by noise in the analog sensor + + // Check if either sensor is out of range (pass in raw) + _system_data.analog_oor_implausibility = _evaluate_steering_oor_analog(analog_raw); + _system_data.digital_oor_implausibility = _evaluate_steering_oor_digital(digital_raw); + + // Check if there is too much of a difference between sensor values + float sensor_difference = std::fabs(_system_data.analog_steering_angle - _system_data.digital_steering_angle); + bool sensors_agree = (sensor_difference <= _params.error_between_sensors_tolerance); //steeringParams.error + _system_data.sensor_disagreement_implausibility = !sensors_agree; + + // Create an algorithm/checklist to determine which sensor we trust more, + // or, if we should have an algorithm to have a weighted calculation based on both values + bool analog_valid = !_system_data.analog_oor_implausibility && !_system_data.dtheta_exceeded_analog; + bool digital_valid = !_system_data.digital_oor_implausibility && !_system_data.dtheta_exceeded_digital && !_system_data.interface_sensor_error; + + if (analog_valid && digital_valid) + { + /// NOTE: This is currently not doing anything essentially. It doesn't matter whether or not sensors agree. + // If sensors have acceptable difference, use digital as steering angle + if (sensors_agree) + { + _system_data.output_steering_angle = _system_data.digital_steering_angle; + } + else + { + _system_data.output_steering_angle = _system_data.digital_steering_angle; // Default to original, but we need to consider what we really want to put here } - } else if (analog_valid) { - _steeringSystemData.output_steering_angle = _steeringSystemData.analog_steering_angle; - } else if (digital_valid) { - _steeringSystemData.output_steering_angle = _steeringSystemData.digital_steering_angle; - } else { // if both sensors fail - _steeringSystemData.output_steering_angle = _prev_digital_angle; - _steeringSystemData.both_sensors_fail = true; + } + else if (analog_valid) + { + _system_data.output_steering_angle = _system_data.analog_steering_angle; + } + else if (digital_valid) + { + _system_data.output_steering_angle = _system_data.digital_steering_angle; + } else // if both sensors fail + { + _system_data.output_steering_angle = _prev_digital_angle; + _system_data.both_sensors_fail = true; } } - //Update states - if (dt >= 2) { // update at 500Hz + + // Update states, 500Hz + if (dt >= 2) + { _prev_timestamp = current_millis; - _prev_analog_vel_angle = _steeringSystemData.analog_steering_angle; - _prev_digital_vel_angle = _steeringSystemData.digital_steering_angle; + _prev_analog_vel_angle = _system_data.analog_steering_angle; + _prev_digital_vel_angle = _system_data.digital_steering_angle; } - _prev_analog_angle = _steeringSystemData.analog_steering_angle; - _prev_digital_angle = _steeringSystemData.digital_steering_angle; + _prev_analog_angle = _system_data.analog_steering_angle; + _prev_digital_angle = _system_data.digital_steering_angle; _first_run = false; } -void SteeringSystem::update_observed_steering_limits(const uint32_t analog_raw, const uint32_t digital_raw) { +void SteeringSystem::update_observed_steering_limits(const uint32_t analog_raw, const uint32_t digital_raw) +{ + _min_observed_analog = std::min(_min_observed_analog, analog_raw); + _max_observed_analog = std::max(_max_observed_analog, analog_raw); + _min_observed_digital = std::min(_min_observed_digital, digital_raw); //NOLINT should both be uint32_t + _max_observed_digital = std::max(_max_observed_digital, digital_raw); //NOLINT ^ - min_observed_analog = std::min(min_observed_analog, static_cast(analog_raw)); - max_observed_analog = std::max(max_observed_analog, static_cast(analog_raw)); - min_observed_digital = std::min(min_observed_digital, static_cast(digital_raw)); //NOLINT should both be uint32_t - max_observed_digital = std::max(max_observed_digital, static_cast(digital_raw)); //NOLINT ^ - if (min_observed_analog < 5) // NOLINT want to prevent sticking at 0 or clipping with small value + if (_min_observed_analog < 5) // NOLINT want to prevent sticking at 0 or clipping with small value { - min_observed_analog = UINT32_MAX; // clipping if it is at 0, it is likely sensor is clipping or clipped in past and reading is holding the 0 value. + _min_observed_analog = UINT32_MAX; // clipping if it is at 0, it is likely sensor is clipping or clipped in past and reading is holding the 0 value. } - if (max_observed_analog > 3675) // NOLINT prevents clipping, this is slightly less than calculated value of actual max output of sensor with current resistor divider on VCF's ADC + if (_max_observed_analog > 3675) // NOLINT prevents clipping, this is slightly less than calculated value of actual max output of sensor with current resistor divider on VCF's ADC { - max_observed_analog = 0; // clipping + _max_observed_analog = 0; // clipping } - if (min_observed_digital < 10) // NOLINT want to prevent sticking at 0 or clipping + if (_min_observed_digital < 10) // NOLINT want to prevent sticking at 0 or clipping { - min_observed_digital = UINT32_MAX; // clipping on prior run. + _min_observed_digital = UINT32_MAX; // clipping on prior run. } - if (max_observed_digital > 16374) // NOLINT 16374 = 2^14 - 10 to prevent clipping with 14 bit resolution on sensor + if (_max_observed_digital > 16374) // NOLINT 16374 = 2^14 - 10 to prevent clipping with 14 bit resolution on sensor { - max_observed_digital = 0; // clipping + _max_observed_digital = 0; // clipping } } -float SteeringSystem::_convert_digital_sensor(const uint32_t digital_raw) { - // Same logic for digital - const int32_t offset = _steeringParams.digital_midpoint-static_cast(digital_raw); //NOLINT - return static_cast(offset) * _steeringParams.deg_per_count_digital; // bc diital sensor is flipped +float SteeringSystem::_convert_digital_sensor(const uint32_t digital_raw) +{ + const int32_t offset = _params.digital_midpoint-static_cast(digital_raw); //NOLINT + return static_cast(offset) * _params.deg_per_count_digital; // bc diital sensor is flipped } -float SteeringSystem::_convert_analog_sensor(const uint32_t analog_raw) { +float SteeringSystem::_convert_analog_sensor(const uint32_t analog_raw) +{ // Get the raw value - const int32_t offset = static_cast(analog_raw) - _steeringParams.analog_midpoint; //NOLINT - return static_cast(offset) * _steeringParams.deg_per_count_analog; + const int32_t offset = static_cast(analog_raw) - _params.analog_midpoint; //NOLINT + return static_cast(offset) * _params.deg_per_count_analog; } -bool SteeringSystem::_evaluate_steering_oor_analog(const uint32_t steering_analog_raw) { // RAW - return (static_cast(steering_analog_raw) < _steeringParams.analog_min_with_margins || static_cast(steering_analog_raw) > _steeringParams.analog_max_with_margins); +bool SteeringSystem::_evaluate_steering_oor_analog(const uint32_t steering_analog_raw) // RAW +{ + return (static_cast(steering_analog_raw) < _params.analog_min_with_margins || static_cast(steering_analog_raw) > _params.analog_max_with_margins); } -bool SteeringSystem::_evaluate_steering_oor_digital(const uint32_t steering_digital_raw) {// RAW - return (static_cast(steering_digital_raw) < _steeringParams.digital_min_with_margins || static_cast(steering_digital_raw) > _steeringParams.digital_max_with_margins); +bool SteeringSystem::_evaluate_steering_oor_digital(const uint32_t steering_digital_raw) // RAW +{ + return (static_cast(steering_digital_raw) < _params.digital_min_with_margins || static_cast(steering_digital_raw) > _params.digital_max_with_margins); } -bool SteeringSystem::_evaluate_steering_dtheta_exceeded(float steering_velocity_deg_s) { - return (fabs(steering_velocity_deg_s) > _steeringParams.max_dtheta_threshold); +bool SteeringSystem::_evaluate_steering_dtheta_exceeded(float steering_velocity_deg_s) +{ + return (std::fabs(steering_velocity_deg_s) > _params.max_dtheta_threshold); } -float SteeringSystem::_filter_analog_angle(float x) { +float SteeringSystem::_filter_analog_angle(float x) +{ // First sample: pre-load the state so the output starts at x and // there is no startup transient (otherwise the filter would ramp // from 0 up to the first real value over ~50 ms). - if (!_bw_initialized) { + if (!_bw_initialized) + { _bw_z1 = (1.0f - kBwB0) * x; _bw_z2 = (kBwB2 - kBwA2) * x; _bw_initialized = true; } + // Direct Form II Transposed biquad: 5 multiplies, 4 adds, 2 floats of state. float y = kBwB0 * x + _bw_z1; _bw_z1 = kBwB1 * x - kBwA1 * y + _bw_z2; From ea632e0978aab1598e973baf0c95d218d2bc12a3 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Thu, 25 Jun 2026 16:17:22 -0700 Subject: [PATCH 09/10] VCR Interface --- lib/interfaces/include/VCRInterface.h | 87 +++++++++++++++------------ lib/interfaces/src/VCRInterface.cpp | 13 ++-- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/lib/interfaces/include/VCRInterface.h b/lib/interfaces/include/VCRInterface.h index ed58411..b9a9d9b 100644 --- a/lib/interfaces/include/VCRInterface.h +++ b/lib/interfaces/include/VCRInterface.h @@ -1,68 +1,81 @@ #ifndef VCR_INTERFACE_H #define VCR_INTERFACE_H -#include "SharedFirmwareTypes.h" -#include "Arduino.h" -#include "BuzzerController.h" +/* ETL Library */ #include "etl/singleton.h" + +/* External Includes */ +#include "Arduino.h" +#include "SharedFirmwareTypes.h" #include "hytech.h" #include "FlexCAN_T4.h" -struct InverterErrorFlags_s{ +/* Local System Includes */ +#include "BuzzerController.h" +struct InverterErrorFlags_s +{ veh_vec error; - }; -struct InverterBusVolts_s{ +struct InverterBusVolts_s +{ veh_vec voltage; }; -class VCRInterface +class VCRInterface { - public: +public: - bool is_in_pedals_calibration_state() {return _is_in_pedals_calibration_state;} - TorqueLimit_e get_torque_limit_mode() {return _torque_limit;} - - bool is_in_steering_calibration_state() {return _is_in_steering_calibration_state;} //steering and pedals calibration states are the same, so we can use the same variable for both + void receive_dash_control_data(const CAN_message_t &can_msg); - void receive_dash_control_data(const CAN_message_t &can_msg); + void receive_car_states_data(const CAN_message_t &can_msg); - void disable_calibration_state() {_is_in_pedals_calibration_state = false;} + void receive_inverter_status_1(const CAN_message_t &can_msg); - void disable_steering_calibration_state() {_is_in_steering_calibration_state = false;} + void receive_inverter_status_2(const CAN_message_t &can_msg); - void receive_car_states_data(const CAN_message_t &can_msg); + void receive_inverter_status_3(const CAN_message_t &can_msg); - void receive_inverter_status_1(const CAN_message_t &can_msg); + void receive_inverter_status_4(const CAN_message_t &can_msg); - void receive_inverter_status_2(const CAN_message_t &can_msg); + /* State Observation + Control */ + bool is_in_pedals_calibration_state() { return _is_in_pedals_calibration_state; } - void receive_inverter_status_3(const CAN_message_t &can_msg); + bool is_in_steering_calibration_state() { return _is_in_steering_calibration_state; } //steering and pedals calibration states are the same, so we can use the same variable for both - void receive_inverter_status_4(const CAN_message_t &can_msg); + void disable_calibration_state() {_is_in_pedals_calibration_state = false;} + void disable_steering_calibration_state() {_is_in_steering_calibration_state = false;} - VehicleState_e get_vehicle_state() {return _vehicle_state_value;} - DrivetrainState_e get_drivetrain_state() {return _drivetrain_state_value;} - InverterBusVolts_s get_dc_bus_voltage() {return _bus_voltages;} - bool get_db_in_ctrl() {return _is_db_in_ctrl;} - bool get_inverter_error(); + /* Getters */ + VehicleState_e get_vehicle_state() const { return _vehicle_state_value; } - private: + DrivetrainState_e get_drivetrain_state() const { return _drivetrain_state_value; } - bool _is_in_pedals_calibration_state = false; - bool _is_in_steering_calibration_state = false; - VehicleState_e _vehicle_state_value; - DrivetrainState_e _drivetrain_state_value; - bool _is_db_in_ctrl; - TorqueLimit_e _torque_limit = TorqueLimit_e::TCMUX_LOW_TORQUE; - InverterErrorFlags_s _inv_error_status; //creates object that reflects the inverter error status...the object - //holds the error flags for each inverter, the getter above returns True if there's an error in any of the 4 - InverterBusVolts_s _bus_voltages; -}; + InverterBusVolts_s get_dc_bus_voltage() const { return _bus_voltages; } + + TorqueLimit_e get_torque_limit_mode() const { return _torque_limit; } + + bool get_db_in_ctrl() const { return _is_db_in_ctrl; } + + bool get_inverter_error() ; +private: + + bool _is_in_pedals_calibration_state = false; + bool _is_in_steering_calibration_state = false; + bool _is_db_in_ctrl; + VehicleState_e _vehicle_state_value; + DrivetrainState_e _drivetrain_state_value; + TorqueLimit_e _torque_limit = TorqueLimit_e::TCMUX_LOW_TORQUE; + InverterBusVolts_s _bus_voltages; + + // Creates object that reflects the inverter error status...the object holds the error flags for each inverter, + // the getter above returns True if there's an error in any of the 4 + InverterErrorFlags_s _inv_error_status; + +}; using VCRInterfaceInstance = etl::singleton; -#endif /* VCR_INTERFACE_H */ +#endif /* VCR_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/src/VCRInterface.cpp b/lib/interfaces/src/VCRInterface.cpp index 85b80d5..0a25cbd 100644 --- a/lib/interfaces/src/VCRInterface.cpp +++ b/lib/interfaces/src/VCRInterface.cpp @@ -3,9 +3,10 @@ void VCRInterface::receive_dash_control_data(const CAN_message_t &can_msg) { DASHBOARD_BUZZER_CONTROL_t unpacked_msg; - Unpack_DASHBOARD_BUZZER_CONTROL_hytech(&unpacked_msg, can_msg.buf, can_msg.len); //NOLINT + Unpack_DASHBOARD_BUZZER_CONTROL_hytech(&unpacked_msg, can_msg.buf, can_msg.len); //NOLINT - if (unpacked_msg.dash_buzzer_flag) { + if (unpacked_msg.dash_buzzer_flag) + { BuzzerController::getInstance().activate(millis()); } @@ -34,6 +35,7 @@ void VCRInterface::receive_inverter_status_1(const CAN_message_t &can_msg) _inv_error_status.error.FL = unpacked_msg.error; _bus_voltages.voltage.FL = unpacked_msg.dc_bus_voltage; } + void VCRInterface::receive_inverter_status_2(const CAN_message_t &can_msg) { INV2_STATUS_t unpacked_msg; @@ -41,6 +43,7 @@ void VCRInterface::receive_inverter_status_2(const CAN_message_t &can_msg) _inv_error_status.error.FR = unpacked_msg.error; _bus_voltages.voltage.FR = unpacked_msg.dc_bus_voltage; } + void VCRInterface::receive_inverter_status_3(const CAN_message_t &can_msg) { INV3_STATUS_t unpacked_msg; @@ -48,6 +51,7 @@ void VCRInterface::receive_inverter_status_3(const CAN_message_t &can_msg) _inv_error_status.error.RL = unpacked_msg.error; _bus_voltages.voltage.RL = unpacked_msg.dc_bus_voltage; } + void VCRInterface::receive_inverter_status_4(const CAN_message_t &can_msg) { INV4_STATUS_t unpacked_msg; @@ -59,7 +63,4 @@ void VCRInterface::receive_inverter_status_4(const CAN_message_t &can_msg) bool VCRInterface::get_inverter_error() { return _inv_error_status.error.FL || _inv_error_status.error.FR || _inv_error_status.error.RL || _inv_error_status.error.RR; -} - - - +} \ No newline at end of file From 231c275a3da4ff8648975b2dd7592ed55c17b019 Mon Sep 17 00:00:00 2001 From: Anthony Liu Date: Mon, 29 Jun 2026 21:20:43 -0700 Subject: [PATCH 10/10] Split into interface and system tasks, plz work --- .clang-tidy | 1 + getcompilecommands.sh | 4 - include/VCF_Constants.h | 122 ++--- include/VCF_InterfaceTasks.h | 64 +-- include/VCF_SystemTasks.h | 33 ++ lib/interfaces/include/ACUInterface.h | 16 +- lib/interfaces/include/ADCInterface.h | 373 +++++++------- .../include/BrakeRotorTempInterface.h | 50 +- lib/interfaces/include/DashboardInterface.h | 101 ++-- lib/interfaces/include/OrbisInterface.h | 125 ++--- lib/interfaces/include/SystemTimeInterface.h | 6 +- lib/interfaces/include/VCFCANInterfaceImpl.h | 23 +- lib/interfaces/include/VCFEthernetInterface.h | 25 +- lib/interfaces/include/VCRInterface.h | 7 +- lib/interfaces/include/WatchdogInterface.h | 78 +++ lib/interfaces/src/ACUInterface.cpp | 1 + lib/interfaces/src/ADCInterface.cpp | 197 ++++---- lib/interfaces/src/DashboardInterface.cpp | 12 +- lib/interfaces/src/OrbisInterface.cpp | 149 +++--- lib/interfaces/src/SystemTimeInterface.cpp | 12 +- lib/interfaces/src/VCFEthernetInterface.cpp | 24 +- lib/interfaces/src/WatchdogInterface.cpp | 25 + lib/systems/include/BuzzerController.h | 14 +- .../{EEPROMUtils.h => EEPROMUtilities.h} | 5 +- ...OExpanderUtils.h => IOExpanderUtilities.h} | 8 +- lib/systems/include/NeopixelController.h | 17 +- lib/systems/include/SteeringSystem.h | 45 +- lib/systems/include/WatchdogSystem.h | 39 -- ...anderUtils.cpp => IOExpanderUtilities.cpp} | 5 +- lib/systems/src/NeopixelController.cpp | 5 +- lib/systems/src/WatchdogSystem.cpp | 15 - platformio.ini | 302 ++++------- src/VCF_InterfaceTasks.cpp | 471 ++++++------------ src/VCF_SystemTasks.cpp | 161 ++++++ src/main.cpp | 94 ++-- 35 files changed, 1329 insertions(+), 1300 deletions(-) delete mode 100755 getcompilecommands.sh create mode 100644 lib/interfaces/include/WatchdogInterface.h create mode 100644 lib/interfaces/src/WatchdogInterface.cpp rename lib/systems/include/{EEPROMUtils.h => EEPROMUtilities.h} (95%) rename lib/systems/include/{IOExpanderUtils.h => IOExpanderUtilities.h} (76%) delete mode 100644 lib/systems/include/WatchdogSystem.h rename lib/systems/src/{IOExpanderUtils.cpp => IOExpanderUtilities.cpp} (68%) delete mode 100644 lib/systems/src/WatchdogSystem.cpp diff --git a/.clang-tidy b/.clang-tidy index bd77198..319b4ee 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,7 @@ Checks: 'bugprone-*, cppcoreguidelines-*, readability-identifier-naming, -cppcoreguidelines-avoid-non-const-global-variables, -bugprone-branch-clone, -cppcoreguidelines-pro-type-vararg, -bugprone-easily-swappable-parameters, -cppcoreguidelines-avoid-c-arrays' WarningsAsErrors: 'cppcoreguidelines-*, bugprone-*, readability-identifier-naming' FormatStyle: 'file' +SystemHeaders: false CheckOptions: - { key: readability-identifier-naming.ClassMemberCase, value: 'lower_case' } - { key: readability-identifier-naming.ClassMemberPrefix, value: '_' } diff --git a/getcompilecommands.sh b/getcompilecommands.sh deleted file mode 100755 index 1c99bcb..0000000 --- a/getcompilecommands.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -set -o pipefail -pio run -e teensy41 -pio run -t compiledb -e teensy41 \ No newline at end of file diff --git a/include/VCF_Constants.h b/include/VCF_Constants.h index 26bb991..a3917e0 100644 --- a/include/VCF_Constants.h +++ b/include/VCF_Constants.h @@ -1,19 +1,21 @@ #ifndef VCF_CONSTANTS #define VCF_CONSTANTS -#include -#include +/* External Includes */ +#include "SharedFirmwareTypes.h" +using pin = uint8_t; using degree = float; +using time_us = uint32_t; -namespace VCFInterfaceConstants +namespace VCFInterfaces { /* Serial */ constexpr size_t SERIAL_BAUDRATE = 115200; /* IIR Filter Alphas */ constexpr float LOADCELL_IIR_FILTER_ALPHA = 0.01f; - + /* ADC chip selects */ constexpr int ADC0_CS = 10; // MCP3208 — steering, sus pots, load cells constexpr int ADC1_CS = 38; // MCP3208 — pedal position sensors @@ -93,21 +95,20 @@ namespace VCFInterfaceConstants constexpr int BTN_MC_CYCLE_READ = 31; // DB/MC_RESET on schematic constexpr int BUZZER_CONTROL_PIN = 32; - // watchdog pins - constexpr int WATCHDOG_PIN = 36; - constexpr int SOFTWARE_OK_PIN = 37; // Watchdog's !MR pin - - // watchdog kick interval - constexpr unsigned long WATCHDOG_KICK_INTERVAL_MS = 10UL; // 10 ms = 100 Hz - - /* CAN baudrates */ - constexpr uint32_t TELEM_CAN_BAUDRATE = 1000000; // 1 000 000 = 1 Mbit/s - constexpr uint32_t FAUX_CAN_BAUDRATE = 500000; // 500 000 = 500 Kbit/s + /* Watchdog Interface */ + constexpr pin WATCHDOG_KICK_PIN = 36; + constexpr pin SOFTWARE_OK_PIN = 37; // Watchdog's !MR pin } // calibration and processing constants -namespace VCFSystemConstants +namespace VCFSystems { + /* IO Expander */ + constexpr uint8_t IO_EXPANDER_ADDR = 0x20; + + /* Neopixel Controller */ + constexpr int NEOPIXEL_CONTROL_PIN = 33; + constexpr int NEOPIXEL_COUNT = 16; // 16 neopixeles on dashboard /* EEPROM addresses */ constexpr uint32_t ACCEL_1_MIN_ADDR = 0; @@ -120,8 +121,18 @@ namespace VCFSystemConstants constexpr uint32_t BRAKE_1_MAX_ADDR = 24; constexpr uint32_t BRAKE_2_MAX_ADDR = 28; - // Steering System Constants + constexpr uint32_t ACCEL_MIN_SENSOR_PEDAL_1 = 90; + constexpr uint32_t ACCEL_MIN_SENSOR_PEDAL_2 = 90; + constexpr uint32_t ACCEL_MAX_SENSOR_PEDAL_1 = 4000; + constexpr uint32_t ACCEL_MAX_SENSOR_PEDAL_2 = 4000; + + constexpr uint32_t BRAKE_MIN_SENSOR_PEDAL_1 = 90; + constexpr uint32_t BRAKE_MIN_SENSOR_PEDAL_2 = 90; + constexpr uint32_t BRAKE_MAX_SENSOR_PEDAL_1 = 4000; + constexpr uint32_t BRAKE_MAX_SENSOR_PEDAL_2 = 4000; + + // Steering System Constants /* Steering */ constexpr float ANALOG_TOLERANCE = 0.05f; // +/- 5% sensor tolerance constexpr float DIGITAL_TOLERANCE = 0.05f; // +/- 0.2 degree error @@ -151,67 +162,66 @@ namespace VCFSystemConstants /* Load cells */ constexpr float LBS_TO_NEWTONS = 4.4482216153f; - - /* IO Expander */ - constexpr uint8_t IO_EXPANDER_ADDR = 0x20; - - /* Neopixel */ - constexpr int NEOPIXEL_CONTROL_PIN = 33; - constexpr int NEOPIXEL_COUNT = 16; // 16 neopixeles on dashboard } // software configuration constants namespace VCFConstants { - /* Task Times */ - constexpr uint16_t WATCHDOG_PRIORITY = 1; - constexpr uint32_t WATCHDOG_KICK_PERIOD_US = 10000; // 10 000 us = 100 Hz + constexpr uint8_t WATCHDOG_PRIORITY = 1; + constexpr time_us WATCHDOG_KICK_PERIOD_US = 10000; // 10 000 us = 100 Hz + + constexpr uint8_t ASYNC_MAIN_PRIORITY = 2; + constexpr time_us ASYNC_MAIN_PERIOD_US = 100; // 100 us = 10 kHz + + constexpr uint8_t PEDALS_SAMPLE_PRIORITY = 3; + constexpr time_us PEDALS_SAMPLE_PERIOD_US = 500; // 500 us = 2 kHz - constexpr uint16_t PEDALS_SAMPLE_PRIORITY = 2; - constexpr uint32_t PEDALS_SAMPLE_PERIOD_US = 500; // 500 us = 2 kHz + constexpr uint8_t STEERING_SAMPLE_PRIORITY = 4; + constexpr time_us STEERING_SAMPLE_PERIOD_US = 1000; // 1 000 us = 1 kHz - constexpr uint16_t STEERING_SAMPLE_PRIORITY = 3; - constexpr uint32_t STEERING_SAMPLE_PERIOD_US = 1000; // 1 000 us = 1 kHz + constexpr uint8_t LOADCELL_SAMPLE_PRIORITY = 5; + constexpr time_us LOADCELL_SAMPLE_PERIOD_US = 250; // 250 us = 4 kHz - constexpr uint16_t LOADCELL_SAMPLE_PRIORITY = 4; - constexpr uint32_t LOADCELL_SAMPLE_PERIOD_US = 250; // 250 us = 4 kHz + constexpr uint8_t PEDALS_SEND_PRIORITY = 6; + constexpr time_us PEDALS_SEND_PERIOD_US = 4000; // 4 000 us = 250 Hz - constexpr uint16_t PEDALS_SEND_PRIORITY = 5; - constexpr uint32_t PEDALS_SEND_PERIOD_US = 4000; // 4 000 us = 250 Hz + constexpr uint8_t STEERING_SEND_PRIORITY = 7; + constexpr time_us STEERING_SEND_PERIOD_US = 4000; // 4 000 us = 250 Hz - constexpr uint16_t STEERING_SEND_PRIORITY = 6; - constexpr uint32_t STEERING_SEND_PERIOD_US = 4000; // 4 000 us = 250 Hz + constexpr uint8_t LOADCELL_SEND_PRIORITY = 8; + constexpr time_us LOADCELL_SEND_PERIOD_US = 4000; // 4 000 = 250 Hz - constexpr uint16_t LOADCELL_SEND_PRIORITY = 7; - constexpr uint32_t LOADCELL_SEND_PERIOD_US = 4000; // 4 000 = 250 Hz + constexpr uint8_t CAN_SEND_PRIORITY = 9; + constexpr time_us CAN_SEND_PERIOD_US = 2000; // 2 000 us = 500 Hz - constexpr uint16_t CAN_SEND_PRIORITY = 8; - constexpr uint32_t CAN_SEND_PERIOD_US = 2000; // 2 000 us = 500 Hz + constexpr uint8_t DASH_SEND_PRIORITY = 10; + constexpr time_us DASH_SEND_PERIOD_US = 100000; // 100 000 us = 10 Hz - constexpr uint16_t DASH_SEND_PRIORITY = 9; - constexpr uint32_t DASH_SEND_PERIOD_US = 100000; // 100 000 us = 10 Hz + constexpr uint8_t DASH_SAMPLE_PRIORITY = 11; + constexpr time_us DASH_SAMPLE_PERIOD_US = 100000; // 100 000 us = 10 Hz - constexpr uint16_t DASH_SAMPLE_PRIORITY = 10; - constexpr uint32_t DASH_SAMPLE_PERIOD_US = 100000; // 100 000 us = 10 Hz + constexpr uint8_t ETHERNET_SEND_PRIORITY = 12; + constexpr time_us ETHERNET_SEND_PERIOD_US = 100000; // 100 000 us = 10Hz - constexpr uint16_t ETHERNET_SEND_PRIORITY = 11; - constexpr uint32_t ETHERNET_SEND_PERIOD = 100000; // 100 000 us = 10Hz + constexpr uint8_t BUZZER_PRIORITY = 13; + constexpr time_us BUZZER_WRITE_PERIOD_US = 100000; // 100 000 us = 10 Hz - constexpr uint16_t BUZZER_PRIORITY = 12; - constexpr uint32_t BUZZER_WRITE_PERIOD_US = 100000; // 100 000 us = 10 Hz + constexpr uint8_t NEOPIXEL_UPDATE_PRIORITY = 14; + constexpr time_us NEOPIXEL_UPDATE_PERIOD_US = 100000; // 100 000 us = 10 Hz - constexpr uint16_t NEOPIXEL_UPDATE_PRIORITY_US = 13; - constexpr uint32_t NEOPIXEL_UPDATE_PERIOD_US = 100000; // 100 000 us = 10 Hz + constexpr uint8_t PEDALS_RECALIBRATION_PRIORITY = 20; + constexpr time_us PEDALS_RECALIBRATION_PERIOD_US = 100000; // 100 000 us = 10 Hz - constexpr uint16_t PEDALS_RECALIBRATION_PRIORITY = 20; - constexpr uint32_t PEDALS_RECALIBRATION_PERIOD = 100000; // 100 000 us = 10 Hz + constexpr uint8_t STEERING_RECALIBRATION_PRIORITY = 21; + constexpr time_us STEERING_RECALIBRATION_PERIOD_US = 100000; // 100 000 us = 10 Hz - constexpr uint16_t STEERING_RECALIBRATION_PRIORITY = 21; - constexpr uint32_t STEERING_RECALIBRATION_PERIOD = 100000; // 100 000 us = 10 Hz + constexpr uint8_t DEBUG_PRIORITY = 50; + constexpr time_us DEBUG_PERIOD_US = 10000; // 10 000 us = 2 Hz - constexpr uint16_t DEBUG_PRIORITY = 50; - constexpr uint32_t DEBUG_PERIOD_US = 10000; // 10 000 us = 2 Hz + /* CAN Constants */ + constexpr uint32_t TELEM_CAN_BAUDRATE = 1000000; // 1 000 000 = 1 Mbit/s + constexpr uint32_t FAUX_CAN_BAUDRATE = 500000; // 500 000 = 500 Kbit/s } #endif /* VCF_CONSTANTS */ diff --git a/include/VCF_InterfaceTasks.h b/include/VCF_InterfaceTasks.h index b2ca95a..7dd888c 100644 --- a/include/VCF_InterfaceTasks.h +++ b/include/VCF_InterfaceTasks.h @@ -1,37 +1,11 @@ -/** - * This file includes all of the Task definitions required for the Task - * Scheduler. See the Task Scheduler GitHub - * (https://github.com/hytech-racing/HT_SCHED) and the relevant BookStack page - * (https://wiki.hytechracing.org/books/ht09-design/page/ht-task-scheduler) for - * usage directions. - * - * Generally, defining a task takes three steps: - * 1) Define the "init" function. Name this function init_. This init - * funciton's inputs MUST be the same for all init functions, taking in - * sysMicros and a taskInfo reference. 2) Define the "run" function. Name this - * function run_. Similar to the init function, this function's inputs - * MUST be sysMicros and taskInfo. 3) Define the function itself. This requires - * using the HT_TASK::Task constructor and passing in your init function, your - * run function, a priority level, and a loop interval (in micros). 4) Add the - * function to your scheduler. - * - */ - -/* -------------------------------------------------- */ -/* TASK PRIORITIES */ -/* -------------------------------------------------- */ -/* - * (1-10) - Car-critical functions (watchdog, shutdown circuit) - * (11-100) - Performance-critical functions (reading pedals, interfacing w/ - * inverters, etc) (100+) - Telemetry, logging functions (could be idle - * functions, too) - */ - #ifndef VCF_INTERFACETASKS #define VCF_INTERFACETASKS #include "VCF_Constants.h" -#include "SharedFirmwareTypes.h" + +/* External Includes */ +#include +#include "CANInterface.h" /* Local Interface Includes */ #include "ACUInterface.h" @@ -43,10 +17,11 @@ #include "VCFCANInterfaceImpl.h" #include "VCFEthernetInterface.h" #include "VCRInterface.h" +#include "WatchdogInterface.h" + +/* Local System Includes */ +#include "NeopixelController.h" -/* Scheduling */ -#include "ht_sched.hpp" -#include /** * Init Functions - to be called in setup@ @@ -57,26 +32,23 @@ void initialize_all_interfaces(); * The read_adc0 task will command the ADCInterface to sample, convert, and store * data from all eight channels of adc0. */ -HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); +::HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); /** * The read_adc0 task will command the ADCInterface to sample, convert, and store * data from all eight channels of adc1. */ -HT_TASK::TaskResponse run_read_adc1_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); +::HT_TASK::TaskResponse run_read_adc1_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -HT_TASK::TaskResponse init_kick_watchdog(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -HT_TASK::TaskResponse run_kick_watchdog(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -HT_TASK::TaskResponse update_pedals_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); +::HT_TASK::TaskResponse run_kick_watchdog(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -HT_TASK::TaskResponse update_steering_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); /** * The buzzer_control task will control the buzzer control pin. This function * relies on the buzzer_control pin definition in VCF_Constants.h; */ -HT_TASK::TaskResponse init_buzzer_control_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -HT_TASK::TaskResponse run_buzzer_control_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); +::HT_TASK::TaskResponse init_buzzer_control_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); +::HT_TASK::TaskResponse run_buzzer_control_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); /** * The handle_send_VCF_ethernet_data task will send a protobuf message from VCF @@ -95,20 +67,14 @@ HT_TASK::TaskResponse handle_CAN_send(const unsigned long &sysMicros, const HT_T HT_TASK::TaskResponse run_dash_GPIOs_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info); // NOLINT (capitalization of GPIOs) HT_TASK::TaskResponse send_dash_data(const unsigned long &sysMicros, const HT_TASK::TaskInfo &taskInfo); -HT_TASK::TaskResponse init_neopixels_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info); -HT_TASK::TaskResponse run_update_neopixels_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info); - HT_TASK::TaskResponse enqueue_front_suspension_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -HT_TASK::TaskResponse enqueue_pedals_data(const unsigned long &sys_micros, const HT_TASK::TaskInfo& task_info); -HT_TASK::TaskResponse enqueue_steering_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); -namespace async_tasks { +namespace async_tasks +{ // the others in the VCF Tasks can just stay there, they dont need forward declarations. HT_TASK::TaskResponse handle_async_main(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info); } -void setup_all_interfaces(); - #endif diff --git a/include/VCF_SystemTasks.h b/include/VCF_SystemTasks.h index e69de29..fd1a608 100644 --- a/include/VCF_SystemTasks.h +++ b/include/VCF_SystemTasks.h @@ -0,0 +1,33 @@ +#ifndef VCF_SYSTEMTASKS +#define VCF_SYSTEMTASKS + +#include "VCF_Constants.h" + +/* External Includes */ +#include + +/* Local System Includes */ +#include "BuzzerController.h" +#include "EEPROMUtilities.h" +#include "IOExpanderUtilities.h" +#include "NeopixelController.h" +#include "PedalsSystem.h" +#include "SteeringSystem.h" + +/** + * @brief Creates an instance of all systems. + */ +void initialize_all_systems(); + +::HT_TASK::TaskResponse enqueue_pedals_data(const unsigned long &sys_micros, const HT_TASK::TaskInfo& task_info); + +::HT_TASK::TaskResponse update_pedals_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); + +::HT_TASK::TaskResponse enqueue_steering_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); + +::HT_TASK::TaskResponse update_steering_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); + +::HT_TASK::TaskResponse update_neopixels_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo); + + +#endif \ No newline at end of file diff --git a/lib/interfaces/include/ACUInterface.h b/lib/interfaces/include/ACUInterface.h index 542c5d7..474cbec 100644 --- a/lib/interfaces/include/ACUInterface.h +++ b/lib/interfaces/include/ACUInterface.h @@ -1,19 +1,23 @@ #ifndef ACU_INTERFACE_H #define ACU_INTERFACE_H +/* ETL Library */ +#include + +/* External Includes */ #include "SharedFirmwareTypes.h" -#include "Arduino.h" -#include "etl/singleton.h" #include "hytech.h" -#include "FlexCAN_T4.h" +#include "CANInterface.h" +#include + class ACUInterface { public: - ACUCoreData_s get_last_recvd_data() {return _last_recvd_data;} + ACUCoreData_s get_last_recvd_data() { return _last_recvd_data; } - float get_cell_voltage() {return _min_cell_voltage;} + float get_cell_voltage() { return _min_cell_voltage; } void receive_ACU_voltages(const CAN_message_t &can_msg); @@ -21,7 +25,9 @@ class ACUInterface ACUCoreData_s _last_recvd_data; float _min_cell_voltage = 0; + }; + using ACUInterfaceInstance = etl::singleton; #endif /* ACU_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/include/ADCInterface.h b/lib/interfaces/include/ADCInterface.h index 2cccbe7..5bc81a6 100644 --- a/lib/interfaces/include/ADCInterface.h +++ b/lib/interfaces/include/ADCInterface.h @@ -1,20 +1,27 @@ #ifndef ADC_INTERFACE_H #define ADC_INTERFACE_H -/// @brief This file defines ADC interface. The interface instantiates the ADC modules and provides getter functions to access each sensor's values. +/* ETL Library Includes */ +#include +/* External Includes */ #include -#include "etl/singleton.h" -namespace adc_default_parameters { - constexpr const unsigned int channels_within_mcp_adc = 8; +using pin = uint8_t; + + +namespace adc_default_parameters +{ + constexpr const unsigned int channels_within_mcp_adc = 8; } -struct ADCPinout_s { - int adc0_spi_cs_pin; - int adc1_spi_cs_pin; +struct ADCPinout_s +{ + pin adc0_spi_cs_pin; + pin adc1_spi_cs_pin; }; -struct ADCChannels_s { +struct ADCChannels_s +{ /* ADC 0 */ int pedal_ref_channel; int steering_cw_channel; @@ -23,7 +30,7 @@ struct ADCChannels_s { int accel_2_channel; int brake_1_channel; int brake_2_channel; - + /* ADC 1 */ int shdn_h_channel; int shdn_d_channel; @@ -35,7 +42,8 @@ struct ADCChannels_s { int brake_pressure_rear_channel; }; -struct ADCScales_s { +struct ADCScales_s +{ /* ADC 0 */ float pedal_ref_scale; float steering_cw_scale; @@ -44,19 +52,20 @@ struct ADCScales_s { float accel_2_scale; float brake_1_scale; float brake_2_scale; - + /* ADC 1 */ float shdn_h_scale; float shdn_d_scale; float fl_loadcell_scale; float fr_loadcell_scale; - float fr_suspot_scale; float fl_suspot_scale; + float fr_suspot_scale; float brake_pressure_front_scale; float brake_pressure_rear_scale; }; -struct ADCOffsets_s { +struct ADCOffsets_s +{ /* ADC 0 */ float pedal_ref_offset; float steering_cw_offset; @@ -65,19 +74,20 @@ struct ADCOffsets_s { float accel_2_offset; float brake_1_offset; float brake_2_offset; - + /* ADC 1 */ float shdn_h_offset; float shdn_d_offset; float fl_loadcell_offset; float fr_loadcell_offset; - float fr_suspot_offset; float fl_suspot_offset; + float fr_suspot_offset; float brake_pressure_front_offset; float brake_pressure_rear_offset; }; -struct ADCInterfaceParams_s { +struct ADCInterfaceParams_s +{ ADCPinout_s pinouts; ADCChannels_s channels; ADCScales_s scales; @@ -86,167 +96,176 @@ struct ADCInterfaceParams_s { class ADCInterface { - /* ------ Public Functions ------ */ - public: - ADCInterface(ADCPinout_s pinouts, ADCChannels_s channels, ADCScales_s scales, ADCOffsets_s offsets) : - _adc_parameters { - .pinouts = pinouts, - .channels = channels, - .scales = scales, - .offsets = offsets - }, - _adc0 ( - _adc_parameters.pinouts.adc0_spi_cs_pin, - MCP_ADC_DEFAULT_SPI_SDI, - MCP_ADC_DEFAULT_SPI_SDO, - MCP_ADC_DEFAULT_SPI_CLK, - MCP_ADC_DEFAULT_SPI_SPEED, - adc0_scales().data(), - adc0_offsets().data() - ), - _adc1 ( - _adc_parameters.pinouts.adc1_spi_cs_pin, - MCP_ADC_DEFAULT_SPI_SDI, - MCP_ADC_DEFAULT_SPI_SDO, - MCP_ADC_DEFAULT_SPI_CLK, - MCP_ADC_DEFAULT_SPI_SPEED, - adc1_scales().data(), - adc1_offsets().data() - ) - {}; - - void adc0_tick(); - void adc1_tick(); - - /* ------ ADC 0 ------ */ - - /** - * @return Pedal Reference Reading - */ - AnalogConversion_s pedal_reference(); - - /** - * @return Analog Steering Degrees [Steering 1] - */ - AnalogConversion_s get_steering_degrees_cw(); - - /** - * @return Analog Steering Degrees [Steering 2] - */ - AnalogConversion_s get_steering_degrees_ccw(); - - /** - * @return Acceleration Pedal 1 - */ - AnalogConversion_s acceleration_1(); - - /** - * @return Acceleration Pedal 2 - */ - AnalogConversion_s acceleration_2(); - - /** - * @return Brake Pedal 1 - */ - AnalogConversion_s brake_1(); - - /** - * @return Brake Pedal 2 - */ - AnalogConversion_s brake_2(); - - /* ------ ADC 1 ------ */ - - /** - * @return SHDN H Voltage Sense - */ - AnalogConversion_s shdn_h(); - - /** - * @return SHDN D Voltage Sense - */ - AnalogConversion_s shdn_d(); - - /** - * @return Front Left Load Cell - */ - AnalogConversion_s FL_load_cell(); - - /** - * @return Front Right Load Cell - */ - AnalogConversion_s FR_load_cell(); - - /** - * @return Front Right Suspension Potentiometer Reading - */ - AnalogConversion_s FR_sus_pot(); - - /** - * @return Front Left Suspension Potentiometer Reading - */ - AnalogConversion_s FL_sus_pot(); - - /** - * @return Front Brake Pressure - */ - AnalogConversion_s get_brake_pressure_front(); - - /** - * @return Rear Brake Pressure - */ - AnalogConversion_s get_brake_pressure_rear(); - - /** - * @return Filtered Front Left Load Cell - */ - float get_filtered_FL_load_cell(); - - /** - * @return Filtered Front Right Load Cell - */ - float get_filtered_FR_load_cell(); - - /** - * @return Filtered Front Left Sus Pot - */ - float get_filtered_FL_sus_pot(); - - /** - * @return Filtered Front Right Sus Pot - */ - float get_filtered_FR_sus_pot(); - - /** - * Update the filtered values for the load cells and sus pots. - * Uses the iir_filter method to do so. - */ - void update_filtered_values(float alpha); - - /** - * @return updated filtered value based on given alpha, previous filtered value, and new measured value - */ - static float iir_filter(float alpha, float prev_value, float new_value); - - /* ------ Private Functions ------ */ - private: - std::array adc0_scales(); - std::array adc0_offsets(); - std::array adc1_scales(); - std::array adc1_offsets(); - - /* ------ Private Data Members ------ */ - private: - ADCInterfaceParams_s _adc_parameters = {}; - // Filtered Load Cell and Sus Pot data - float _FL_load_cell_filtered; - float _FR_load_cell_filtered; - float _FL_sus_pot_filtered; - float _FR_sus_pot_filtered; - // MCP3208. ADC0 in VCF schematic. Used for steering, pedal reference, and pedal position sensors. - MCP_ADC _adc0; - // MCP3208. ADC1 in VCF schematic. Used for SHDN senses, load cells, suspension potentiometers, and brake pressure sensors. - MCP_ADC _adc1; +public: + ADCInterface(ADCPinout_s pinouts, + ADCChannels_s channels, + ADCScales_s scales, + ADCOffsets_s offsets + ) : _adc_parameters { + .pinouts = pinouts, + .channels = channels, + .scales = scales, + .offsets = offsets + }, + _adc0 ( + _adc_parameters.pinouts.adc0_spi_cs_pin, + MCP_ADC_DEFAULT_SPI_SDI, + MCP_ADC_DEFAULT_SPI_SDO, + MCP_ADC_DEFAULT_SPI_CLK, + MCP_ADC_DEFAULT_SPI_SPEED, + adc0_scales().data(), + adc0_offsets().data() + ), + _adc1 ( + _adc_parameters.pinouts.adc1_spi_cs_pin, + MCP_ADC_DEFAULT_SPI_SDI, + MCP_ADC_DEFAULT_SPI_SDO, + MCP_ADC_DEFAULT_SPI_CLK, + MCP_ADC_DEFAULT_SPI_SPEED, + adc1_scales().data(), + adc1_offsets().data() + ) + {}; + + /** + * Samples from ADC0 + */ + void tick_adc0(); + + /** + * Samples from ADC1 + */ + void tick_adc1(); + + + /* -------------------- ADC0 -------------------- */ + + /** + * @return Pedal Reference Reading + */ + AnalogConversion_s pedal_reference(); + + /** + * @return Analog Steering Degrees [Steering 1] + */ + AnalogConversion_s get_steering_degrees_cw(); + + /** + * @return Analog Steering Degrees [Steering 2] + */ + AnalogConversion_s get_steering_degrees_ccw(); + + /** + * @return Acceleration Pedal 1 + */ + AnalogConversion_s get_acceleration_1(); + + /** + * @return Acceleration Pedal 2 + */ + AnalogConversion_s get_acceleration_2(); + + /** + * @return Brake Pedal 1 + */ + AnalogConversion_s get_brake_1(); + + /** + * @return Brake Pedal 2 + */ + AnalogConversion_s get_brake_2(); + + /* -------------------- ADC1 -------------------- */ + + /** + * @return SHDN H Voltage Sense + */ + AnalogConversion_s shdn_h(); + + /** + * @return SHDN D Voltage Sense + */ + AnalogConversion_s shdn_d(); + + /** + * @return Front Left Load Cell + */ + AnalogConversion_s get_FL_load_cell(); + + /** + * @return Front Right Load Cell + */ + AnalogConversion_s get_FR_load_cell(); + + /** + * @return Front Left Suspension Potentiometer Reading + */ + AnalogConversion_s get_FL_sus_pot(); + + /** + * @return Front Right Suspension Potentiometer Reading + */ + AnalogConversion_s get_FR_sus_pot(); + + /** + * @return Front Brake Pressure + */ + AnalogConversion_s get_brake_pressure_front(); + + /** + * @return Rear Brake Pressure + */ + AnalogConversion_s get_brake_pressure_rear(); + + /** + * Update the filtered values for the load cells and sus pots. + * Uses the iir_filter method to do so. + */ + void update_filtered_values(float alpha); + + /** + * @return Filtered Front Left Load Cell + */ + float get_filtered_FL_load_cell(); + + /** + * @return Filtered Front Right Load Cell + */ + float get_filtered_FR_load_cell(); + + /** + * @return Filtered Front Left Sus Pot + */ + float get_filtered_FL_sus_pot(); + + /** + * @return Filtered Front Right Sus Pot + */ + float get_filtered_FR_sus_pot(); + +private: + + ADCInterfaceParams_s _adc_parameters = {}; + + // MCP3208. ADC0 in VCF schematic. Used for steering, pedal reference, and pedal position sensors. + MCP_ADC _adc0; + // MCP3208. ADC1 in VCF schematic. Used for SHDN senses, load cells, suspension potentiometers, and brake pressure sensors. + MCP_ADC _adc1; + + float _FL_load_cell_filtered; + float _FR_load_cell_filtered; + float _FL_sus_pot_filtered; + float _FR_sus_pot_filtered; + + std::array adc0_scales(); + std::array adc0_offsets(); + std::array adc1_scales(); + std::array adc1_offsets(); + + /** + * @return updated filtered value based on given alpha, previous filtered value, and new measured value + */ + static float _apply_iir_filter(float alpha, float prev_value, float new_value); }; diff --git a/lib/interfaces/include/BrakeRotorTempInterface.h b/lib/interfaces/include/BrakeRotorTempInterface.h index 21ec360..d0f42a9 100644 --- a/lib/interfaces/include/BrakeRotorTempInterface.h +++ b/lib/interfaces/include/BrakeRotorTempInterface.h @@ -1,11 +1,11 @@ #ifndef BRAKEROTORTEMPINTERFACE_H #define BRAKEROTORTEMPINTERFACE_H -/* ETL Library */ -#include "etl/singleton.h" +/* ETL Library Includes */ +#include /* External Includes */ -#include "FlexCAN_T4.h" +#include namespace brake_rotor_temp_default_params @@ -31,27 +31,29 @@ struct BrakeTempData_s */ class BrakeRotorTempInterface { - public: - // default empty constructor will init state to zeros - BrakeRotorTempInterface() {} - - /** - * Retrieves the latest data that has been sent from the sensors - * @return the latest temp data - */ - BrakeTempData_s getBrakeRotorTempData() const; - - /** - * CAN receive function to parse the new CAN msg and update internal state - * Called by VCF's recv switch - * @param msg the CAN msg to parse - */ - void receiveBrakeRotorTempData(const CAN_message_t &msg); - - private: - BrakeTempData_s _temp_data; - - void _updateCalculatedValues(bool FR); +public: + +// default empty constructor will init state to zeros + BrakeRotorTempInterface() {} + + /** + * Retrieves the latest data that has been sent from the sensors + * @return the latest temp data + */ + BrakeTempData_s getBrakeRotorTempData() const; + + /** + * CAN receive function to parse the new CAN msg and update internal state + * Called by VCF's recv switch + * @param msg the CAN msg to parse + */ + void receiveBrakeRotorTempData(const CAN_message_t &msg); + +private: + + BrakeTempData_s _temp_data; + + void _updateCalculatedValues(bool FR); }; using BrakeRotorTempInterfaceInstance = etl::singleton; diff --git a/lib/interfaces/include/DashboardInterface.h b/lib/interfaces/include/DashboardInterface.h index 8c556ac..3d1af8a 100644 --- a/lib/interfaces/include/DashboardInterface.h +++ b/lib/interfaces/include/DashboardInterface.h @@ -1,19 +1,21 @@ #ifndef DASHBOARD_INTERFACE_H #define DASHBOARD_INTERFACE_H -/* ETL Library */ -#include "etl/singleton.h" +/* ETL Library Includes */ +#include /* External Includes */ -#include "MCP23017.h" +#include #include -#include "FlexCAN_T4.h" -#include "hytech.h" #include "SharedFirmwareTypes.h" +#include "hytech.h" +#include "FlexCAN_T4.h" -/* Local Includes */ +/* Local Interface Includes */ #include "SystemTimeInterface.h" -#include "IOExpanderUtils.h" + +/* Local System Includes */ +#include "IOExpanderUtilities.h" // Struct representing dashboard gpios @@ -30,49 +32,50 @@ struct DashboardGPIOs_s class DashboardInterface { - public: - DashboardInterface( - DashboardGPIOs_s gpios, - uint8_t io_expander_addr, - TwoWire &i2c_bus - ) : - _dashboard_gpios(gpios), - _io_expander(MCP23017(io_expander_addr, i2c_bus)), - _i2c_bus(i2c_bus) - {} - - /** - * @brief Initializes GPIO pins and IO expander. - */ - void init(); - - /** - * @brief Syncs stored outputs with last read outputs. - */ - void sync_dashboard_stored_state(); - - bool bms_ok = true; - bool imd_ok = true; - void receive_ACU_OK(const CAN_message_t &can_msg); - - void set_dial_state(ControllerMode_e mode); - - void read_ioexpander(); - - DashInputState_s get_dashboard_outputs(); - DashInputState_s get_dashboard_stored_state(); - - private: - - DashboardGPIOs_s _dashboard_gpios; - DashInputState_s _dashboard_outputs; // curr state, what the buttons are doing right now - DashInputState_s _dashboard_stored_state; // previous state, what the buttons were doing last tick - MCP23017 _io_expander; - TwoWire &_i2c_bus; - unsigned long _dash_created_millis; - - void _init_ioexpander(); +public: + DashboardInterface(DashboardGPIOs_s gpios, + uint8_t io_expander_addr, + TwoWire &i2c_bus + ) : _dashboard_gpios(gpios), + _io_expander(MCP23017(io_expander_addr, i2c_bus)), + _i2c_bus(i2c_bus) + {}; + + /** + * @brief Initializes GPIO pins and IO expander. + */ + void init(); + + /** + * @brief Syncs stored outputs with last read outputs. + */ + void sync_dashboard_stored_state(); + + bool bms_ok = true; + bool imd_ok = true; + void receive_ACU_OK(const CAN_message_t &can_msg); + + void set_dial_state(ControllerMode_e mode); + + void read_ioexpander(); + + DashInputState_s get_dashboard_outputs(); + + DashInputState_s get_dashboard_stored_state(); + +private: + + DashboardGPIOs_s _dashboard_gpios; + DashInputState_s _dashboard_outputs; // curr state, what the buttons are doing right now + DashInputState_s _dashboard_stored_state; // previous state, what the buttons were doing last tick + MCP23017 _io_expander; + TwoWire &_i2c_bus; + unsigned long _dash_created_millis; + + void _init_ioexpander(); + }; + using DashboardInterfaceInstance = etl::singleton; #endif /* DASHBOARD_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/include/OrbisInterface.h b/lib/interfaces/include/OrbisInterface.h index 29140ec..4f24a37 100644 --- a/lib/interfaces/include/OrbisInterface.h +++ b/lib/interfaces/include/OrbisInterface.h @@ -1,66 +1,71 @@ -#ifndef ORBIS_BR_H -#define ORBIS_BR_H +#ifndef ORBIS_INTERFACE_H +#define ORBIS_INTERFACE_H -/* Library Includes */ -#include +/* ETL Library */ #include -/* --- Constants --- */ -namespace OrbisConstants { - const uint8_t TIMEOUT = 10; // ms - - const uint32_t ORBIS_BR_DEFAULT_BAUD_RATE = 115200; - const uint8_t FACTORY_RESET_DELAY_MS = 200; - const uint8_t SAVE_CONFIG_DELAY_MS = 200; - - const uint8_t SELF_CALIB_STATUS_MASK = 0b00000011; - const uint16_t SELF_CALIB_MAX_TIME_MS = 10000; - const uint8_t SELF_CALIB_NEW_COUNTER_MASK = 0b00000011; - const uint8_t SELF_CALIB_TIMEOUT_ERROR_MASK = 0b00000100; - const uint8_t SELF_CALIB_PARAMETER_ERROR_MASK = 0b00001000; +/* Library Includes */ +#include +#include "SharedFirmwareTypes.h" - const uint8_t OFFSET_HIGH_BYTE_SHIFT = 8; - const uint8_t OFFSET_RECOMBINING_MASK = 0xFF; +using degree = float; - const uint8_t POSITION_DATA_HIGH_BYTE_SHIFT = 8; - const uint8_t POSITION_DATA_RIGHT_SHIFT = 2; - const float ANGLE_WRAPAROUND_THRESHOLD = 180.0f; - const float FULL_ROTATION_DEGREES = 360.0f; - const float ENCODER_RESOLUTION = 16384.0f; // 14-bit resolution = 2^14 counts per revolution - const float DEGREES_PER_REVOLUTION = 360.0f; +namespace orbis_constants +{ + constexpr uint32_t DEFAULT_BAUD_RATE = 115200; + constexpr uint16_t SELF_CALIB_MAX_TIME_MS = 10000; + constexpr uint8_t TIMEOUT_MS = 10; + constexpr uint8_t FACTORY_RESET_DELAY_MS = 200; + constexpr uint8_t SAVE_CONFIG_DELAY_MS = 200; + + constexpr uint8_t OFFSET_HIGH_BYTE_SHIFT = 8; + constexpr uint8_t POSITION_DATA_HIGH_BYTE_SHIFT = 8; + constexpr uint8_t POSITION_DATA_RIGHT_SHIFT = 2; + + constexpr degree ANGLE_WRAPAROUND_THRESHOLD = 180.0f; + constexpr degree FULL_ROTATION_DEGREES = 360.0f; + constexpr degree DEGREES_PER_REVOLUTION = 360.0f; + constexpr float ENCODER_RESOLUTION = 16384.0f; // 14-bit resolution = 2^14 counts per revolution } +/** + * @brief General errors are included in the first byte of the detailed position request response. Detailed errors are from the fourth byte. + */ +namespace orbis_bitmasks +{ + const uint8_t GENERAL_WARNING_BITMASK = 0b00000001; // Error if low, position data is valid, but some operating conditions are close to limits + const uint8_t GENERAL_ERROR_BITMASK = 0b00000010; // Error if low, position data is not valid + const uint8_t OFFSET_RECOMBINING_MASK = 0xFF; -/* --- Error Definitions --- */ -// General errors are included in the first byte of the detailed position request response. Detailed errors are from the fourth byte. -namespace OrbisErrorMasks { - const uint16_t ORBIS_BR_BITMASK_GENERAL_WARNING = 0b00000001; // Error if low, position data is valid, but some operating conditions are close to limits - const uint16_t ORBIS_BR_BITMASK_GENERAL_ERROR = 0b00000010; // Error if low, position data is not valid + const uint8_t DETAILED_COUNTER_ERROR_BITMASK = 0b00001000; // Errors if high + const uint8_t DETAILED_SPEED_HIGH_BITMASK = 0b00010000; // Errors if high + const uint8_t DETAILED_TEMP_RANGE_BITMASK = 0b00100000; // Errors if high + const uint8_t DETAILED_DIST_FAR_BITMASK = 0b01000000; // Errors if high + const uint8_t DETAILED_DIST_NEAR_BITMASK = 0b10000000; // Errors if high - const uint16_t ORBIS_BR_BITMASK_DETAILED_COUNTER_ERROR = 0b00001000; // Errors if high - const uint16_t ORBIS_BR_BITMASK_DETAILED_SPEED_HIGH = 0b00010000; // Errors if high - const uint16_t ORBIS_BR_BITMASK_DETAILED_TEMP_RANGE = 0b00100000; // Errors if high - const uint16_t ORBIS_BR_BITMASK_DETAILED_DIST_FAR = 0b01000000; // Errors if high - const uint16_t ORBIS_BR_BITMASK_DETAILED_DIST_NEAR = 0b10000000; // Errors if high + const uint8_t SELF_CALIB_STATUS_BITMASK = 0b00000011; + const uint8_t SELF_CALIB_NEW_COUNTER_BITMASK = 0b00000011; + const uint8_t SELF_CALIB_TIMEOUT_ERROR_BITMASK = 0b00000100; + const uint8_t SELF_CALIB_PARAMETER_ERROR_BITMASK = 0b00001000; } -/* --- Commands --- */ -namespace OrbisCommands { - const byte UNLOCK_SEQUENCE[4] = {0xCD, 0xEF, 0x89, 0xAB}; - const byte SELF_CALIB_START = 0x41; // requires unlock sequence - const byte SELF_CALIB_STATUS = 0x69; - const byte POSITION_OFFSET = 0x5A; // 'Z' requires unlock sequence - const byte SAVE_CONFIG = 0x63; // 'c' requires unlock sequence - const byte FACTORY_RESET = 0x72; // 'r' requires unlock sequence - const byte SHORT_POS_REQUEST = 0x33; - const byte DETAILED_POS_REQUEST = 0x64; - const byte MULTITURN_COUNTER_SETTING = 0x4D; // 'M' requires unlock sequence - const byte CONTINUOUS_RESPONSE_SETTING = 0x54; // 'T' requires unlock sequence - const byte CONTINUOUS_RESPONSE_START = 0x53; // 'S' requires unlock sequence - const byte CONTINUOUS_RESPONSE_STOP = 0x50; // 'P' requires unlock sequence - const byte BAUD_RATE_SETTING = 0x42; // 'B' requires unlock sequence +namespace orbis_commands +{ + const byte UNLOCK_SEQUENCE[4] = {0xCD, 0xEF, 0x89, 0xAB}; + const byte SELF_CALIB_START = 0x41; // requires unlock sequence + const byte SELF_CALIB_STATUS = 0x69; + const byte POSITION_OFFSET = 0x5A; // 'Z' requires unlock sequence + const byte SAVE_CONFIG = 0x63; // 'c' requires unlock sequence + const byte FACTORY_RESET = 0x72; // 'r' requires unlock sequence + const byte SHORT_POS_REQUEST = 0x33; + const byte DETAILED_POS_REQUEST = 0x64; + const byte MULTITURN_COUNTER_SETTING = 0x4D; // 'M' requires unlock sequence + const byte CONTINUOUS_RESPONSE_SETTING = 0x54; // 'T' requires unlock sequence + const byte CONTINUOUS_RESPONSE_START = 0x53; // 'S' requires unlock sequence + const byte CONTINUOUS_RESPONSE_STOP = 0x50; // 'P' requires unlock sequence + const byte BAUD_RATE_SETTING = 0x42; // 'B' requires unlock sequence } struct OrbisErrorFlags_s @@ -74,34 +79,38 @@ struct OrbisErrorFlags_s bool dist_near = false; // Dist b/w readhead and ring too close (bit=1 means error) }; -class OrbisBR : public SteeringEncoderInterface +class OrbisInterface { public: -// Constructors - OrbisBR(HardwareSerial* serial); -//Fields + OrbisInterface(HardwareSerial* serial); + OrbisErrorFlags_s getOrbisDetailedErrors() const { return _orbisErrors; } -// Functions bool performSelfCalibration(); + void setEncoderOffset(); + void saveConfiguration(); + void factoryReset(); + void sample(); + SteeringEncoderReading_s getLastReading(); private: -// Fields + HardwareSerial* _serial; SteeringEncoderReading_s _lastReading; // Most recently sampled encoder reading. OrbisErrorFlags_s _orbisErrors; -// Functions + void _decodeErrors(uint8_t general, uint8_t detailed); void _sendUnlockSequence(); void _flushSerialBuffer(); + }; -using OrbisBRInstance = etl::singleton; +using OrbisInterfaceInstance = etl::singleton; #endif /* ORBIS_BR_H */ \ No newline at end of file diff --git a/lib/interfaces/include/SystemTimeInterface.h b/lib/interfaces/include/SystemTimeInterface.h index 1af6d79..f9e30a4 100644 --- a/lib/interfaces/include/SystemTimeInterface.h +++ b/lib/interfaces/include/SystemTimeInterface.h @@ -1,10 +1,14 @@ #ifndef SYSTEMTIMEINTERFACE_H #define SYSTEMTIMEINTERFACE_H +/* External Includes */ +#include + + namespace sys_time { unsigned long hal_millis(); unsigned long hal_micros(); } -#endif // SYSTEMTIMEINTERFACE_H +#endif // __SYSTEMTIMEINTERFACE_H__ \ No newline at end of file diff --git a/lib/interfaces/include/VCFCANInterfaceImpl.h b/lib/interfaces/include/VCFCANInterfaceImpl.h index ed01cfa..34bea45 100644 --- a/lib/interfaces/include/VCFCANInterfaceImpl.h +++ b/lib/interfaces/include/VCFCANInterfaceImpl.h @@ -2,14 +2,13 @@ #define VCFCANINTERFACEIMPL_H /* ETL Library */ -#include "etl/delegate.h" -#include "etl/singleton.h" +#include +#include /* External Includes */ -#include "FlexCAN_T4.h" -#include "CANInterface.h" #include "SharedFirmwareTypes.h" -#include "hytech.h" +#include "CANInterface.h" +#include /* Local Interface Includes */ #include "ACUInterface.h" @@ -31,17 +30,15 @@ using FlexCAN_t = FlexCAN_T4; */ struct CANInterfaces_s { - explicit CANInterfaces_s( - ACUInterface &acu_int, - BrakeRotorTempInterface &brake_rotor_temp_int, - DashboardInterface &dash_int, - VCRInterface &vcr_int - ) : - acu_interface(acu_int), + explicit CANInterfaces_s(ACUInterface &acu_int, + BrakeRotorTempInterface &brake_rotor_temp_int, + DashboardInterface &dash_int, + VCRInterface &vcr_int + ) : acu_interface(acu_int), brake_rotor_temp_interface(brake_rotor_temp_int), dash_interface(dash_int), vcr_interface(vcr_int) - {} + {}; ACUInterface &acu_interface; BrakeRotorTempInterface &brake_rotor_temp_interface; diff --git a/lib/interfaces/include/VCFEthernetInterface.h b/lib/interfaces/include/VCFEthernetInterface.h index c3ee136..62e16cd 100644 --- a/lib/interfaces/include/VCFEthernetInterface.h +++ b/lib/interfaces/include/VCFEthernetInterface.h @@ -2,13 +2,12 @@ #define VCF_ETHERNET_INTERFACE_H /* External Includes */ +#include "SharedFirmwareTypes.h" #include "hytech_msgs.pb.h" -#include "hytech_msgs_version.h" -#include "ht_can_version.h" -#include "QNEthernet.h" -#include "EthernetAddressDefs.h" #include "ProtobufMsgInterface.h" -#include "SharedFirmwareTypes.h" +#include "EthernetAddressDefs.h" +#include +#include "ht_can_version.h" #include "device_fw_version.h" /* Local Interface Includes */ @@ -20,9 +19,11 @@ using namespace qindesign::network; + class VCFEthernetInterface { public: + VCFEthernetInterface() = default; void init_ethernet_device(); @@ -33,12 +34,11 @@ class VCFEthernetInterface * @param shared_state The current VCF state, which includes both interface and system data. * @return A populated instance of the outgoing protoc struct. */ - hytech_msgs_VCFData_s make_vcf_data_msg( - ADCInterface &adc_int, - DashboardInterface &dash_int, - PedalsSystem &pedals_sys, - SteeringSystem &steering_sys, - BrakeRotorTempInterface &brake_rotor_temp_int + hytech_msgs_VCFData_s make_vcf_data_msg(ADCInterface &adc_int, + DashboardInterface &dash_int, + PedalsSystem &pedals_sys, + SteeringSystem &steering_sys, + BrakeRotorTempInterface &brake_rotor_temp_int ); /** @@ -55,6 +55,7 @@ class VCFEthernetInterface void handle_send_ethernet_vcf_data(const hytech_msgs_VCFData_s &data); private: + static constexpr size_t VER_HASH_LEN = 9; static constexpr float SHDN_HIGH_THRESHOLD = 12.0f; // threshold for shutdown being considered high @@ -63,4 +64,6 @@ class VCFEthernetInterface EthernetUDP _vcr_recv_socket; }; +using VCFEthernetInterfaceInstance = etl::singleton; + #endif /* VCF_ETHERNET_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/include/VCRInterface.h b/lib/interfaces/include/VCRInterface.h index b9a9d9b..d7fc24f 100644 --- a/lib/interfaces/include/VCRInterface.h +++ b/lib/interfaces/include/VCRInterface.h @@ -2,13 +2,13 @@ #define VCR_INTERFACE_H /* ETL Library */ -#include "etl/singleton.h" +#include /* External Includes */ -#include "Arduino.h" +#include #include "SharedFirmwareTypes.h" #include "hytech.h" -#include "FlexCAN_T4.h" +#include /* Local System Includes */ #include "BuzzerController.h" @@ -76,6 +76,7 @@ class VCRInterface InverterErrorFlags_s _inv_error_status; }; + using VCRInterfaceInstance = etl::singleton; #endif /* VCR_INTERFACE_H */ \ No newline at end of file diff --git a/lib/interfaces/include/WatchdogInterface.h b/lib/interfaces/include/WatchdogInterface.h new file mode 100644 index 0000000..6104108 --- /dev/null +++ b/lib/interfaces/include/WatchdogInterface.h @@ -0,0 +1,78 @@ +#ifndef WATCHDOG_INTERFACE_H +#define WATCHDOG_INTERFACE_H + +/* ETL Library */ +#include + +/* External Includes */ +#include + +/* Local Interface Includes */ +#include "SystemTimeInterface.h" + +using pin = uint8_t; + +namespace watchdog_default_parameters +{ + constexpr unsigned long WATCHDOG_KICK_INTERVAL_MS = 10UL; // 10 ms = 100 Hz +} + +struct WatchdogPinout_s +{ + pin teensy_watchdog_pin; + pin teensy_software_ok_pin; +}; + +struct WatchdogInterfaceParams_s +{ + WatchdogPinout_s pinout; + unsigned long watchdog_kick_interval_ms; +}; + +/** + * This class controls the boolean _watchdog_state, but does not directly control the watchdog. + * WatchdogSystem provides functionality to initialize, monitor, and "kick" the watchdog to prevent system resets. + * + * NOTE: To ensure system responsiveness, WatchdogSystem requires periodic updates by calling the `get_watchdog_state()` method. + * This toggles the _watchdog_state (if the interval has passed) and returns the new state, which must then be sent to the watchdog. + */ +class WatchdogInterface +{ +public: + + WatchdogInterface(WatchdogPinout_s pinout, + uint32_t watchdog_kick_interval_ms = watchdog_default_parameters::WATCHDOG_KICK_INTERVAL_MS + ): _watchdog_parameters { + pinout, + watchdog_kick_interval_ms + } + {}; + + void init(); + + /** + * Get/update watchdog state + * @param curr_millis time of VCF time + * @post IF reach interval, _watchdog_time updated and state switched + */ + bool update_watchdog_state(unsigned long curr_millis); + +private: + + const WatchdogInterfaceParams_s _watchdog_parameters = {}; + + /** + * @brief timestamp of the last watchdog kick + */ + uint32_t _watchdog_time = 0; + + /** + * @brief current output level driven on the watchdog kick pin, true = HIGH + */ + bool _watchdog_state = false; + +}; + +using WatchdogInterfaceInstance = etl::singleton; + +#endif /* WATCHDOG_SYSTEM_H */ diff --git a/lib/interfaces/src/ACUInterface.cpp b/lib/interfaces/src/ACUInterface.cpp index 2f29225..786d63c 100644 --- a/lib/interfaces/src/ACUInterface.cpp +++ b/lib/interfaces/src/ACUInterface.cpp @@ -1,4 +1,5 @@ #include "ACUInterface.h" +#include "VCFCANInterfaceImpl.h" void ACUInterface::receive_ACU_voltages(const CAN_message_t &can_msg) { diff --git a/lib/interfaces/src/ADCInterface.cpp b/lib/interfaces/src/ADCInterface.cpp index 51cb744..9d012ea 100644 --- a/lib/interfaces/src/ADCInterface.cpp +++ b/lib/interfaces/src/ADCInterface.cpp @@ -1,14 +1,23 @@ #include "ADCInterface.h" +void ADCInterface::tick_adc0() +{ + _adc0.tick(); +} +void ADCInterface::tick_adc1() +{ + _adc1.tick(); +} -std::array ADCInterface::adc0_scales() { +std::array ADCInterface::adc0_scales() +{ std::array scales = {}; scales[_adc_parameters.channels.pedal_ref_channel] = _adc_parameters.scales.pedal_ref_scale; - scales[_adc_parameters.channels.steering_cw_channel] = _adc_parameters.scales.steering_cw_scale; + scales[_adc_parameters.channels.steering_cw_channel] = _adc_parameters.scales.steering_cw_scale; scales[_adc_parameters.channels.steering_ccw_channel] = _adc_parameters.scales.steering_ccw_scale; - scales[_adc_parameters.channels.accel_1_channel] = _adc_parameters.scales.accel_1_scale; + scales[_adc_parameters.channels.accel_1_channel] = _adc_parameters.scales.accel_1_scale; scales[_adc_parameters.channels.accel_2_channel] = _adc_parameters.scales.accel_2_scale; scales[_adc_parameters.channels.brake_1_channel] = _adc_parameters.scales.brake_1_scale; scales[_adc_parameters.channels.brake_2_channel] = _adc_parameters.scales.brake_2_scale; @@ -16,160 +25,174 @@ std::array ADCInterface: return scales; } -std::array ADCInterface::adc0_offsets() { +std::array ADCInterface::adc0_offsets() +{ std::array offsets = {}; - offsets[_adc_parameters.channels.pedal_ref_channel] = _adc_parameters.offsets.pedal_ref_offset; - offsets[_adc_parameters.channels.steering_cw_channel] = _adc_parameters.offsets.steering_cw_offset; - offsets[_adc_parameters.channels.steering_ccw_channel] = _adc_parameters.offsets.steering_ccw_offset; - offsets[_adc_parameters.channels.accel_1_channel] = _adc_parameters.offsets.accel_1_offset; - offsets[_adc_parameters.channels.accel_2_channel] = _adc_parameters.offsets.accel_2_offset; - offsets[_adc_parameters.channels.brake_1_channel] = _adc_parameters.offsets.brake_1_offset; - offsets[_adc_parameters.channels.brake_2_channel] = _adc_parameters.offsets.brake_2_offset; - + offsets[_adc_parameters.channels.pedal_ref_channel] = _adc_parameters.offsets.pedal_ref_offset; + offsets[_adc_parameters.channels.steering_cw_channel] = _adc_parameters.offsets.steering_cw_offset; + offsets[_adc_parameters.channels.steering_ccw_channel] = _adc_parameters.offsets.steering_ccw_offset; + offsets[_adc_parameters.channels.accel_1_channel] = _adc_parameters.offsets.accel_1_offset; + offsets[_adc_parameters.channels.accel_2_channel] = _adc_parameters.offsets.accel_2_offset; + offsets[_adc_parameters.channels.brake_1_channel] = _adc_parameters.offsets.brake_1_offset; + offsets[_adc_parameters.channels.brake_2_channel] = _adc_parameters.offsets.brake_2_offset; + return offsets; } -std::array ADCInterface::adc1_scales() { +std::array ADCInterface::adc1_scales() +{ std::array scales = {}; - + scales[_adc_parameters.channels.shdn_h_channel] = _adc_parameters.scales.shdn_h_scale; scales[_adc_parameters.channels.shdn_d_channel] = _adc_parameters.scales.shdn_d_scale; scales[_adc_parameters.channels.fl_loadcell_channel] = _adc_parameters.scales.fl_loadcell_scale; scales[_adc_parameters.channels.fr_loadcell_channel] = _adc_parameters.scales.fr_loadcell_scale; - scales[_adc_parameters.channels.fr_suspot_channel] = _adc_parameters.scales.fr_suspot_scale; scales[_adc_parameters.channels.fl_suspot_channel] = _adc_parameters.scales.fl_suspot_scale; + scales[_adc_parameters.channels.fr_suspot_channel] = _adc_parameters.scales.fr_suspot_scale; scales[_adc_parameters.channels.brake_pressure_front_channel] = _adc_parameters.scales.brake_pressure_front_scale; scales[_adc_parameters.channels.brake_pressure_rear_channel] = _adc_parameters.scales.brake_pressure_rear_scale; - + return scales; } -std::array ADCInterface::adc1_offsets() { +std::array ADCInterface::adc1_offsets() +{ std::array offsets = {}; - offsets[_adc_parameters.channels.shdn_h_channel] = _adc_parameters.offsets.shdn_h_offset; - offsets[_adc_parameters.channels.shdn_d_channel] = _adc_parameters.offsets.shdn_d_offset; - offsets[_adc_parameters.channels.fl_loadcell_channel] = _adc_parameters.offsets.fl_loadcell_offset; - offsets[_adc_parameters.channels.fr_loadcell_channel] = _adc_parameters.offsets.fr_loadcell_offset; - offsets[_adc_parameters.channels.fr_suspot_channel] = _adc_parameters.offsets.fr_suspot_offset; - offsets[_adc_parameters.channels.fl_suspot_channel] = _adc_parameters.offsets.fl_suspot_offset; - offsets[_adc_parameters.channels.brake_pressure_front_channel] = _adc_parameters.offsets.brake_pressure_front_offset; - offsets[_adc_parameters.channels.brake_pressure_rear_channel] = _adc_parameters.offsets.brake_pressure_rear_offset; - - return offsets; -} - -float ADCInterface::iir_filter(float alpha, float prev_value, float new_value) -{ - return (alpha * new_value) + (1 - alpha) * (prev_value); -} + offsets[_adc_parameters.channels.shdn_h_channel] = _adc_parameters.offsets.shdn_h_offset; + offsets[_adc_parameters.channels.shdn_d_channel] = _adc_parameters.offsets.shdn_d_offset; + offsets[_adc_parameters.channels.fl_loadcell_channel] = _adc_parameters.offsets.fl_loadcell_offset; + offsets[_adc_parameters.channels.fr_loadcell_channel] = _adc_parameters.offsets.fr_loadcell_offset; + offsets[_adc_parameters.channels.fl_suspot_channel] = _adc_parameters.offsets.fl_suspot_offset; + offsets[_adc_parameters.channels.fr_suspot_channel] = _adc_parameters.offsets.fr_suspot_offset; + offsets[_adc_parameters.channels.brake_pressure_front_channel] = _adc_parameters.offsets.brake_pressure_front_offset; + offsets[_adc_parameters.channels.brake_pressure_rear_channel] = _adc_parameters.offsets.brake_pressure_rear_offset; -void ADCInterface::update_filtered_values(float alpha) { - _FL_load_cell_filtered = iir_filter( - alpha, - _FL_load_cell_filtered, - FL_load_cell().conversion - ); - _FR_load_cell_filtered = iir_filter( - alpha, - _FR_load_cell_filtered, - FR_load_cell().conversion - ); - _FL_sus_pot_filtered = iir_filter( - alpha, - _FL_sus_pot_filtered, - FL_sus_pot().conversion - ); - _FR_sus_pot_filtered = iir_filter( - alpha, - _FR_sus_pot_filtered, - FR_sus_pot().conversion - ); + return offsets; } /* -------------------- ADC 0 Functions -------------------- */ -void ADCInterface::adc0_tick() { - _adc0.tick(); -} AnalogConversion_s ADCInterface::pedal_reference() { return _adc0.data.conversions[_adc_parameters.channels.pedal_ref_channel]; } -AnalogConversion_s ADCInterface::get_steering_degrees_cw() { +AnalogConversion_s ADCInterface::get_steering_degrees_cw() +{ return _adc0.data.conversions[_adc_parameters.channels.steering_cw_channel]; } -AnalogConversion_s ADCInterface::get_steering_degrees_ccw() { +AnalogConversion_s ADCInterface::get_steering_degrees_ccw() +{ return _adc0.data.conversions[_adc_parameters.channels.steering_ccw_channel]; } -AnalogConversion_s ADCInterface::acceleration_1() { +AnalogConversion_s ADCInterface::get_acceleration_1() +{ return _adc0.data.conversions[_adc_parameters.channels.accel_1_channel]; } -AnalogConversion_s ADCInterface::acceleration_2() { +AnalogConversion_s ADCInterface::get_acceleration_2() +{ return _adc0.data.conversions[_adc_parameters.channels.accel_2_channel]; } -AnalogConversion_s ADCInterface::brake_1() { +AnalogConversion_s ADCInterface::get_brake_1() +{ return _adc0.data.conversions[_adc_parameters.channels.brake_1_channel]; } -AnalogConversion_s ADCInterface::brake_2() { +AnalogConversion_s ADCInterface::get_brake_2() +{ return _adc0.data.conversions[_adc_parameters.channels.brake_2_channel]; } /* -------------------- ADC 1 Functions -------------------- */ -void ADCInterface::adc1_tick() { - _adc1.tick(); -} -AnalogConversion_s ADCInterface::shdn_h() { +AnalogConversion_s ADCInterface::shdn_h() +{ return _adc1.data.conversions[_adc_parameters.channels.shdn_h_channel]; } -AnalogConversion_s ADCInterface::shdn_d() { +AnalogConversion_s ADCInterface::shdn_d() +{ return _adc1.data.conversions[_adc_parameters.channels.shdn_d_channel]; } -AnalogConversion_s ADCInterface::FL_load_cell() { +AnalogConversion_s ADCInterface::get_FL_load_cell() +{ return _adc1.data.conversions[_adc_parameters.channels.fl_loadcell_channel]; } -float ADCInterface::get_filtered_FL_load_cell() { - return _FL_load_cell_filtered; -} - -AnalogConversion_s ADCInterface::FR_load_cell() { +AnalogConversion_s ADCInterface::get_FR_load_cell() +{ return _adc1.data.conversions[_adc_parameters.channels.fr_loadcell_channel]; } -float ADCInterface::get_filtered_FR_load_cell() { - return _FR_load_cell_filtered; +AnalogConversion_s ADCInterface::get_FL_sus_pot() +{ + return _adc1.data.conversions[_adc_parameters.channels.fl_suspot_channel]; } -AnalogConversion_s ADCInterface::FR_sus_pot() { +AnalogConversion_s ADCInterface::get_FR_sus_pot() +{ return _adc1.data.conversions[_adc_parameters.channels.fr_suspot_channel]; } -float ADCInterface::get_filtered_FR_sus_pot() { - return _FR_sus_pot_filtered; +AnalogConversion_s ADCInterface::get_brake_pressure_front() { + return _adc1.data.conversions[_adc_parameters.channels.brake_pressure_front_channel]; } -AnalogConversion_s ADCInterface::FL_sus_pot() { - return _adc1.data.conversions[_adc_parameters.channels.fl_suspot_channel]; +AnalogConversion_s ADCInterface::get_brake_pressure_rear() { + return _adc1.data.conversions[_adc_parameters.channels.brake_pressure_rear_channel]; } -float ADCInterface::get_filtered_FL_sus_pot() { - return _FL_sus_pot_filtered; +void ADCInterface::update_filtered_values(float alpha) +{ + _FL_load_cell_filtered = _apply_iir_filter( + alpha, + _FL_load_cell_filtered, + get_FL_load_cell().conversion + ); + _FR_load_cell_filtered = _apply_iir_filter( + alpha, + _FR_load_cell_filtered, + get_FR_load_cell().conversion + ); + _FL_sus_pot_filtered = _apply_iir_filter( + alpha, + _FL_sus_pot_filtered, + get_FL_sus_pot().conversion + ); + _FR_sus_pot_filtered = _apply_iir_filter( + alpha, + _FR_sus_pot_filtered, + get_FR_sus_pot().conversion + ); } -AnalogConversion_s ADCInterface::get_brake_pressure_front() { - return _adc1.data.conversions[_adc_parameters.channels.brake_pressure_front_channel]; +float ADCInterface::get_filtered_FL_load_cell() +{ + return _FL_load_cell_filtered; } -AnalogConversion_s ADCInterface::get_brake_pressure_rear() { - return _adc1.data.conversions[_adc_parameters.channels.brake_pressure_rear_channel]; +float ADCInterface::get_filtered_FR_load_cell() +{ + return _FR_load_cell_filtered; } + +float ADCInterface::get_filtered_FL_sus_pot() +{ + return _FL_sus_pot_filtered; +} + +float ADCInterface::get_filtered_FR_sus_pot() +{ + return _FR_sus_pot_filtered; +} + +float ADCInterface::_apply_iir_filter(float alpha, float prev_value, float new_value) +{ + return (alpha * new_value) + (1 - alpha) * (prev_value); +} \ No newline at end of file diff --git a/lib/interfaces/src/DashboardInterface.cpp b/lib/interfaces/src/DashboardInterface.cpp index 64e6e71..7f24a11 100644 --- a/lib/interfaces/src/DashboardInterface.cpp +++ b/lib/interfaces/src/DashboardInterface.cpp @@ -45,27 +45,27 @@ void DashboardInterface::read_ioexpander() ControllerMode_e new_mode = ControllerMode_e::MODE_0; // default to mode 0 // check for value of dial - if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 0)) // NOLINT 0 is pos of bit + if (IOExpanderUtilities::getBit(data, (bool) MCP23017Port::B, 0)) // NOLINT 0 is pos of bit { new_mode = ControllerMode_e::MODE_0; } - else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 1)) // NOLINT 1 is pos of bit + else if (IOExpanderUtilities::getBit(data, (bool) MCP23017Port::B, 1)) // NOLINT 1 is pos of bit { new_mode = ControllerMode_e::MODE_1; } - else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 2)) // NOLINT 2 is pos of bit + else if (IOExpanderUtilities::getBit(data, (bool) MCP23017Port::B, 2)) // NOLINT 2 is pos of bit { new_mode = ControllerMode_e::MODE_2; } - else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 3)) // NOLINT 3 is pos of bit + else if (IOExpanderUtilities::getBit(data, (bool) MCP23017Port::B, 3)) // NOLINT 3 is pos of bit { new_mode = ControllerMode_e::MODE_3; } - else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 4)) // NOLINT 4 is pos of bit + else if (IOExpanderUtilities::getBit(data, (bool) MCP23017Port::B, 4)) // NOLINT 4 is pos of bit { new_mode = ControllerMode_e::MODE_4; } - else if (IOExpanderUtils::getBit(data, (bool) MCP23017Port::B, 5)) // NOLINT 5 is pos of bit + else if (IOExpanderUtilities::getBit(data, (bool) MCP23017Port::B, 5)) // NOLINT 5 is pos of bit { new_mode = ControllerMode_e::MODE_5; } diff --git a/lib/interfaces/src/OrbisInterface.cpp b/lib/interfaces/src/OrbisInterface.cpp index 0e50cd3..50861c0 100644 --- a/lib/interfaces/src/OrbisInterface.cpp +++ b/lib/interfaces/src/OrbisInterface.cpp @@ -1,55 +1,52 @@ -/* Library Includes */ -#include "Orbis_BR.h" -#include +#include "OrbisInterface.h" -OrbisBR::OrbisBR(HardwareSerial* serial) -: _serial(serial) + +OrbisInterface::OrbisInterface(HardwareSerial* serial) : _serial(serial) { _lastReading.status = SteeringEncoderStatus_e::ERROR; - _serial->begin(OrbisConstants::ORBIS_BR_DEFAULT_BAUD_RATE, SERIAL_8N1); + _serial->begin(orbis_constants::DEFAULT_BAUD_RATE, SERIAL_8N1); } - -/* -------------------- Initialization Methods -------------------- */ - -bool OrbisBR::performSelfCalibration() +bool OrbisInterface::performSelfCalibration() { _orbisErrors.calibration_timeout = false; _orbisErrors.calibration_parameter = false; - /* ----- SELF CALIBRATION STATUS 1 ----- */ + /** + * Datasheet recommends doing status before and after self-calibration command. + * Status command returns 2 bytes: echo byte + status byte + */ - _serial->write(OrbisCommands::SELF_CALIB_STATUS); delay(1); - // Datasheet recommends doing status before and after self-calibration command. - // Status command returns 2 bytes: echo byte + status byte + /* ----- SELF CALIBRATION STATUS 1 ----- */ + _serial->write(orbis_commands::SELF_CALIB_STATUS); delay(1); uint8_t echo1 = _serial->read(); uint8_t status_before_calib = _serial->read(); - uint8_t calibration_counter_before = status_before_calib & OrbisConstants::SELF_CALIB_STATUS_MASK; + uint8_t calibration_counter_before = status_before_calib & orbis_bitmasks::SELF_CALIB_STATUS_BITMASK; /* ----- SELF CALIBRATION START ----- */ - _sendUnlockSequence(); - _serial->write(OrbisCommands::SELF_CALIB_START); delay(1); + _serial->write(orbis_commands::SELF_CALIB_START); delay(1); while (!_serial->available()); // wait until bytes are available uint8_t echo2 = _serial->read(); - Serial.println("ROTATE NOW"); // Debug line + // Serial.println("ROTATE NOW"); // Debug line - delay(OrbisConstants::SELF_CALIB_MAX_TIME_MS); // Max time for a self-calibration is 10 seconds. + delay(orbis_constants::SELF_CALIB_MAX_TIME_MS); // Max time for a self-calibration is 10 seconds. /* ----- SELF CALIBRATION STATUS 2 ----- */ - - _serial->write(OrbisCommands::SELF_CALIB_STATUS); delay(1); + _serial->write(orbis_commands::SELF_CALIB_STATUS); delay(1); unsigned long startTime = millis(); - while (_serial->available() < 2) { - if (millis() - startTime >= OrbisConstants::TIMEOUT) { // NOLINT + while (_serial->available() < 2) + { + if (millis() - startTime >= orbis_constants::TIMEOUT_MS) + { return false; // timeout } } @@ -59,12 +56,12 @@ bool OrbisBR::performSelfCalibration() uint8_t echo = _serial->read(); uint8_t status_after_calib = _serial->read(); - uint8_t calibration_counter_after = status_after_calib & OrbisConstants::SELF_CALIB_NEW_COUNTER_MASK; + uint8_t calibration_counter_after = status_after_calib & orbis_bitmasks::SELF_CALIB_NEW_COUNTER_BITMASK; // Encoder increments a 2-bit counter each successful calibration. // We verify calibration completed by confirming this counter changed. - bool timeout_error = status_after_calib & OrbisConstants::SELF_CALIB_TIMEOUT_ERROR_MASK; // b2 - bool parameter_error = status_after_calib & OrbisConstants::SELF_CALIB_PARAMETER_ERROR_MASK; // b3 + bool timeout_error = status_after_calib & orbis_bitmasks::SELF_CALIB_TIMEOUT_ERROR_BITMASK; // b2 + bool parameter_error = status_after_calib & orbis_bitmasks::SELF_CALIB_PARAMETER_ERROR_BITMASK; // b3 if (calibration_counter_before == calibration_counter_after) { // Serial.println("ERROR: Calibration Did Not Complete"); // Debug Line @@ -81,26 +78,26 @@ bool OrbisBR::performSelfCalibration() return true; } -void OrbisBR::setEncoderOffset() +void OrbisInterface::setEncoderOffset() { factoryReset(); - _serial->write(OrbisCommands::SHORT_POS_REQUEST); delay(1); + _serial->write(orbis_commands::SHORT_POS_REQUEST); delay(1); while (!_serial->available()); // wait until bytes are available uint8_t position_high_byte = _serial->read(); while (!_serial->available()); // wait until bytes are available uint8_t position_low_byte = _serial->read(); - uint16_t current_raw_position = ((((uint16_t) position_high_byte) << OrbisConstants::POSITION_DATA_HIGH_BYTE_SHIFT) | (uint16_t) position_low_byte) >> OrbisConstants::POSITION_DATA_RIGHT_SHIFT; - byte offset_pos_high_byte = (current_raw_position >> OrbisConstants::OFFSET_HIGH_BYTE_SHIFT) & OrbisConstants::OFFSET_RECOMBINING_MASK; // b15 - b8. - byte offset_pos_low_byte = current_raw_position & OrbisConstants::OFFSET_RECOMBINING_MASK; // b7 - b0 + uint16_t current_raw_position = ((((uint16_t) position_high_byte) << orbis_constants::POSITION_DATA_HIGH_BYTE_SHIFT) | (uint16_t) position_low_byte) >> orbis_constants::POSITION_DATA_RIGHT_SHIFT; + byte offset_pos_high_byte = (current_raw_position >> orbis_constants::OFFSET_HIGH_BYTE_SHIFT) & orbis_bitmasks::OFFSET_RECOMBINING_MASK; // b15 - b8. + byte offset_pos_low_byte = current_raw_position & orbis_bitmasks::OFFSET_RECOMBINING_MASK; // b7 - b0 // Current raw position is 14 bit integer, we parse two bytes to remove warning/error bits. // Offset command only takes in position data as individual bytes (8 bit integer). Break 14 bit integer into two bytes. _sendUnlockSequence(); - _serial->write(OrbisCommands::POSITION_OFFSET); delay(1); + _serial->write(orbis_commands::POSITION_OFFSET); delay(1); _serial->write((byte) 0x00); delay(1); _serial->write((byte) 0x00); delay(1); _serial->write(offset_pos_high_byte); delay(1); @@ -112,32 +109,34 @@ void OrbisBR::setEncoderOffset() saveConfiguration(); } -void OrbisBR::saveConfiguration() +void OrbisInterface::saveConfiguration() { _sendUnlockSequence(); - _serial->write(OrbisCommands::SAVE_CONFIG); delay(1); + _serial->write(orbis_commands::SAVE_CONFIG); delay(1); _flushSerialBuffer(); - delay(OrbisConstants::SAVE_CONFIG_DELAY_MS); + delay(orbis_constants::SAVE_CONFIG_DELAY_MS); } /* -------------------- Sample/Data Methods -------------------- */ -void OrbisBR::sample() +void OrbisInterface::sample() { _lastReading.errors = EncoderErrorFlags_s{}; // reset to all false _orbisErrors = OrbisErrorFlags_s{}; // reset to all false - _serial->write(OrbisCommands::DETAILED_POS_REQUEST); delay(1); + _serial->write(orbis_commands::DETAILED_POS_REQUEST); delay(1); // Detailed Position Request: 1 byte echo, 2 byte position, 1 byte detailed status unsigned long startTime = millis(); - while (_serial->available() < 4) { - if (millis() - startTime >= OrbisConstants::TIMEOUT ) { // NOLINT + while (_serial->available() < 4) + { + if (millis() - startTime >= orbis_constants::TIMEOUT_MS) // NOLINT + { _lastReading.errors.noData = true; _lastReading.status = SteeringEncoderStatus_e::ERROR; return; @@ -147,7 +146,7 @@ void OrbisBR::sample() uint8_t echo = _serial->read(); - if (echo != OrbisCommands::DETAILED_POS_REQUEST) + if (echo != orbis_commands::DETAILED_POS_REQUEST) { _lastReading.errors.noData = true; _lastReading.status = SteeringEncoderStatus_e::ERROR; @@ -157,18 +156,18 @@ void OrbisBR::sample() uint8_t general_high_byte = _serial->read(); uint8_t general_low_byte = _serial->read(); uint8_t detailed = _serial->read(); - - uint8_t general_status = general_low_byte & OrbisConstants::SELF_CALIB_STATUS_MASK; // b1:b0 are general status + uint8_t general_status = general_low_byte & orbis_bitmasks::SELF_CALIB_STATUS_BITMASK; // b1:b0 are general status _decodeErrors(general_status, detailed); // Decode errors using the extracted general status bits + detailed errors byte - uint16_t raw_position = ((((uint16_t) general_high_byte) << OrbisConstants::POSITION_DATA_HIGH_BYTE_SHIFT) | (uint16_t) general_low_byte) >> OrbisConstants::POSITION_DATA_RIGHT_SHIFT; + uint16_t raw_position = ((((uint16_t) general_high_byte) << orbis_constants::POSITION_DATA_HIGH_BYTE_SHIFT) | (uint16_t) general_low_byte) >> orbis_constants::POSITION_DATA_RIGHT_SHIFT; _lastReading.rawValue = raw_position; - float angle = ((float)raw_position / OrbisConstants::ENCODER_RESOLUTION ) * OrbisConstants::DEGREES_PER_REVOLUTION; - if (angle > OrbisConstants::ANGLE_WRAPAROUND_THRESHOLD) { - angle -= OrbisConstants::FULL_ROTATION_DEGREES; + float angle = ((float)raw_position / orbis_constants::ENCODER_RESOLUTION ) * orbis_constants::DEGREES_PER_REVOLUTION; + if (angle > orbis_constants::ANGLE_WRAPAROUND_THRESHOLD) + { + angle -= orbis_constants::FULL_ROTATION_DEGREES; } _lastReading.angle = angle; @@ -182,65 +181,59 @@ void OrbisBR::sample() // Serial.println(_lastReading.angle); } -SteeringEncoderReading_s OrbisBR::getLastReading() +SteeringEncoderReading_s OrbisInterface::getLastReading() { return _lastReading; } /* -------------------- Error Flagging -------------------- */ -void OrbisBR::_decodeErrors(uint8_t general, uint8_t detailed) +void OrbisInterface::_decodeErrors(uint8_t general, uint8_t detailed) { // General bits error low (0) - _lastReading.errors.dataInvalid = !(general & OrbisErrorMasks::ORBIS_BR_BITMASK_GENERAL_ERROR); - _lastReading.errors.operatingLimit = !(general & OrbisErrorMasks::ORBIS_BR_BITMASK_GENERAL_WARNING); + _lastReading.errors.dataInvalid = !(general & orbis_bitmasks::GENERAL_ERROR_BITMASK); + _lastReading.errors.operatingLimit = !(general & orbis_bitmasks::GENERAL_WARNING_BITMASK); // Detailed bits are error high (1) - _orbisErrors.counter_error = detailed & OrbisErrorMasks::ORBIS_BR_BITMASK_DETAILED_COUNTER_ERROR; - _orbisErrors.speed_high = detailed & OrbisErrorMasks::ORBIS_BR_BITMASK_DETAILED_SPEED_HIGH; - _orbisErrors.temp_out_of_range = detailed & OrbisErrorMasks::ORBIS_BR_BITMASK_DETAILED_TEMP_RANGE; - _orbisErrors.dist_far = detailed & OrbisErrorMasks::ORBIS_BR_BITMASK_DETAILED_DIST_FAR; - _orbisErrors.dist_near = detailed & OrbisErrorMasks::ORBIS_BR_BITMASK_DETAILED_DIST_NEAR; + _orbisErrors.counter_error = detailed & orbis_bitmasks::DETAILED_COUNTER_ERROR_BITMASK; + _orbisErrors.speed_high = detailed & orbis_bitmasks::DETAILED_SPEED_HIGH_BITMASK; + _orbisErrors.temp_out_of_range = detailed & orbis_bitmasks::DETAILED_TEMP_RANGE_BITMASK; + _orbisErrors.dist_far = detailed & orbis_bitmasks::DETAILED_DIST_FAR_BITMASK; + _orbisErrors.dist_near = detailed & orbis_bitmasks::DETAILED_DIST_NEAR_BITMASK; - // Detect any errors bool anyError = ( - _lastReading.errors.dataInvalid || - _lastReading.errors.noData || - _orbisErrors.counter_error || - _orbisErrors.speed_high || - _orbisErrors.temp_out_of_range || - _orbisErrors.dist_far || + _lastReading.errors.dataInvalid || + _lastReading.errors.noData || + _orbisErrors.counter_error || + _orbisErrors.speed_high || + _orbisErrors.temp_out_of_range || + _orbisErrors.dist_far || _orbisErrors.dist_near ); _lastReading.status = anyError ? SteeringEncoderStatus_e::ERROR : SteeringEncoderStatus_e::NOMINAL; } - - -/* -------------------- Additional Functionalities -------------------- */ -void OrbisBR::factoryReset() +void OrbisInterface::factoryReset() { _sendUnlockSequence(); - - _serial->write(OrbisCommands::FACTORY_RESET); - + _serial->write(orbis_commands::FACTORY_RESET); _flushSerialBuffer(); - - delay(OrbisConstants::FACTORY_RESET_DELAY_MS); - - //Serial.println("Factory Reset Done"); // Debug line + delay(orbis_constants::FACTORY_RESET_DELAY_MS); } -void OrbisBR::_sendUnlockSequence() { - for (byte b : OrbisCommands::UNLOCK_SEQUENCE) { +void OrbisInterface::_sendUnlockSequence() +{ + for (byte b : orbis_commands::UNLOCK_SEQUENCE) { _serial->write(b); delay(1); - _serial->read(); // Discard echo + _serial->read(); } } -void OrbisBR::_flushSerialBuffer() { - while (_serial->available()) { +void OrbisInterface::_flushSerialBuffer() +{ + while (_serial->available()) + { _serial->read(); } } diff --git a/lib/interfaces/src/SystemTimeInterface.cpp b/lib/interfaces/src/SystemTimeInterface.cpp index 5775e59..e45424f 100644 --- a/lib/interfaces/src/SystemTimeInterface.cpp +++ b/lib/interfaces/src/SystemTimeInterface.cpp @@ -1,16 +1,8 @@ #include "SystemTimeInterface.h" -#include namespace sys_time { - unsigned long hal_millis() - { - return millis(); - } - - unsigned long hal_micros() - { - return micros(); - } + unsigned long hal_millis() { return millis(); } + unsigned long hal_micros() { return micros(); } } \ No newline at end of file diff --git a/lib/interfaces/src/VCFEthernetInterface.cpp b/lib/interfaces/src/VCFEthernetInterface.cpp index 81279dc..847a91b 100644 --- a/lib/interfaces/src/VCFEthernetInterface.cpp +++ b/lib/interfaces/src/VCFEthernetInterface.cpp @@ -1,26 +1,28 @@ #include "VCFEthernetInterface.h" +#include "hytech_msgs_version.h" + void VCFEthernetInterface::init_ethernet_device() { EthernetIPDefsInstance::create(); - Ethernet.begin( - EthernetIPDefsInstance::instance().vcf_ip, - EthernetIPDefsInstance::instance().car_subnet, - EthernetIPDefsInstance::instance().default_gateway + Ethernet.begin(EthernetIPDefsInstance::instance().vcf_ip, + EthernetIPDefsInstance::instance().car_subnet, + EthernetIPDefsInstance::instance().default_gateway ); _vcf_send_socket.begin(EthernetIPDefsInstance::instance().VCFData_port); _vcr_recv_socket.begin(EthernetIPDefsInstance::instance().VCRData_port); } -hytech_msgs_VCFData_s VCFEthernetInterface::make_vcf_data_msg( - ADCInterface &adc_int, - DashboardInterface &dash_int, - PedalsSystem &pedals_sys, - SteeringSystem &steering_sys, - BrakeRotorTempInterface &brake_rotor_temp_int + +hytech_msgs_VCFData_s VCFEthernetInterface::make_vcf_data_msg(ADCInterface &adc_int, + DashboardInterface &dash_int, + PedalsSystem &pedals_sys, + SteeringSystem &steering_sys, + BrakeRotorTempInterface &brake_rotor_temp_int ) { - hytech_msgs_VCFData_s out; + auto fw_version_hash = convert_version_to_char_arr(device_status_t::firmware_version); + hytech_msgs_VCFData_s out = {}; // has_value out.has_dash_input_state = true; diff --git a/lib/interfaces/src/WatchdogInterface.cpp b/lib/interfaces/src/WatchdogInterface.cpp new file mode 100644 index 0000000..967af47 --- /dev/null +++ b/lib/interfaces/src/WatchdogInterface.cpp @@ -0,0 +1,25 @@ +#include "WatchdogInterface.h" + +void WatchdogInterface::init() +{ + // Pin Congfiguration + pinMode(_watchdog_parameters.pinout.teensy_watchdog_pin, OUTPUT); + pinMode(_watchdog_parameters.pinout.teensy_software_ok_pin, OUTPUT); + + // Inital Pin States For OUTPUT Pins + digitalWrite(_watchdog_parameters.pinout.teensy_watchdog_pin, LOW); + digitalWrite(_watchdog_parameters.pinout.teensy_software_ok_pin, HIGH); +} + +bool WatchdogInterface::update_watchdog_state(unsigned long curr_millis) +{ + + if ((curr_millis - _watchdog_time) > _watchdog_parameters.watchdog_kick_interval_ms) + { + _watchdog_state = !_watchdog_state; + _watchdog_time = curr_millis; + digitalWrite(_watchdog_parameters.pinout.teensy_watchdog_pin, _watchdog_state); + } + + return _watchdog_state; +} \ No newline at end of file diff --git a/lib/systems/include/BuzzerController.h b/lib/systems/include/BuzzerController.h index 73ee9a8..206630c 100644 --- a/lib/systems/include/BuzzerController.h +++ b/lib/systems/include/BuzzerController.h @@ -3,7 +3,7 @@ /** * This class controls the car's buzzer. It is a singleton class (since we only have one buzzer). - * + * * NOTE: This class does NOT directly control the buzzer. Rather, it does the calculations of whether * or not the buzzer SHOULD be active. The output of this system then goes to the Dashboard, * who will activate the buzzer when this system outputs HIGH. @@ -11,12 +11,13 @@ class BuzzerController { public: + static BuzzerController& getInstance() { static BuzzerController instance; return instance; } - + /** * Calling this command will activate the buzzer for BUZZER_PERIOD_MS milliseconds. */ @@ -38,20 +39,19 @@ class BuzzerController */ bool buzzer_is_active(unsigned long millis) { - return _last_activation_time_ms != 0 && (millis - _last_activation_time_ms) < BUZZER_PERIOD_MS; + return _last_activation_time_ms != 0 && (millis - _last_activation_time_ms) < _BUZZER_PERIOD_MS; } private: + const unsigned long _BUZZER_PERIOD_MS = 2000; // Default buzzer period is 2000ms + unsigned long _last_activation_time_ms; + BuzzerController() { _last_activation_time_ms = 0; } - const unsigned long BUZZER_PERIOD_MS = 2000; // Default buzzer period is 2000ms - - unsigned long _last_activation_time_ms; - }; #endif /* BUZZER */ diff --git a/lib/systems/include/EEPROMUtils.h b/lib/systems/include/EEPROMUtilities.h similarity index 95% rename from lib/systems/include/EEPROMUtils.h rename to lib/systems/include/EEPROMUtilities.h index 806d07f..3b07b84 100644 --- a/lib/systems/include/EEPROMUtils.h +++ b/lib/systems/include/EEPROMUtilities.h @@ -1,12 +1,12 @@ #ifndef EEPROM_UTILITIES_H #define EEPROM_UTILITIES_H -/* Standard Library */ +/* Standard Library Includes */ #include /* External Includes */ #include -#include "Logger.h" +#include namespace EEPROMUtilities @@ -36,7 +36,6 @@ namespace EEPROMUtilities EEPROM.write(address + 2, third_msb); EEPROM.write(address + 3, lsb); } - } #endif /* EEPROM_UTILITIES_H */ \ No newline at end of file diff --git a/lib/systems/include/IOExpanderUtils.h b/lib/systems/include/IOExpanderUtilities.h similarity index 76% rename from lib/systems/include/IOExpanderUtils.h rename to lib/systems/include/IOExpanderUtilities.h index b8e87a2..2851dde 100644 --- a/lib/systems/include/IOExpanderUtils.h +++ b/lib/systems/include/IOExpanderUtilities.h @@ -1,12 +1,12 @@ -#ifndef IO_EXPANDER_UTILS_H -#define IO_EXPANDER_UTILS_H +#ifndef IO_EXPANDER_UTILITIES_H +#define IO_EXPANDER_UTILITIES_H -/* Standard Library */ +/* Standard Library Includes */ #include #include -namespace IOExpanderUtils +namespace IOExpanderUtilities { /** IOExpander's read() only reads. diff --git a/lib/systems/include/NeopixelController.h b/lib/systems/include/NeopixelController.h index 185c338..de12ade 100644 --- a/lib/systems/include/NeopixelController.h +++ b/lib/systems/include/NeopixelController.h @@ -13,11 +13,11 @@ // define a new type of struct, add an arg to the constructor, etc. // - this is how it was implemented on STM32 dash and I want to be fast :) -/* ETL Library */ -#include "etl/singleton.h" +/* ETL Library Includes */ +#include /* External Includes */ -#include "Adafruit_NeoPixel.h" +#include #include "SharedFirmwareTypes.h" /* Local Interface Includes */ @@ -70,16 +70,22 @@ enum class LED_color_e class NeopixelController { public: - NeopixelController(uint32_t neopixel_count, uint32_t neopixel_pin) : - _neopixels(neopixel_count, neopixel_pin, NEO_GRBW + NEO_KHZ800), + + NeopixelController(uint32_t neopixel_count, + uint32_t neopixel_pin + ) : _neopixels(neopixel_count, neopixel_pin, NEO_GRBW + NEO_KHZ800), _current_brightness(64), _neopixel_count(neopixel_count) {}; void init_neopixels(); + void dim_neopixels(); + void set_neopixel(uint16_t id, uint32_t c); + void refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces_s &interfaces); + void set_neopixel_color(LED_ID_e led, LED_color_e color); private: @@ -89,6 +95,7 @@ class NeopixelController uint8_t _neopixel_count; const uint8_t _hv_threshold_voltage = 60; MinCellMonitoringThresholds_s _min_cell_thresholds; + }; using NeopixelControllerInstance = etl::singleton; diff --git a/lib/systems/include/SteeringSystem.h b/lib/systems/include/SteeringSystem.h index c0aff29..31927eb 100644 --- a/lib/systems/include/SteeringSystem.h +++ b/lib/systems/include/SteeringSystem.h @@ -49,10 +49,13 @@ struct SteeringParams_s class SteeringSystem { public: + SteeringSystem(const SteeringParams_s ¶ms) : _params(params) {} void recalibrate_steering_digital(); + void evaluate_steering(const uint32_t analog_raw, const SteeringEncoderReading_s digital_data, const uint32_t current_millis); + void update_observed_steering_limits(const uint32_t analog_raw, const uint32_t digital_raw); /* Getters */ @@ -66,25 +69,6 @@ class SteeringSystem private: - float _convert_digital_sensor(const uint32_t digital_raw); - float _convert_analog_sensor(const uint32_t analog_raw); - float _filter_analog_angle(float x); - - /** - * @brief returns true if steering_analog is outside of the range defined by min and max sensor values - */ - bool _evaluate_steering_oor_analog(const uint32_t steering_analog); - - /** - * @brief returns true if steering_digital is outside the range defined by min and max sensor values - */ - bool _evaluate_steering_oor_digital(const uint32_t steering_digital); - - /** - * @brief returns true if change in angle exceeds maximum change per reading ( max_dtheta_threshold ) - */ - bool _evaluate_steering_dtheta_exceeded(float dtheta); - SteeringSystemData_s _system_data {}; SteeringParams_s _params; @@ -116,7 +100,30 @@ class SteeringSystem static constexpr float kBwB2 = 0.00235721f; static constexpr float kBwA1 = -1.85804330f; static constexpr float kBwA2 = 0.86747213f; + + float _convert_digital_sensor(const uint32_t digital_raw); + + float _convert_analog_sensor(const uint32_t analog_raw); + + float _filter_analog_angle(float x); + + /** + * @brief returns true if steering_analog is outside of the range defined by min and max sensor values + */ + bool _evaluate_steering_oor_analog(const uint32_t steering_analog); + + /** + * @brief returns true if steering_digital is outside the range defined by min and max sensor values + */ + bool _evaluate_steering_oor_digital(const uint32_t steering_digital); + + /** + * @brief returns true if change in angle exceeds maximum change per reading ( max_dtheta_threshold ) + */ + bool _evaluate_steering_dtheta_exceeded(float dtheta); + }; + using SteeringSystemInstance = etl::singleton; diff --git a/lib/systems/include/WatchdogSystem.h b/lib/systems/include/WatchdogSystem.h deleted file mode 100644 index e49557d..0000000 --- a/lib/systems/include/WatchdogSystem.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WATCHDOG_SYSTEM_H -#define WATCHDOG_SYSTEM_H - -#include - -/** - * This class controls the boolean _watchdog_state, but does not directly control the watchdog. - * WatchdogSystem provides functionality to initialize, monitor, and "kick" the watchdog to prevent system resets. - * - * NOTE: To ensure system responsiveness, WatchdogSystem requires periodic updates by calling the `get_watchdog_state()` method. - * This toggles the _watchdog_state (if the interval has passed) and returns the new state, which must then be sent to the watchdog. - */ - - -class WatchdogSystem -{ -public: - - WatchdogSystem(const unsigned long kick_interval_ms = 10UL) : _watchdog_time(0), _watchdog_state(false), _watchdog_kick_interval(kick_interval_ms) {}; -private: - - /*Private constructor*/ - - /* Watchdog last kicked time */ - unsigned long _watchdog_time; - bool _watchdog_state; - unsigned long _watchdog_kick_interval; - /* Watchdog output state */ - -public: - - /* Get/update watchdog state */ - bool get_watchdog_state(unsigned long curr_millis); - -}; - -using WatchdogInstance = etl::singleton; - -#endif /* WATCHDOG_SYSTEM_H */ diff --git a/lib/systems/src/IOExpanderUtils.cpp b/lib/systems/src/IOExpanderUtilities.cpp similarity index 68% rename from lib/systems/src/IOExpanderUtils.cpp rename to lib/systems/src/IOExpanderUtilities.cpp index a522a45..a13cd06 100644 --- a/lib/systems/src/IOExpanderUtils.cpp +++ b/lib/systems/src/IOExpanderUtilities.cpp @@ -1,10 +1,11 @@ -#include "IOExpanderUtils.h" +#include "IOExpanderUtilities.h" + /* * Retrieves the bit from the data frame. * Port A = 0, and is the lower byte of data. Port B = 1, and is the higher byte of data. */ -bool IOExpanderUtils::getBit(uint16_t data, bool port, uint8_t bit) +bool IOExpanderUtilities::getBit(uint16_t data, bool port, uint8_t bit) { return (data >> ((uint16_t) port * 8 + bit)) & 1; // NOLINT 8 is num of bits in byte } \ No newline at end of file diff --git a/lib/systems/src/NeopixelController.cpp b/lib/systems/src/NeopixelController.cpp index 6a96471..e41c722 100644 --- a/lib/systems/src/NeopixelController.cpp +++ b/lib/systems/src/NeopixelController.cpp @@ -1,5 +1,6 @@ #include "NeopixelController.h" + void NeopixelController::init_neopixels() { _neopixels.begin(); @@ -38,7 +39,8 @@ void NeopixelController::set_neopixel(uint16_t id, uint32_t c) void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data, CANInterfaces_s &interfaces) { // If we are in pedals recalibration state, LIGHT UP DASHBOARD ALL RED. - if (interfaces.vcr_interface.is_in_pedals_calibration_state() || interfaces.vcr_interface.is_in_steering_calibration_state()) { + if (interfaces.vcr_interface.is_in_pedals_calibration_state() || interfaces.vcr_interface.is_in_steering_calibration_state()) + { set_neopixel_color(LED_ID_e::BRAKE, LED_color_e::RED); set_neopixel_color(LED_ID_e::TORQUE_MODE, LED_color_e::RED); set_neopixel_color(LED_ID_e::LATCH, LED_color_e::RED); @@ -169,7 +171,6 @@ void NeopixelController::refresh_neopixels(const PedalsSystemData_s &pedals_data _neopixels.show(); - } void NeopixelController::set_neopixel_color(LED_ID_e led, LED_color_e color) diff --git a/lib/systems/src/WatchdogSystem.cpp b/lib/systems/src/WatchdogSystem.cpp deleted file mode 100644 index 6ecbac6..0000000 --- a/lib/systems/src/WatchdogSystem.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "WatchdogSystem.h" -#include "SharedFirmwareTypes.h" - -/* Returns intended watchdog state */ -bool WatchdogSystem::get_watchdog_state(unsigned long curr_millis) -{ - - if ((curr_millis - _watchdog_time) > _watchdog_kick_interval) { - _watchdog_state = !_watchdog_state; - _watchdog_time = curr_millis; - } - - return _watchdog_state; - -} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index c2dd462..0d147ec 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,228 +1,144 @@ -; HT09 VCF PlatformIO configuration file. +; Hytech VCF PlatformIO configuration file. ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [common] lib_deps_shared = - nanopb/Nanopb@0.4.91 - https://github.com/hytech-racing/shared_firmware_systems.git#af96a631bd76ac4da2084c6fa4faa62ca1bac9d1 - https://github.com/hytech-racing/shared_firmware_types.git#956ce41b93d93975a56d33aa3abd7efac7706533 - https://github.com/hytech-racing/HT_SCHED#c13cff762c59dd82a8c273e3e98fd1a80622656d - https://github.com/hytech-racing/HT_proto/releases/download/2026-05-07T16_36_28/hytech_msgs_pb_lib.tar.gz - https://github.com/hytech-racing/HT_CAN/releases/download/254/can_lib.tar.gz - etlcpp/Embedded Template Library + https://github.com/hytech-racing/shared_firmware_types.git#5e98919bd05951dee3daa3a42a5f73ea3539f093 + https://github.com/hytech-racing/shared_firmware_systems.git#af96a631bd76ac4da2084c6fa4faa62ca1bac9d1 + https://github.com/hytech-racing/HT_SCHED.git#c13cff762c59dd82a8c273e3e98fd1a80622656d + Embedded Template Library@^20.39.4 + nanopb/Nanopb@0.4.91 + +[hw_common] +lib_deps = + https://github.com/hytech-racing/HT_CAN/releases/download/264/can_lib.tar.gz + https://github.com/hytech-racing/HT_proto/releases/download/2026-06-14T06_30_48/hytech_msgs_pb_lib.tar.gz + https://github.com/hytech-racing/shared_firmware_interfaces.git#2c81ce7c0a8ef105241394d336166c075ca0d1ad + https://github.com/KSU-MS/pio-git-hash-gen#7998b5b3f8a2464209b0e73338717998bcf511ee + blemasle/MCP23017@^2.0.0 + arkhipenko/TaskScheduler@^3.8.5 + +[teensy_common] +platform = teensy@5.2.0 +board = teensy41 +framework = arduino +monitor_speed = 115200 +upload_protocol = teensy-cli +build_unflags = -std=gnu++11 +build_flags = + -std=c++17 + -D TEENSY_OPT_SMALLEST_CODE +check_tool = clangtidy +check_severity = medium, high +check_flags = + clangtidy: --config-file=./.clang-tidy +check_src_filters = + + + + + + + - +test_ignore = + test_interfaces + test_systems + +[platformio] +default_envs = teensy41 + ; Teensy41 Environment. This environment is the primary environment for uploading code to the car. ; * Build to verify the on-car software. ; * UPLOAD to compile and upload on-car software. ; * TEST is not yet configured. [env:teensy41] -check_tool = clangtidy -check_flags = - clangtidy: --config-file=./.clang-tidy -check_severity = medium, high -test_framework=googletest -build_unflags = -std=gnu++11 +extends = teensy_common +test_framework = googletest build_src_filter = - +<*.cpp> - - - - - - - - - - -build_flags = - -std=c++17 - -D TEENSY_OPT_SMALLEST_CODE -check_src_filters = - + - + - + - - -platform = teensy -board = teensy41 -framework = arduino -monitor_speed = 115200 -upload_protocol = teensy-cli -test_ignore = - test_interfaces - test_systems + +<*.cpp> + - + - + - + - + - lib_deps = - ${common.lib_deps_shared} - arkhipenko/TaskScheduler@^3.8.5 - https://github.com/ssilverman/QNEthernet#v0.26.0 - https://github.com/hytech-racing/shared_firmware_interfaces.git#d9f195a0e5640cd99411deb97c960edb7b455659 - blemasle/MCP23017@^2.0.0 - https://github.com/adafruit/Adafruit_NeoPixel.git - https://github.com/KSU-MS/pio-git-hash-gen#7998b5b3f8a2464209b0e73338717998bcf511ee + ${common.lib_deps_shared} + ${hw_common.lib_deps} + https://github.com/adafruit/Adafruit_NeoPixel.git -[env:test_orbis] -check_tool = clangtidy -check_flags = - clangtidy: --config-file=./.clang-tidy -check_severity = medium, high -build_unflags = -std=gnu++11 -build_src_filter = - +<*.cpp> - + - - - - - - - - - - -build_flags = - -std=c++17 - -D TEENSY_OPT_SMALLEST_CODE -check_src_filters = - +. ;Anything else I need to change? - + - + - - -platform = teensy -board = teensy41 -framework = arduino -monitor_speed = 115200 -upload_protocol = teensy-cli -test_ignore = - test_interfaces - test_systems -lib_deps = - ${common.lib_deps_shared} - arkhipenko/TaskScheduler@^3.8.5 - https://github.com/ssilverman/QNEthernet#v0.26.0 - https://github.com/hytech-racing/shared_firmware_interfaces.git#29a9cb09f91b684382e897de780d8d52a14659a7 - blemasle/MCP23017@^2.0.0 - https://github.com/adafruit/Adafruit_NeoPixel.git - https://github.com/KSU-MS/pio-git-hash-gen#7998b5b3f8a2464209b0e73338717998bcf511ee ; Test Systems Environment. This is only for compiling and uploading the hardware-abstracted code. ; * BUILD to verify the SYSTEMS compile. ; * DO NOT UPLOAD. This is a test-only environment. ; * TEST to run all unit tests in test_systems on the existing system code. [env:test_systems_env] -platform = native -test_framework = googletest +platform = native +test_framework = googletest +build_unflags = -std=gnu++11 +build_flags = + -std=c++17 + -g + -D TESTING_SYSTEMS +build_src_filter = + -<**/*.cpp> + +<../test/test_systems/main.cpp> +test_ignore = + test_interfaces* +lib_deps = + ${common.lib_deps_shared} + google/googletest@^1.15.2 + +[env:test_orbis] +extends = teensy_common build_src_filter = - -<**/*.cpp> - +<../test/test_systems/main.cpp> -build_unflags = -std=gnu++11 -build_flags = - -std=c++17 - -g - -D TESTING_SYSTEMS -lib_ignore= -test_ignore= - test_interfaces* + +<*.cpp> + + + - + - + - + - + - lib_deps = - ${common.lib_deps_shared} - google/googletest@^1.15.2 + ${common.lib_deps_shared} + ${hw_common.lib_deps} + https://github.com/adafruit/Adafruit_NeoPixel.git [env:test_adcs] -check_tool = clangtidy -check_flags = - clangtidy: --config-file=./.clang-tidy -check_severity = medium, high -build_unflags = -std=gnu++11 +extends = teensy_common build_src_filter = - +<*.cpp> - - - - - - - - - - -build_flags = - -std=c++17 - -D TEENSY_OPT_SMALLEST_CODE -check_src_filters = - + - + - + - - -platform = teensy -board = teensy41 -framework = arduino -monitor_speed = 115200 -upload_protocol = teensy-cli -test_ignore = - test_interfaces - test_systems + +<*.cpp> + - + - + - + - + - lib_deps = - ${common.lib_deps_shared} - arkhipenko/TaskScheduler@^3.8.5 - https://github.com/ssilverman/QNEthernet#v0.26.0 - https://github.com/hytech-racing/shared_firmware_interfaces.git#29a9cb09f91b684382e897de780d8d52a14659a7 - blemasle/MCP23017@^2.0.0 - https://github.com/KSU-MS/pio-git-hash-gen#7998b5b3f8a2464209b0e73338717998bcf511ee + ${common.lib_deps_shared} + ${hw_common.lib_deps} [env:test_can] -check_tool = clangtidy -check_flags = - clangtidy: --config-file=./.clang-tidy -check_severity = medium, high -build_unflags = -std=gnu++11 +extends = teensy_common build_src_filter = - +<*.cpp> - - - - - - - - - - -build_flags = - -std=c++17 - -D TEENSY_OPT_SMALLEST_CODE -check_src_filters = - + - + - + - - -platform = teensy -board = teensy41 -framework = arduino -monitor_speed = 115200 -upload_protocol = teensy-cli -test_ignore = - test_interfaces - test_systems + +<*.cpp> + - + - + - + - + - lib_deps = - ${common.lib_deps_shared} - https://github.com/hytech-racing/shared_firmware_interfaces.git - blemasle/MCP23017@^2.0.0 - https://github.com/KSU-MS/pio-git-hash-gen#7998b5b3f8a2464209b0e73338717998bcf511ee + ${common.lib_deps_shared} + ${hw_common.lib_deps} [env:test_pedals_env] -check_tool = clangtidy -check_flags = - clangtidy: --config-file=./.clang-tidy -check_severity = medium, high -test_framework=googletest -build_unflags = -std=gnu++11 +extends = teensy_common +test_framework = googletest build_src_filter = - +<*.cpp> - - - - - - - - - - -build_flags = - -std=c++17 - -D TEENSY_OPT_SMALLEST_CODE -check_src_filters = - + - + - + - - -platform = teensy -board = teensy41 -framework = arduino -monitor_speed = 115200 -upload_protocol = teensy-cli -test_ignore = - test_interfaces - test_systems + +<*.cpp> + - + - + - + - + - lib_deps = - ${common.lib_deps_shared} - arkhipenko/TaskScheduler@^3.8.5 - https://github.com/ssilverman/QNEthernet#v0.26.0 - blemasle/MCP23017@^2.0.0 - https://github.com/hytech-racing/shared_firmware_interfaces.git#29a9cb09f91b684382e897de780d8d52a14659a7 - https://github.com/KSU-MS/pio-git-hash-gen#7998b5b3f8a2464209b0e73338717998bcf511ee + ${common.lib_deps_shared} + ${hw_common.lib_deps} \ No newline at end of file diff --git a/src/VCF_InterfaceTasks.cpp b/src/VCF_InterfaceTasks.cpp index d7d7f00..4d2de7c 100644 --- a/src/VCF_InterfaceTasks.cpp +++ b/src/VCF_InterfaceTasks.cpp @@ -2,24 +2,130 @@ void initialize_all_interfaces() { - + SPI.begin(); + Serial.begin(VCFInterfaces::SERIAL_BAUDRATE); // NOLINT + + /* Watchdog Interface */ + WatchdogInterfaceInstance::create(WatchdogPinout_s { + VCFInterfaces::WATCHDOG_KICK_PIN, + VCFInterfaces::SOFTWARE_OK_PIN + } + ); + WatchdogInterfaceInstance::instance().init(); + + /* ACU Interface */ + ACUInterfaceInstance::create(); + + /* ADC Interface */ + ADCInterfaceInstance::create( + ADCPinout_s + { + VCFInterfaces::ADC0_CS, + VCFInterfaces::ADC1_CS + }, + ADCChannels_s + { + VCFInterfaces::PEDAL_REF_2V5_CHANNEL, + VCFInterfaces::STEERING_1_CHANNEL, + VCFInterfaces::STEERING_2_CHANNEL, + VCFInterfaces::ACCEL_1_CHANNEL, + VCFInterfaces::ACCEL_2_CHANNEL, + VCFInterfaces::BRAKE_1_CHANNEL, + VCFInterfaces::BRAKE_2_CHANNEL, + + VCFInterfaces::SHDN_H_CHANNEL, + VCFInterfaces::SHDN_D_CHANNEL, + VCFInterfaces::FL_LOADCELL_CHANNEL, + VCFInterfaces::FR_LOADCELL_CHANNEL, + VCFInterfaces::FR_SUS_POT_CHANNEL, + VCFInterfaces::FL_SUS_POT_CHANNEL, + VCFInterfaces::BRAKE_PRESSURE_FRONT_CHANNEL, + VCFInterfaces::BRAKE_PRESSURE_REAR_CHANNEL + }, + ADCScales_s + { + VCFInterfaces::PEDAL_REF_2V5_SCALE, + VCFInterfaces::STEERING_1_SCALE, + VCFInterfaces::STEERING_2_SCALE, + VCFInterfaces::ACCEL_1_SCALE, + VCFInterfaces::ACCEL_2_SCALE, + VCFInterfaces::BRAKE_1_SCALE, + VCFInterfaces::BRAKE_2_SCALE, + + VCFInterfaces::SHDN_H_SCALE, + VCFInterfaces::SHDN_D_SCALE, + VCFInterfaces::FL_LOADCELL_SCALE, + VCFInterfaces::FR_LOADCELL_SCALE, + VCFInterfaces::FR_SUS_POT_SCALE, + VCFInterfaces::FL_SUS_POT_SCALE, + VCFInterfaces::BRAKE_PRESSURE_FRONT_SCALE, + VCFInterfaces::BRAKE_PRESSURE_REAR_SCALE + }, + ADCOffsets_s + { + VCFInterfaces::PEDAL_REF_2V5_OFFSET, + VCFInterfaces::STEERING_1_OFFSET, + VCFInterfaces::STEERING_2_OFFSET, + VCFInterfaces::ACCEL_1_OFFSET, + VCFInterfaces::ACCEL_2_OFFSET, + VCFInterfaces::BRAKE_1_OFFSET, + VCFInterfaces::BRAKE_2_OFFSET, + + VCFInterfaces::SHDN_H_OFFSET, + VCFInterfaces::SHDN_D_OFFSET, + VCFInterfaces::FL_LOADCELL_OFFSET, + VCFInterfaces::FR_LOADCELL_OFFSET, + VCFInterfaces::FR_SUS_POT_OFFSET, + VCFInterfaces::FL_SUS_POT_OFFSET, + VCFInterfaces::BRAKE_PRESSURE_FRONT_OFFSET, + VCFInterfaces::BRAKE_PRESSURE_REAR_OFFSET + } + ); + + /* Brake Rotor Temp Interface */ + BrakeRotorTempInterfaceInstance::create(); /* Dashboard Interface */ - DashboardInterfaceInstance::create(); - DashboardInterfaceInstance::instance().init(); + DashboardGPIOs_s dashboard_gpios = { + .BRIGHTNESS_CONTROL_PIN = VCFInterfaces::BRIGHTNESS_CONTROL_PIN, + .PRESET_BUTTON = VCFInterfaces::BTN_PRESET_READ, + .MC_CYCLE_BUTTON = VCFInterfaces::BTN_MC_CYCLE_READ, + .START_BUTTON = VCFInterfaces::BTN_START_READ, + .DATA_BUTTON = VCFInterfaces::BTN_DATA_READ, + .BUTTON_2 = VCFInterfaces::BUTTON_2 + }; + DashboardInterfaceInstance::create(dashboard_gpios, VCFSystems::IO_EXPANDER_ADDR, Wire2); //NOLINT + DashboardInterfaceInstance::instance().init(); + + /* Orbis Interface */ + OrbisInterfaceInstance::create(&Serial2); // fix t + + /* VCR Interface */ + VCRInterfaceInstance::create(); + + /* CAN Interfaces */ + CANInterfacesInstance::create(ACUInterfaceInstance::instance(), + BrakeRotorTempInterfaceInstance::instance(), + DashboardInterfaceInstance::instance(), + VCRInterfaceInstance::instance() + ); + handle_CAN_setup(VCFCANInterfaceInstance::instance().TELEM_CAN, VCFConstants::TELEM_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_telem_can_recv); + handle_CAN_setup(VCFCANInterfaceInstance::instance().FRONT_AUX_CAN, VCFConstants::FAUX_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_front_aux_can_recv); + // Create Ethernet singletons + VCFEthernetInterfaceInstance::create(); + VCFEthernetInterfaceInstance::instance().init_ethernet_device(); } HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { // Updates all eight channels. - ADCInterfaceInstance::instance().adc0_tick(); - OrbisBRInstance::instance().sample(); - PedalsSystemInstance::instance().set_pedals_sensor_data(PedalSensorData_s{ - .accel_1 = static_cast(ADCInterfaceInstance::instance().acceleration_1().conversion), - .accel_2 = static_cast(ADCInterfaceInstance::instance().acceleration_2().conversion), - .brake_1 = static_cast(ADCInterfaceInstance::instance().brake_1().conversion), - .brake_2 = static_cast(ADCInterfaceInstance::instance().brake_2().conversion) + ADCInterfaceInstance::instance().tick_adc0(); + PedalsSystemInstance::instance().set_pedals_sensor_data(PedalSensorData_s { + .accel_1 = static_cast(ADCInterfaceInstance::instance().get_acceleration_1().conversion), + .accel_2 = static_cast(ADCInterfaceInstance::instance().get_acceleration_2().conversion), + .brake_1 = static_cast(ADCInterfaceInstance::instance().get_brake_1().conversion), + .brake_2 = static_cast(ADCInterfaceInstance::instance().get_brake_2().conversion) }); return HT_TASK::TaskResponse::YIELD; @@ -28,70 +134,17 @@ HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const H HT_TASK::TaskResponse run_read_adc1_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { // Samples all eight channels. - ADCInterfaceInstance::instance().adc1_tick(); - ADCInterfaceInstance::instance().update_filtered_values(VCFTaskConstants::LOADCELL_IIR_FILTER_ALPHA); + ADCInterfaceInstance::instance().tick_adc1(); + ADCInterfaceInstance::instance().update_filtered_values(VCFInterfaces::LOADCELL_IIR_FILTER_ALPHA); return HT_TASK::TaskResponse::YIELD; } -HT_TASK::TaskResponse init_kick_watchdog(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) +HT_TASK::TaskResponse run_kick_watchdog(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - WatchdogInstance::create(VCFInterfaceConstants::WATCHDOG_KICK_INTERVAL_MS); // NOLINT - pinMode(VCFInterfaceConstants::WATCHDOG_PIN, OUTPUT); - pinMode(VCFInterfaceConstants::SOFTWARE_OK_PIN, OUTPUT); - return HT_TASK::TaskResponse::YIELD; -} - -HT_TASK::TaskResponse run_kick_watchdog(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - digitalWrite(VCFInterfaceConstants::SOFTWARE_OK_PIN, HIGH); - digitalWrite(VCFInterfaceConstants::WATCHDOG_PIN, WatchdogInstance::instance().get_watchdog_state(sys_time::hal_millis())); - return HT_TASK::TaskResponse::YIELD; -} - -HT_TASK::TaskResponse update_pedals_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - // Observed pedal values (ONLY USED FOR RECALIBRATION) - // WARNING: These are the true min/max observed values, NOT the "value at min travel" and "value at max travel" - // that are defined in the PedalsParam struct. - PedalsSystemInstance::instance().update_observed_pedal_limits(PedalsSystemInstance::instance().get_pedals_sensor_data()); - - if (VCRInterfaceInstance::instance().is_in_pedals_calibration_state()) - { - // PedalsSystemInstance::instance().recalibrate_min_max(VCFData_sInstance::instance().interface_data.pedal_sensor_data); - PedalsSystemInstance::instance().recalibrate_min_max(PedalsSystemInstance::instance().get_pedals_sensor_data()); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::ACCEL_1_MIN_ADDR, PedalsSystemInstance::instance().get_accel_params().min_pedal_1); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::ACCEL_1_MAX_ADDR, PedalsSystemInstance::instance().get_accel_params().max_pedal_1); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::ACCEL_2_MIN_ADDR, PedalsSystemInstance::instance().get_accel_params().min_pedal_2); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::ACCEL_2_MAX_ADDR, PedalsSystemInstance::instance().get_accel_params().max_pedal_2); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::BRAKE_1_MIN_ADDR, PedalsSystemInstance::instance().get_brake_params().min_pedal_1); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::BRAKE_1_MAX_ADDR, PedalsSystemInstance::instance().get_brake_params().max_pedal_1); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::BRAKE_2_MIN_ADDR, PedalsSystemInstance::instance().get_brake_params().min_pedal_2); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::BRAKE_2_MAX_ADDR, PedalsSystemInstance::instance().get_brake_params().max_pedal_2); - } - + WatchdogInterfaceInstance::instance().update_watchdog_state(sys_time::hal_millis()); return HT_TASK::TaskResponse::YIELD; } -HT_TASK::TaskResponse update_steering_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - const uint32_t analog_raw = SteeringSystemInstance::instance().get_steering_system_data().analog_raw; // NOLINT thinks this is not initialized - const uint32_t digital_raw = SteeringSystemInstance::instance().get_steering_system_data().digital_raw; // NOLINT thinks this is not initialized - - SteeringSystemInstance::instance().update_observed_steering_limits(analog_raw, digital_raw); - - - if (VCRInterfaceInstance::instance().is_in_steering_calibration_state()) { - - SteeringSystemInstance::instance().recalibrate_steering_digital(); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_ANALOG_ADDR, SteeringSystemInstance::instance().get_steering_params().min_steering_signal_analog); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::MAX_STEERING_SIGNAL_ANALOG_ADDR, SteeringSystemInstance::instance().get_steering_params().max_steering_signal_analog); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_DIGITAL_ADDR, SteeringSystemInstance::instance().get_steering_params().min_steering_signal_digital); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::MAX_STEERING_SIGNAL_DIGITAL_ADDR, SteeringSystemInstance::instance().get_steering_params().max_steering_signal_digital); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::ANALOG_MIN_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().analog_min_with_margins); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::ANALOG_MAX_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().analog_max_with_margins); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::DIGITAL_MIN_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().digital_min_with_margins); - EEPROMUtilities::write_eeprom_32bit(VCFSystemConstants::DIGITAL_MAX_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().digital_max_with_margins); - } - - return HT_TASK::TaskResponse::YIELD; -} // bool init_read_gpio_task() // { // // Setting digital/analog buttons D10-D6, A8 as inputs @@ -126,7 +179,7 @@ HT_TASK::TaskResponse update_steering_calibration_task(const unsigned long& sysM HT_TASK::TaskResponse init_buzzer_control_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - pinMode(VCFInterfaceConstants::BUZZER_CONTROL_PIN, OUTPUT); + pinMode(VCFInterfaces::BUZZER_CONTROL_PIN, OUTPUT); return HT_TASK::TaskResponse::YIELD; } @@ -136,7 +189,7 @@ HT_TASK::TaskResponse run_buzzer_control_task(const unsigned long& sysMicros, co bool buzzer_is_active = BuzzerController::getInstance().buzzer_is_active(sys_time::hal_millis()); //NOLINT - digitalWrite(VCFInterfaceConstants::BUZZER_CONTROL_PIN, buzzer_is_active); + digitalWrite(VCFInterfaces::BUZZER_CONTROL_PIN, buzzer_is_active); return HT_TASK::TaskResponse::YIELD; } @@ -184,41 +237,21 @@ HT_TASK::TaskResponse enqueue_front_suspension_data(const unsigned long& sysMicr return HT_TASK::TaskResponse::YIELD; } -HT_TASK::TaskResponse enqueue_steering_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) -{ - STEERING_DATA_t msg_out; - SteeringSystemData_s steering_system_data = SteeringSystemInstance::instance().get_steering_system_data(); - - msg_out.steering_analog_oor = steering_system_data.analog_oor_implausibility; - msg_out.steering_both_sensors_fail = steering_system_data.both_sensors_fail; - msg_out.steering_digital_oor = steering_system_data.digital_oor_implausibility; - msg_out.steering_dtheta_exceeded_analog = steering_system_data.dtheta_exceeded_analog; - msg_out.steering_dtheta_exceeded_digital = steering_system_data.dtheta_exceeded_digital; - msg_out.steering_interface_sensor_error = steering_system_data.interface_sensor_error; - msg_out.steering_output_steering_angle_ro = HYTECH_steering_output_steering_angle_ro_toS(steering_system_data.output_steering_angle); - msg_out.steering_sensor_disagreement = steering_system_data.sensor_disagreement_implausibility; - msg_out.steering_analog_raw = steering_system_data.analog_raw; - msg_out.steering_digital_raw = steering_system_data.digital_raw; - - CAN_util::enqueue_msg(&msg_out, &Pack_STEERING_DATA_hytech, VCFCANInterfaceInstance::instance().telem_can_tx_buffer); - return HT_TASK::TaskResponse::YIELD; -} - HT_TASK::TaskResponse init_handle_send_vcf_ethernet_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { VCFEthernetInterfaceInstance::instance().init_ethernet_device(); return HT_TASK::TaskResponse::YIELD; } -HT_TASK::TaskResponse run_handle_send_vcf_ethernet_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { - hytech_msgs_VCFData_s msg = VCFEthernetInterface::make_vcf_data_msg(ADCInterfaceInstance::instance(), DashboardInterfaceInstance::instance(), PedalsSystemInstance::instance(), SteeringSystemInstance::instance(), BrakeRotorTempInstance::instance()); - if(handle_ethernet_socket_send_pb - (EthernetIPDefsInstance::instance().drivebrain_ip, - EthernetIPDefsInstance::instance().VCFData_port, - &VCFEthernetInterface::VCF_socket, - msg, - hytech_msgs_VCFData_s_fields)) { - } +HT_TASK::TaskResponse run_handle_send_vcf_ethernet_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) +{ + hytech_msgs_VCFData_s msg = VCFEthernetInterfaceInstance::instance().make_vcf_data_msg(ADCInterfaceInstance::instance(), + DashboardInterfaceInstance::instance(), + PedalsSystemInstance::instance(), + SteeringSystemInstance::instance(), + BrakeRotorTempInterfaceInstance::instance() + ); + VCFEthernetInterfaceInstance::instance().handle_send_ethernet_vcf_data(msg); return HT_TASK::TaskResponse::YIELD; } @@ -234,26 +267,6 @@ HT_TASK::TaskResponse run_handle_send_vcf_ethernet_data(const unsigned long& sys // return HT_TASK::TaskResponse::YIELD; // } -HT_TASK::TaskResponse enqueue_pedals_data(const unsigned long &sys_micros, const HT_TASK::TaskInfo& task_info) -{ - PEDALS_SYSTEM_DATA_t pedals_data = {}; - - pedals_data.accel_implausible = PedalsSystemInstance::instance().get_pedals_system_data().accel_is_implausible; - pedals_data.brake_implausible = PedalsSystemInstance::instance().get_pedals_system_data().brake_is_implausible; - pedals_data.brake_accel_implausibility = PedalsSystemInstance::instance().get_pedals_system_data().brake_and_accel_pressed_implausibility_high; - - pedals_data.accel_pedal_active = PedalsSystemInstance::instance().get_pedals_system_data().accel_is_pressed; - pedals_data.brake_pedal_active = PedalsSystemInstance::instance().get_pedals_system_data().brake_is_pressed; - pedals_data.mechanical_brake_active = PedalsSystemInstance::instance().get_pedals_system_data().mech_brake_is_active; - pedals_data.implaus_exceeded_max_duration = PedalsSystemInstance::instance().get_pedals_system_data().implausibility_has_exceeded_max_duration; - - - pedals_data.accel_pedal_ro = HYTECH_accel_pedal_ro_toS(PedalsSystemInstance::instance().get_pedals_system_data().accel_percent); - pedals_data.brake_pedal_ro = HYTECH_brake_pedal_ro_toS(PedalsSystemInstance::instance().get_pedals_system_data().brake_percent); - - CAN_util::enqueue_msg(&pedals_data, &Pack_PEDALS_SYSTEM_DATA_hytech, VCFCANInterfaceInstance::instance().telem_can_tx_buffer); - return HT_TASK::TaskResponse::YIELD; -} HT_TASK::TaskResponse run_dash_GPIOs_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info) { @@ -283,19 +296,6 @@ HT_TASK::TaskResponse run_dash_GPIOs_task(const unsigned long& sys_micros, const return HT_TASK::TaskResponse::YIELD; } -HT_TASK::TaskResponse init_neopixels_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info) -{ - NeopixelControllerInstance::create(VCFInterfaceConstants::NEOPIXEL_COUNT, VCFInterfaceConstants::NEOPIXEL_CONTROL_PIN); - NeopixelControllerInstance::instance().init_neopixels(); - return HT_TASK::TaskResponse::YIELD; -} - -HT_TASK::TaskResponse run_update_neopixels_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info) -{ - NeopixelControllerInstance::instance().refresh_neopixels(PedalsSystemInstance::instance().get_pedals_system_data(), CANInterfacesInstance::instance()); - return HT_TASK::TaskResponse::YIELD; -} - namespace async_tasks { // these are async tasks. we want these to run as fast as possible p much @@ -316,11 +316,11 @@ namespace async_tasks { handle_async_recvs(); - SteeringSystemInstance::instance().evaluate_steering( - ADCInterfaceInstance::instance().get_steering_degrees_cw().conversion, - OrbisBRInstance::instance().getLastReading(), - sys_time::hal_millis() - ); + // SteeringSystemInstance::instance().evaluate_steering( + // ADCInterfaceInstance::instance().get_steering_degrees_cw().conversion, + // // OrbisInterfaceInstance::instance().getLastReading(), + // sys_time::hal_millis() + // ); PedalsSystemInstance::instance().evaluate_pedals( PedalsSystemInstance::instance().get_pedals_sensor_data(), @@ -367,9 +367,9 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: Serial.print("|"); Serial.println(SteeringSystemInstance::instance().get_steering_system_data().digital_steering_angle); Serial.print("min_observed_analog: "); - Serial.println(SteeringSystemInstance::instance().get_min_observed_analog()); - Serial.print("max_observed_analog: "); - Serial.println(SteeringSystemInstance::instance().get_max_observed_analog()); + // Serial.println(SteeringSystemInstance::instance().get_min_observed_analog()); + // Serial.print("max_observed_analog: "); + // Serial.println(SteeringSystemInstance::instance().get_max_observed_analog()); Serial.print("analog_steering_angle: "); Serial.println(SteeringSystemInstance::instance().get_steering_system_data().analog_steering_angle); Serial.print("digital_steering_angle: "); @@ -410,19 +410,19 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: Serial.print(ADCInterfaceInstance::instance().pedal_reference().raw); Serial.print("\t"); Serial.print(ADCInterfaceInstance::instance().get_steering_degrees_cw().raw); Serial.print("\t"); Serial.print(ADCInterfaceInstance::instance().get_steering_degrees_ccw().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().acceleration_1().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().acceleration_2().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().brake_1().raw); Serial.print("\t"); - Serial.println(ADCInterfaceInstance::instance().brake_2().raw); + Serial.print(ADCInterfaceInstance::instance().get_acceleration_1().raw); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_acceleration_2().raw); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_brake_1().raw); Serial.print("\t"); + Serial.println(ADCInterfaceInstance::instance().get_brake_2().raw); // Converted values Serial.print("Convert\t"); Serial.print(ADCInterfaceInstance::instance().pedal_reference().conversion); Serial.print("\t"); Serial.print(ADCInterfaceInstance::instance().get_steering_degrees_cw().conversion); Serial.print("\t"); Serial.print(ADCInterfaceInstance::instance().get_steering_degrees_ccw().conversion); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().acceleration_1().conversion); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().acceleration_2().conversion); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().brake_1().conversion); Serial.print("\t"); - Serial.println(ADCInterfaceInstance::instance().brake_2().conversion); + Serial.print(ADCInterfaceInstance::instance().get_acceleration_1().conversion); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_acceleration_2().conversion); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_brake_1().conversion); Serial.print("\t"); + Serial.println(ADCInterfaceInstance::instance().get_brake_2().conversion); // ADC 1 Serial.println("\nADC 1\t\t\t Load Cells \t Sus Pots \t Brake Pressure"); @@ -431,10 +431,10 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: Serial.print("Raw\t"); Serial.print(ADCInterfaceInstance::instance().shdn_h().raw); Serial.print("\t"); Serial.print(ADCInterfaceInstance::instance().shdn_d().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().FL_load_cell().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().FR_load_cell().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().FR_sus_pot().raw); Serial.print("\t"); - Serial.print(ADCInterfaceInstance::instance().FL_sus_pot().raw); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_FL_load_cell().raw); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_FR_load_cell().raw); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_FR_sus_pot().raw); Serial.print("\t"); + Serial.print(ADCInterfaceInstance::instance().get_FL_sus_pot().raw); Serial.print("\t"); Serial.print(ADCInterfaceInstance::instance().get_brake_pressure_front().raw); Serial.print("\t"); Serial.println(ADCInterfaceInstance::instance().get_brake_pressure_rear().raw); // Conversion ADC @@ -463,174 +463,27 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: // Sensor 1 Serial.print("FL\t"); - Serial.print(BrakeRotorTempInstance::instance().getBrakeRotorTempData().fl_sensor.max_temp); Serial.print("\t"); - Serial.print(BrakeRotorTempInstance::instance().getBrakeRotorTempData().fl_sensor.avg_temp); Serial.print("\t"); + Serial.print(BrakeRotorTempInterfaceInstance::instance().getBrakeRotorTempData().fl_sensor.max_temp); Serial.print("\t"); + Serial.print(BrakeRotorTempInterfaceInstance::instance().getBrakeRotorTempData().fl_sensor.avg_temp); Serial.print("\t"); - for (size_t i = 0; i < BrakeRotorTempDefaultParams::channels_within_brake_temp_sensor; ++i) { - Serial.print(BrakeRotorTempInstance::instance().getBrakeRotorTempData().fl_sensor.channel_data[i]); + for (size_t i = 0; i < brake_rotor_temp_default_params::channels_within_brake_temp_sensor; ++i) + { + Serial.print(BrakeRotorTempInterfaceInstance::instance().getBrakeRotorTempData().fl_sensor.channel_data[i]); Serial.print("\t"); } Serial.println(); // Sensor 2 Serial.print("FR\t"); - Serial.print(BrakeRotorTempInstance::instance().getBrakeRotorTempData().fr_sensor.max_temp); Serial.print("\t"); - Serial.print(BrakeRotorTempInstance::instance().getBrakeRotorTempData().fr_sensor.avg_temp); Serial.print("\t"); + Serial.print(BrakeRotorTempInterfaceInstance::instance().getBrakeRotorTempData().fr_sensor.max_temp); Serial.print("\t"); + Serial.print(BrakeRotorTempInterfaceInstance::instance().getBrakeRotorTempData().fr_sensor.avg_temp); Serial.print("\t"); - for (size_t i = 0; i < BrakeRotorTempDefaultParams::channels_within_brake_temp_sensor; ++i) { - Serial.print(BrakeRotorTempInstance::instance().getBrakeRotorTempData().fr_sensor.channel_data[i]); + for (size_t i = 0; i < brake_rotor_temp_default_params::channels_within_brake_temp_sensor; ++i) + { + Serial.print(BrakeRotorTempInterfaceInstance::instance().getBrakeRotorTempData().fr_sensor.channel_data[i]); Serial.print("\t"); } Serial.println(); return HT_TASK::TaskResponse::YIELD; -} - -void setup_all_interfaces() { - SPI.begin(); - Serial.begin(VCFTaskConstants::SERIAL_BAUDRATE); // NOLINT - - /* Init singletons */ - // Create ADC interface singleton - ADCInterfaceInstance::create( - ADCPinout_s { - VCFInterfaceConstants::ADC0_CS, - VCFInterfaceConstants::ADC1_CS - }, - ADCChannels_s { - VCFInterfaceConstants::PEDAL_REF_2V5_CHANNEL, - VCFInterfaceConstants::STEERING_1_CHANNEL, - VCFInterfaceConstants::STEERING_2_CHANNEL, - VCFInterfaceConstants::ACCEL_1_CHANNEL, - VCFInterfaceConstants::ACCEL_2_CHANNEL, - VCFInterfaceConstants::BRAKE_1_CHANNEL, - VCFInterfaceConstants::BRAKE_2_CHANNEL, - - VCFInterfaceConstants::SHDN_H_CHANNEL, - VCFInterfaceConstants::SHDN_D_CHANNEL, - VCFInterfaceConstants::FL_LOADCELL_CHANNEL, - VCFInterfaceConstants::FR_LOADCELL_CHANNEL, - VCFInterfaceConstants::FR_SUS_POT_CHANNEL, - VCFInterfaceConstants::FL_SUS_POT_CHANNEL, - VCFInterfaceConstants::BRAKE_PRESSURE_FRONT_CHANNEL, - VCFInterfaceConstants::BRAKE_PRESSURE_REAR_CHANNEL - }, - ADCScales_s { - VCFInterfaceConstants::PEDAL_REF_2V5_SCALE, - VCFInterfaceConstants::STEERING_1_SCALE, - VCFInterfaceConstants::STEERING_2_SCALE, - VCFInterfaceConstants::ACCEL_1_SCALE, - VCFInterfaceConstants::ACCEL_2_SCALE, - VCFInterfaceConstants::BRAKE_1_SCALE, - VCFInterfaceConstants::BRAKE_2_SCALE, - - VCFInterfaceConstants::SHDN_H_SCALE, - VCFInterfaceConstants::SHDN_D_SCALE, - VCFInterfaceConstants::FL_LOADCELL_SCALE, - VCFInterfaceConstants::FR_LOADCELL_SCALE, - VCFInterfaceConstants::FR_SUS_POT_SCALE, - VCFInterfaceConstants::FL_SUS_POT_SCALE, - VCFInterfaceConstants::BRAKE_PRESSURE_FRONT_SCALE, - VCFInterfaceConstants::BRAKE_PRESSURE_REAR_SCALE - }, - ADCOffsets_s { - VCFInterfaceConstants::PEDAL_REF_2V5_OFFSET, - VCFInterfaceConstants::STEERING_1_OFFSET, - VCFInterfaceConstants::STEERING_2_OFFSET, - VCFInterfaceConstants::ACCEL_1_OFFSET, - VCFInterfaceConstants::ACCEL_2_OFFSET, - VCFInterfaceConstants::BRAKE_1_OFFSET, - VCFInterfaceConstants::BRAKE_2_OFFSET, - - VCFInterfaceConstants::SHDN_H_OFFSET, - VCFInterfaceConstants::SHDN_D_OFFSET, - VCFInterfaceConstants::FL_LOADCELL_OFFSET, - VCFInterfaceConstants::FR_LOADCELL_OFFSET, - VCFInterfaceConstants::FR_SUS_POT_OFFSET, - VCFInterfaceConstants::FL_SUS_POT_OFFSET, - VCFInterfaceConstants::BRAKE_PRESSURE_FRONT_OFFSET, - VCFInterfaceConstants::BRAKE_PRESSURE_REAR_OFFSET - }); - - // Create pedals singleton - PedalsParams accel_params = { - .min_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::ACCEL_1_MIN_ADDR), - .min_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::ACCEL_2_MIN_ADDR), - .max_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::ACCEL_1_MAX_ADDR), - .max_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::ACCEL_2_MAX_ADDR), - .activation_percentage = VCFSystemConstants::ACCEL_ACTIVATION_PERCENTAGE, - .min_sensor_pedal_1 = VCFSystemConstants::ACCEL_MIN_SENSOR_PEDAL_1, - .min_sensor_pedal_2 = VCFSystemConstants::ACCEL_MIN_SENSOR_PEDAL_2, - .max_sensor_pedal_1 = VCFSystemConstants::ACCEL_MAX_SENSOR_PEDAL_1, - .max_sensor_pedal_2 = VCFSystemConstants::ACCEL_MAX_SENSOR_PEDAL_2, - .deadzone_margin = VCFSystemConstants::ACCEL_DEADZONE_MARGIN, - .implausibility_margin = IMPLAUSIBILITY_PERCENT, - .mechanical_activation_percentage = VCFSystemConstants::ACCEL_MECHANICAL_ACTIVATION_PERCENTAGE - }; - PedalsParams brake_params = { - .min_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::BRAKE_1_MIN_ADDR), - .min_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::BRAKE_2_MIN_ADDR), - .max_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::BRAKE_1_MAX_ADDR), - .max_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::BRAKE_2_MAX_ADDR), - .activation_percentage = VCFSystemConstants::BRAKE_ACTIVATION_PERCENTAGE, - .min_sensor_pedal_1 = VCFSystemConstants::BRAKE_MIN_SENSOR_PEDAL_1, - .min_sensor_pedal_2 = VCFSystemConstants::BRAKE_MIN_SENSOR_PEDAL_2, - .max_sensor_pedal_1 = VCFSystemConstants::BRAKE_MAX_SENSOR_PEDAL_1, - .max_sensor_pedal_2 = VCFSystemConstants::BRAKE_MAX_SENSOR_PEDAL_2, - .deadzone_margin = VCFSystemConstants::BRAKE_DEADZONE_MARGIN, - .implausibility_margin = IMPLAUSIBILITY_PERCENT, - .mechanical_activation_percentage = VCFSystemConstants::BRAKE_MECHANICAL_ACTIVATION_PERCENTAGE - }; - PedalsSystemInstance::create(accel_params, brake_params); //pass in the two different params - - SteeringParams_s steering_params = { - .min_steering_signal_analog = EEPROMUtils::read_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_ANALOG_ADDR), - .max_steering_signal_analog = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MAX_STEERING_SIGNAL_ANALOG_ADDR), - .min_steering_signal_digital = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MIN_STEERING_SIGNAL_DIGITAL_ADDR), - .max_steering_signal_digital = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::MAX_STEERING_SIGNAL_DIGITAL_ADDR), - .analog_min_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::ANALOG_MIN_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok - .analog_max_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::ANALOG_MAX_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok - .digital_min_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::DIGITAL_MIN_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok - .digital_max_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystemConstants::DIGITAL_MAX_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok - .deg_per_count_analog = VCFSystemConstants::DEG_PER_COUNT_ANALOG, - .deg_per_count_digital = VCFSystemConstants::DEG_PER_COUNT_DIGITAL, - .analog_tolerance = VCFSystemConstants::ANALOG_TOLERANCE, - .digital_tolerance = VCFSystemConstants::DIGITAL_TOLERANCE, - .max_dtheta_threshold = VCFSystemConstants::MAX_DTHETA_THRESHOLD, - .error_between_sensors_tolerance = VCFSystemConstants::ERROR_BETWEEN_SENSORS_TOLERANCE - - }; - steering_params.span_signal_analog = steering_params.max_steering_signal_analog - steering_params.min_steering_signal_analog; - steering_params.analog_midpoint = (steering_params.max_steering_signal_analog + steering_params.min_steering_signal_analog) / 2; - steering_params.span_signal_digital = steering_params.max_steering_signal_digital - steering_params.min_steering_signal_digital; - steering_params.digital_midpoint = (steering_params.min_steering_signal_digital + steering_params.max_steering_signal_digital) / 2; - SteeringSystemInstance::create(steering_params); // NOLINT thinks steering params is not initialized - - // Create Digital Steering Sensor singleton - // OrbisBRInstance::create(&Serial2); - - // Create dashboard singleton - DashboardGPIOs_s dashboard_gpios = { - .BRIGHTNESS_CONTROL_PIN = VCFInterfaceConstants::BRIGHTNESS_CONTROL_PIN, - .PRESET_BUTTON = VCFInterfaceConstants::BTN_PRESET_READ, - .MC_CYCLE_BUTTON = VCFInterfaceConstants::BTN_MC_CYCLE_READ, - .START_BUTTON = VCFInterfaceConstants::BTN_START_READ, - .DATA_BUTTON = VCFInterfaceConstants::BTN_DATA_READ, - .BUTTON_2 = VCFInterfaceConstants::BUTTON_2 - }; - DashboardInterfaceInstance::create(dashboard_gpios, VCFInterfaceConstants::IO_EXPANDER_ADDR, Wire2); //NOLINT - ACUInterfaceInstance::create(); - VCRInterfaceInstance::create(); - - // Create CAN singletons - CANInterfacesInstance::create(ACUInterfaceInstance::instance(), BrakeRotorTempInstance::instance(), DashboardInterfaceInstance::instance(), VCRInterfaceInstance::instance()); - VCFCANInterfaceInstance::create(etl::delegate::create()); - handle_CAN_setup(VCFCANInterfaceInstance::instance().TELEM_CAN, VCFInterfaceConstants::TELEM_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_telem_can_recv); - handle_CAN_setup(VCFCANInterfaceInstance::instance().FRONT_AUX_CAN, VCFInterfaceConstants::FAUX_CAN_BAUDRATE, &VCFCANInterfaceImpl::on_front_aux_can_recv); - - // Create Ethernet singletons - EthernetIPDefsInstance::create(); - uint8_t mac[6]; // NOLINT (mac addresses are always 6 bytes) - qindesign::network::Ethernet.macAddress(&mac[0]); - qindesign::network::Ethernet.begin(mac, EthernetIPDefsInstance::instance().vcf_ip, EthernetIPDefsInstance::instance().default_dns, EthernetIPDefsInstance::instance().default_gateway, EthernetIPDefsInstance::instance().car_subnet); -} +} \ No newline at end of file diff --git a/src/VCF_SystemTasks.cpp b/src/VCF_SystemTasks.cpp index e69de29..813d3b2 100644 --- a/src/VCF_SystemTasks.cpp +++ b/src/VCF_SystemTasks.cpp @@ -0,0 +1,161 @@ +#include "VCF_SystemTasks.h" + + +void initialize_all_systems() +{ + + /* Neopixel Controller */ + NeopixelControllerInstance::create(VCFSystems::NEOPIXEL_COUNT, VCFSystems::NEOPIXEL_CONTROL_PIN); + NeopixelControllerInstance::instance().init_neopixels(); + + /* Pedals System */ + PedalsParams accel_params = { + .min_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::ACCEL_1_MIN_ADDR), + .min_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::ACCEL_2_MIN_ADDR), + .max_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::ACCEL_1_MAX_ADDR), + .max_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::ACCEL_2_MAX_ADDR), + .activation_percentage = VCFSystems::ACCEL_ACTIVATION_PERCENTAGE, + .min_sensor_pedal_1 = VCFSystems::ACCEL_MIN_SENSOR_PEDAL_1, + .min_sensor_pedal_2 = VCFSystems::ACCEL_MIN_SENSOR_PEDAL_2, + .max_sensor_pedal_1 = VCFSystems::ACCEL_MAX_SENSOR_PEDAL_1, + .max_sensor_pedal_2 = VCFSystems::ACCEL_MAX_SENSOR_PEDAL_2, + .deadzone_margin = VCFSystems::ACCEL_DEADZONE_MARGIN, + .implausibility_margin = IMPLAUSIBILITY_PERCENT, + .mechanical_activation_percentage = VCFSystems::ACCEL_MECHANICAL_ACTIVATION_PERCENTAGE + }; + + PedalsParams brake_params = { + .min_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::BRAKE_1_MIN_ADDR), + .min_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::BRAKE_2_MIN_ADDR), + .max_pedal_1 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::BRAKE_1_MAX_ADDR), + .max_pedal_2 = EEPROMUtilities::read_eeprom_32bit(VCFSystems::BRAKE_2_MAX_ADDR), + .activation_percentage = VCFSystems::BRAKE_ACTIVATION_PERCENTAGE, + .min_sensor_pedal_1 = VCFSystems::BRAKE_MIN_SENSOR_PEDAL_1, + .min_sensor_pedal_2 = VCFSystems::BRAKE_MIN_SENSOR_PEDAL_2, + .max_sensor_pedal_1 = VCFSystems::BRAKE_MAX_SENSOR_PEDAL_1, + .max_sensor_pedal_2 = VCFSystems::BRAKE_MAX_SENSOR_PEDAL_2, + .deadzone_margin = VCFSystems::BRAKE_DEADZONE_MARGIN, + .implausibility_margin = IMPLAUSIBILITY_PERCENT, + .mechanical_activation_percentage = VCFSystems::BRAKE_MECHANICAL_ACTIVATION_PERCENTAGE + }; + PedalsSystemInstance::create(accel_params, brake_params); // pass in the two different params + + /* Steering System */ + SteeringParams_s steering_params = { + .min_steering_signal_analog = EEPROMUtilities::read_eeprom_32bit(VCFSystems::MIN_STEERING_SIGNAL_ANALOG_ADDR), + .max_steering_signal_analog = EEPROMUtilities::read_eeprom_32bit(VCFSystems::MAX_STEERING_SIGNAL_ANALOG_ADDR), + .min_steering_signal_digital = EEPROMUtilities::read_eeprom_32bit(VCFSystems::MIN_STEERING_SIGNAL_DIGITAL_ADDR), + .max_steering_signal_digital = EEPROMUtilities::read_eeprom_32bit(VCFSystems::MAX_STEERING_SIGNAL_DIGITAL_ADDR), + .analog_min_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystems::ANALOG_MIN_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok + .analog_max_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystems::ANALOG_MAX_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok + .digital_min_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystems::DIGITAL_MIN_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok + .digital_max_with_margins = EEPROMUtilities::read_eeprom_32bit(VCFSystems::DIGITAL_MAX_WITH_MARGINS_ADDR), // NOLINT this is prev saved value so it is ok + .deg_per_count_analog = VCFSystems::DEG_PER_COUNT_ANALOG, + .deg_per_count_digital = VCFSystems::DEG_PER_COUNT_DIGITAL, + .analog_tolerance = VCFSystems::ANALOG_TOLERANCE, + .digital_tolerance = VCFSystems::DIGITAL_TOLERANCE, + .max_dtheta_threshold = VCFSystems::MAX_DTHETA_THRESHOLD, + .error_between_sensors_tolerance = VCFSystems::ERROR_BETWEEN_SENSORS_TOLERANCE + }; + steering_params.span_signal_analog = steering_params.max_steering_signal_analog - steering_params.min_steering_signal_analog; + steering_params.analog_midpoint = (steering_params.max_steering_signal_analog + steering_params.min_steering_signal_analog) / 2; + steering_params.span_signal_digital = steering_params.max_steering_signal_digital - steering_params.min_steering_signal_digital; + steering_params.digital_midpoint = (steering_params.min_steering_signal_digital + steering_params.max_steering_signal_digital) / 2; + SteeringSystemInstance::create(steering_params); // NOLINT thinks steering params is not initialized + + +} + +HT_TASK::TaskResponse update_pedals_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { + // Observed pedal values (ONLY USED FOR RECALIBRATION) + // WARNING: These are the true min/max observed values, NOT the "value at min travel" and "value at max travel" + // that are defined in the PedalsParam struct. + PedalsSystemInstance::instance().update_observed_pedal_limits(PedalsSystemInstance::instance().get_pedals_sensor_data()); + + if (VCRInterfaceInstance::instance().is_in_pedals_calibration_state()) + { + // PedalsSystemInstance::instance().recalibrate_min_max(VCFData_sInstance::instance().interface_data.pedal_sensor_data); + PedalsSystemInstance::instance().recalibrate_min_max(PedalsSystemInstance::instance().get_pedals_sensor_data()); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::ACCEL_1_MIN_ADDR, PedalsSystemInstance::instance().get_accel_params().min_pedal_1); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::ACCEL_1_MAX_ADDR, PedalsSystemInstance::instance().get_accel_params().max_pedal_1); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::ACCEL_2_MIN_ADDR, PedalsSystemInstance::instance().get_accel_params().min_pedal_2); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::ACCEL_2_MAX_ADDR, PedalsSystemInstance::instance().get_accel_params().max_pedal_2); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::BRAKE_1_MIN_ADDR, PedalsSystemInstance::instance().get_brake_params().min_pedal_1); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::BRAKE_1_MAX_ADDR, PedalsSystemInstance::instance().get_brake_params().max_pedal_1); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::BRAKE_2_MIN_ADDR, PedalsSystemInstance::instance().get_brake_params().min_pedal_2); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::BRAKE_2_MAX_ADDR, PedalsSystemInstance::instance().get_brake_params().max_pedal_2); + } + + return HT_TASK::TaskResponse::YIELD; +} + +HT_TASK::TaskResponse enqueue_pedals_data(const unsigned long &sys_micros, const HT_TASK::TaskInfo& task_info) +{ + PEDALS_SYSTEM_DATA_t pedals_data = {}; + + pedals_data.accel_implausible = PedalsSystemInstance::instance().get_pedals_system_data().accel_is_implausible; + pedals_data.brake_implausible = PedalsSystemInstance::instance().get_pedals_system_data().brake_is_implausible; + pedals_data.brake_accel_implausibility = PedalsSystemInstance::instance().get_pedals_system_data().brake_and_accel_pressed_implausibility_high; + + pedals_data.accel_pedal_active = PedalsSystemInstance::instance().get_pedals_system_data().accel_is_pressed; + pedals_data.brake_pedal_active = PedalsSystemInstance::instance().get_pedals_system_data().brake_is_pressed; + pedals_data.mechanical_brake_active = PedalsSystemInstance::instance().get_pedals_system_data().mech_brake_is_active; + pedals_data.implaus_exceeded_max_duration = PedalsSystemInstance::instance().get_pedals_system_data().implausibility_has_exceeded_max_duration; + + + pedals_data.accel_pedal_ro = HYTECH_accel_pedal_ro_toS(PedalsSystemInstance::instance().get_pedals_system_data().accel_percent); + pedals_data.brake_pedal_ro = HYTECH_brake_pedal_ro_toS(PedalsSystemInstance::instance().get_pedals_system_data().brake_percent); + + CAN_util::enqueue_msg(&pedals_data, &Pack_PEDALS_SYSTEM_DATA_hytech, VCFCANInterfaceInstance::instance().telem_can_tx_buffer); + return HT_TASK::TaskResponse::YIELD; +} + +HT_TASK::TaskResponse update_steering_calibration_task(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) { + const uint32_t analog_raw = SteeringSystemInstance::instance().get_steering_system_data().analog_raw; // NOLINT thinks this is not initialized + const uint32_t digital_raw = SteeringSystemInstance::instance().get_steering_system_data().digital_raw; // NOLINT thinks this is not initialized + + SteeringSystemInstance::instance().update_observed_steering_limits(analog_raw, digital_raw); + + + if (VCRInterfaceInstance::instance().is_in_steering_calibration_state()) { + + SteeringSystemInstance::instance().recalibrate_steering_digital(); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::MIN_STEERING_SIGNAL_ANALOG_ADDR, SteeringSystemInstance::instance().get_steering_params().min_steering_signal_analog); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::MAX_STEERING_SIGNAL_ANALOG_ADDR, SteeringSystemInstance::instance().get_steering_params().max_steering_signal_analog); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::MIN_STEERING_SIGNAL_DIGITAL_ADDR, SteeringSystemInstance::instance().get_steering_params().min_steering_signal_digital); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::MAX_STEERING_SIGNAL_DIGITAL_ADDR, SteeringSystemInstance::instance().get_steering_params().max_steering_signal_digital); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::ANALOG_MIN_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().analog_min_with_margins); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::ANALOG_MAX_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().analog_max_with_margins); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::DIGITAL_MIN_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().digital_min_with_margins); + EEPROMUtilities::write_eeprom_32bit(VCFSystems::DIGITAL_MAX_WITH_MARGINS_ADDR, SteeringSystemInstance::instance().get_steering_params().digital_max_with_margins); + } + + return HT_TASK::TaskResponse::YIELD; +} + +HT_TASK::TaskResponse enqueue_steering_data(const unsigned long& sysMicros, const HT_TASK::TaskInfo& taskInfo) +{ + STEERING_DATA_t msg_out; + SteeringSystemData_s steering_system_data = SteeringSystemInstance::instance().get_steering_system_data(); + + msg_out.steering_analog_oor = steering_system_data.analog_oor_implausibility; + msg_out.steering_both_sensors_fail = steering_system_data.both_sensors_fail; + msg_out.steering_digital_oor = steering_system_data.digital_oor_implausibility; + msg_out.steering_dtheta_exceeded_analog = steering_system_data.dtheta_exceeded_analog; + msg_out.steering_dtheta_exceeded_digital = steering_system_data.dtheta_exceeded_digital; + msg_out.steering_interface_sensor_error = steering_system_data.interface_sensor_error; + msg_out.steering_output_steering_angle_ro = HYTECH_steering_output_steering_angle_ro_toS(steering_system_data.output_steering_angle); + msg_out.steering_sensor_disagreement = steering_system_data.sensor_disagreement_implausibility; + msg_out.steering_analog_raw = steering_system_data.analog_raw; + msg_out.steering_digital_raw = steering_system_data.digital_raw; + + CAN_util::enqueue_msg(&msg_out, &Pack_STEERING_DATA_hytech, VCFCANInterfaceInstance::instance().telem_can_tx_buffer); + return HT_TASK::TaskResponse::YIELD; +} + +HT_TASK::TaskResponse update_neopixels_task(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info) +{ + NeopixelControllerInstance::instance().refresh_neopixels(PedalsSystemInstance::instance().get_pedals_system_data(), CANInterfacesInstance::instance()); + return HT_TASK::TaskResponse::YIELD; +} + diff --git a/src/main.cpp b/src/main.cpp index f23b1de..82f2e35 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,69 +1,43 @@ -#ifdef ARDUINO -#endif - - -/* From shared_firmware_types libdep */ -#include "SharedFirmwareTypes.h" -#include "EthernetAddressDefs.h" - -/* From HT_SCHED libdep */ -#include "ht_sched.hpp" -#include "ht_task.hpp" - -#include -#include - -/* From Arduino Libraries */ -#include "hytech.h" -#include "QNEthernet.h" -#include "FlexCAN_T4.h" - -/* Local includes */ - #include "VCF_Constants.h" -#include "VCF_Tasks.h" -#include "PedalsSystem.h" -#include "SteeringSystem.h" -#include "DashboardInterface.h" -#include "VCFEthernetInterface.h" -#include "WatchdogSystem.h" -#include "EEPROMUtilities.h" +#include "VCF_InterfaceTasks.h" +#include "VCF_SystemTasks.h" -/* CAN Interface stuff */ -#include "VCFCANInterfaceImpl.h" -#include "CANInterface.h" -// #include "VCFEthernetInterface.h" +/* Schedular Dependencies */ #include "ht_sched.hpp" #include "ht_task.hpp" -#include "hytech.h" - -// Globals -qindesign::network::EthernetUDP VCFEthernetInterface::VCF_socket; // TODO: move these out of main -qindesign::network::EthernetUDP VCFEthernetInterface::VCR_socket; - -// Tasks -HT_TASK::Task async_main(HT_TASK::DUMMY_FUNCTION, &async_tasks::handle_async_main, VCFTaskConstants::MAIN_TASK_PRIORITY, VCFTaskConstants::MAIN_TASK_PERIOD); -HT_TASK::Task CAN_send(HT_TASK::DUMMY_FUNCTION, &handle_CAN_send, VCFTaskConstants::CAN_SEND_PRIORITY, VCFTaskConstants::CAN_SEND_PERIOD); -HT_TASK::Task dash_CAN_enqueue(HT_TASK::DUMMY_FUNCTION, &send_dash_data, VCFTaskConstants::DASH_SEND_PRIORITY, VCFTaskConstants::DASH_SEND_PERIOD); -HT_TASK::Task pedals_message_enqueue(HT_TASK::DUMMY_FUNCTION, &enqueue_pedals_data, VCFTaskConstants::PEDALS_PRIORITY, VCFTaskConstants::PEDALS_SEND_PERIOD); -HT_TASK::Task adc0_sample(HT_TASK::DUMMY_FUNCTION, &run_read_adc0_task, VCFTaskConstants::LOADCELL_SAMPLE_PRIORITY, VCFTaskConstants::LOADCELL_SAMPLE_PERIOD); -HT_TASK::Task adc1_sample(HT_TASK::DUMMY_FUNCTION, &run_read_adc1_task, VCFTaskConstants::PEDALS_PRIORITY, VCFTaskConstants::PEDALS_SAMPLE_PERIOD); -HT_TASK::Task buzzer_control_task(&init_buzzer_control_task, &run_buzzer_control_task, VCFTaskConstants::BUZZER_PRIORITY, VCFTaskConstants::BUZZER_WRITE_PERIOD); -HT_TASK::Task read_dash_GPIOs_task(HT_TASK::DUMMY_FUNCTION, &run_dash_GPIOs_task, VCFTaskConstants::DASH_SAMPLE_PRIORITY, VCFTaskConstants::DASH_SAMPLE_PERIOD); -HT_TASK::Task neopixels_task(&init_neopixels_task, &run_update_neopixels_task, VCFTaskConstants::NEOPIXEL_UPDATE_PRIORITY, VCFTaskConstants::NEOPIXEL_UPDATE_PERIOD); -HT_TASK::Task ethernet_send_task(init_handle_send_vcf_ethernet_data, run_handle_send_vcf_ethernet_data, VCFTaskConstants::ETHERNET_SEND_PRIORITY, VCFTaskConstants::ETHERNET_SEND_PERIOD); -HT_TASK::Task steering_message_enqueue(HT_TASK::DUMMY_FUNCTION, &enqueue_steering_data, VCFTaskConstants::STEERING_SEND_PRIORITY, VCFTaskConstants::STEERING_SEND_PERIOD); -HT_TASK::Task front_suspension_message_enqueue(HT_TASK::DUMMY_FUNCTION, &enqueue_front_suspension_data, VCFTaskConstants::LOADCELL_SEND_PRIORITY, VCFTaskConstants::LOADCELL_SEND_PERIOD); - -HT_TASK::Task kick_watchdog_task(&init_kick_watchdog, &run_kick_watchdog, VCFTaskConstants::WATCHDOG_PRIORITY, VCFTaskConstants::WATCHDOG_KICK_PERIOD); -HT_TASK::Task pedals_calibration_task(HT_TASK::DUMMY_FUNCTION, &update_pedals_calibration_task, VCFTaskConstants::PEDALS_RECALIBRATION_PRIORITY, VCFTaskConstants::PEDALS_RECALIBRATION_PERIOD); -HT_TASK::Task steering_calibration_task(HT_TASK::DUMMY_FUNCTION, &update_steering_calibration_task, VCFTaskConstants::STEERING_RECALIBRATION_PRIORITY, VCFTaskConstants::STEERING_RECALIBRATION_PERIOD); - -HT_TASK::Task debug_state_print_task(HT_TASK::DUMMY_FUNCTION, &debug_print, VCFTaskConstants::DEBUG_PRIORITY, VCFTaskConstants::DEBUG_PERIOD); +/* Systems */ +namespace qn = qindesign::network; // setup of qn namespace +qn::EthernetUDP udp; // setup of qn namespace + +/* Scheduler Setup */ +HT_SCHED::Scheduler& scheduler = HT_SCHED::Scheduler::getInstance(); + +/* Task Declarations */ +HT_TASK::Task kick_watchdog_task(HT_TASK::DUMMY_FUNCTION, &run_kick_watchdog, VCFConstants::WATCHDOG_KICK_PERIOD_US, VCFConstants::WATCHDOG_PRIORITY); +HT_TASK::Task async_main(HT_TASK::DUMMY_FUNCTION, &async_tasks::handle_async_main, VCFConstants::ASYNC_MAIN_PERIOD_US, VCFConstants::ASYNC_MAIN_PRIORITY); +HT_TASK::Task adc0_sample(HT_TASK::DUMMY_FUNCTION, &run_read_adc0_task, VCFConstants::PEDALS_SAMPLE_PERIOD_US, VCFConstants::PEDALS_SAMPLE_PRIORITY); +HT_TASK::Task adc1_sample(HT_TASK::DUMMY_FUNCTION, &run_read_adc1_task, VCFConstants::LOADCELL_SAMPLE_PERIOD_US, VCFConstants::LOADCELL_SAMPLE_PRIORITY); +HT_TASK::Task pedals_message_enqueue(HT_TASK::DUMMY_FUNCTION, &enqueue_pedals_data, VCFConstants::PEDALS_SEND_PERIOD_US, VCFConstants::PEDALS_SEND_PRIORITY); +HT_TASK::Task steering_message_enqueue(HT_TASK::DUMMY_FUNCTION, &enqueue_steering_data, VCFConstants::STEERING_SEND_PERIOD_US, VCFConstants::STEERING_SEND_PRIORITY); +HT_TASK::Task front_suspension_message_enqueue(HT_TASK::DUMMY_FUNCTION, &enqueue_front_suspension_data, VCFConstants::LOADCELL_SEND_PERIOD_US, VCFConstants::LOADCELL_SEND_PRIORITY); +HT_TASK::Task CAN_send(HT_TASK::DUMMY_FUNCTION, &handle_CAN_send, VCFConstants::CAN_SEND_PERIOD_US, VCFConstants::CAN_SEND_PRIORITY); +HT_TASK::Task dash_CAN_enqueue(HT_TASK::DUMMY_FUNCTION, &send_dash_data, VCFConstants::DASH_SEND_PERIOD_US, VCFConstants::DASH_SEND_PRIORITY); +HT_TASK::Task read_dash_GPIOs_task(HT_TASK::DUMMY_FUNCTION, &run_dash_GPIOs_task, VCFConstants::DASH_SAMPLE_PERIOD_US, VCFConstants::DASH_SAMPLE_PRIORITY); +HT_TASK::Task ethernet_send_task(init_handle_send_vcf_ethernet_data, run_handle_send_vcf_ethernet_data, VCFConstants::ETHERNET_SEND_PERIOD_US, VCFConstants::ETHERNET_SEND_PRIORITY); +HT_TASK::Task buzzer_control_task(&init_buzzer_control_task, &run_buzzer_control_task, VCFConstants::BUZZER_WRITE_PERIOD_US, VCFConstants::BUZZER_PRIORITY); +HT_TASK::Task neopixels_task(HT_TASK::DUMMY_FUNCTION, &update_neopixels_task, VCFConstants::NEOPIXEL_UPDATE_PERIOD_US, VCFConstants::NEOPIXEL_UPDATE_PRIORITY); +HT_TASK::Task pedals_calibration_task(HT_TASK::DUMMY_FUNCTION, &update_pedals_calibration_task, VCFConstants::PEDALS_RECALIBRATION_PERIOD_US, VCFConstants::PEDALS_RECALIBRATION_PRIORITY); +HT_TASK::Task steering_calibration_task(HT_TASK::DUMMY_FUNCTION, &update_steering_calibration_task, VCFConstants::STEERING_RECALIBRATION_PERIOD_US, VCFConstants::STEERING_RECALIBRATION_PRIORITY); +HT_TASK::Task debug_state_print_task(HT_TASK::DUMMY_FUNCTION, &debug_print, VCFConstants::DEBUG_PERIOD_US, VCFConstants::DEBUG_PRIORITY); + +void setup() +{ + qn::Ethernet.begin(); + + initialize_all_interfaces(); + initialize_all_systems(); -void setup() { - setup_all_interfaces(); //must be first (if we ever have a setup systems) // Setup scheduler HT_SCHED::Scheduler::getInstance().setTimingFunction(micros);