diff --git a/include/VCF_Constants.h b/include/VCF_Constants.h index bc3fed7..a25ab7a 100644 --- a/include/VCF_Constants.h +++ b/include/VCF_Constants.h @@ -12,7 +12,7 @@ namespace VCFInterfaceConstants { // 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 @@ -20,6 +20,9 @@ namespace VCFInterfaceConstants { 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 diff --git a/include/VCF_Globals.h b/include/VCF_Globals.h deleted file mode 100644 index cd64e53..0000000 --- a/include/VCF_Globals.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef VCF_GLOBALS -#define VCF_GLOBALS - -/* C++ library includes */ -#include - -/* From shared-firmware-interfaces */ -#include "MCP_ADC.h" - -/* From shared-firmware-interfaces */ -#include "EthernetAddressDefs.h" -#include "Orbis_BR.h" - -/* From shared-firmware-types */ -#include "PedalsSystem.h" -#include "SharedFirmwareTypes.h" - -/* Local includes */ -#include "VCF_Constants.h" - -/* From Embedded Template Library */ -#include - -/* Ethernet includes */ -#include "QNEthernet.h" - -/* From MCP23017 Library */ -#include "MCP23017.h" - -/* IOExpander setup */ -using IOExpanderInstance = etl::singleton; - -#endif /* VCF_GLOBALS */ \ No newline at end of file diff --git a/include/VCF_Tasks.h b/include/VCF_Tasks.h index 54837ad..6228bad 100644 --- a/include/VCF_Tasks.h +++ b/include/VCF_Tasks.h @@ -95,9 +95,6 @@ HT_TASK::TaskResponse handle_CAN_receive(const unsigned long& sysMicros, const H 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 create_ioexpander(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info); -HT_TASK::TaskResponse read_ioexpander(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info); - 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); diff --git a/lib/interfaces/include/DashboardInterface.h b/lib/interfaces/include/DashboardInterface.h index cd25ff7..0d64616 100644 --- a/lib/interfaces/include/DashboardInterface.h +++ b/lib/interfaces/include/DashboardInterface.h @@ -1,15 +1,18 @@ #ifndef DASHBOARD_INTERFACE_H #define DASHBOARD_INTERFACE_H -#include "hytech_msgs.pb.h" -#include "SharedFirmwareTypes.h" #include "Arduino.h" #include "etl/singleton.h" -#include "hytech.h" +#include "MCP23017.h" #include -#include "SystemTimeInterface.h" #include "FlexCAN_T4.h" +#include "hytech_msgs.pb.h" +#include "SharedFirmwareTypes.h" +#include "hytech.h" + +#include "SystemTimeInterface.h" + // Struct representing dashboard gpios struct DashboardGPIOs_s { @@ -28,7 +31,9 @@ class DashboardInterface public: DashboardInterface() = delete; - DashboardInterface(DashboardGPIOs_s gpios) : _dashboard_gpios(gpios) + 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); @@ -38,6 +43,9 @@ class DashboardInterface pinMode(_dashboard_gpios.BUTTON_2, INPUT_PULLUP); _dash_created_millis = sys_time::hal_millis(); + + i2c_bus.begin(); + _initIOExpander(); } // Reading gpios @@ -60,6 +68,8 @@ class DashboardInterface bool imd_ok = true; void set_dial_state(ControllerMode_e mode); + + void read_ioexpander(); private: @@ -67,10 +77,20 @@ class DashboardInterface DashInputState_s _dashboard_outputs; DashInputState_s _dashboard_stored_state; + MCP23017 _io_expander; + 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) + } +}; using DashboardInterfaceInstance = etl::singleton; diff --git a/lib/interfaces/src/DashboardInterface.cpp b/lib/interfaces/src/DashboardInterface.cpp index 9a9042c..e7ac81a 100644 --- a/lib/interfaces/src/DashboardInterface.cpp +++ b/lib/interfaces/src/DashboardInterface.cpp @@ -1,8 +1,11 @@ -#include "DashboardInterface.h" #include "SharedFirmwareTypes.h" + +#include "DashboardInterface.h" #include "CANInterface.h" #include "VCFCANInterfaceImpl.h" +#include "IOExpanderUtils.h" + /* Button reads */ DashInputState_s DashboardInterface::get_dashboard_outputs() { @@ -39,4 +42,65 @@ DashInputState_s DashboardInterface::get_dashboard_stored_state() void DashboardInterface::sync_dashboard_stored_state() { _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 + new_mode = ControllerMode_e::MODE_0; + } 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 + new_mode = ControllerMode_e::MODE_2; + } 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 + new_mode = ControllerMode_e::MODE_4; + } 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) { + case ControllerMode_e::MODE_0: + { + _io_expander.writePort(MCP23017Port::A, 0b00000010); // NOLINT 0b0000 0010 = 2 + break; + } + case ControllerMode_e::MODE_1: + { + _io_expander.writePort(MCP23017Port::A, 0b01010111); // NOLINT 0b0101 0111 = 87 + break; + } + case ControllerMode_e::MODE_2: + { + _io_expander.writePort(MCP23017Port::A, 0b00011000); // NOLINT 0b0001 1000 = 24 + break; + } + case ControllerMode_e::MODE_3: + { + _io_expander.writePort(MCP23017Port::A, 0b00010100); // NOLINT 0b0001 0100 = 20 + break; + } + case ControllerMode_e::MODE_4: + { + _io_expander.writePort(MCP23017Port::A, 0b01000101); // NOLINT 0b0100 0101 = 69 + break; + } + case ControllerMode_e::MODE_5: + { + _io_expander.writePort(MCP23017Port::A, 0b00100100); // NOLINT 0b0010 0100 = 36 + break; + } + default: + { + _io_expander.writePort(MCP23017Port::A, 0b11110000); // NOLINT 0b1111 0000 = 240 + break; + } + } } \ No newline at end of file diff --git a/lib/interfaces/src/VCFCANInterfaceImpl.cpp b/lib/interfaces/src/VCFCANInterfaceImpl.cpp index 842736a..202ee80 100644 --- a/lib/interfaces/src/VCFCANInterfaceImpl.cpp +++ b/lib/interfaces/src/VCFCANInterfaceImpl.cpp @@ -15,17 +15,6 @@ namespace VCFCANInterfaceImpl { 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)); - - // Serial.println("msg recvd"); - // Serial.print("MB: "); Serial.print(msg.mb); - // Serial.print(" ID: 0x"); Serial.print(msg.id, HEX); - // Serial.print(" EXT: "); Serial.print(msg.flags.extended); - // Serial.print(" LEN: "); Serial.print(msg.len); - // Serial.print(" DATA: "); - // for ( uint8_t i = 0; i < 8; i++ ) { - // Serial.print(msg.buf[i]); Serial.print(" "); - // } - // Serial.print(" TS: "); Serial.println(msg.timestamp); } void vcf_recv_switch(CANInterfaces &interfaces, const CAN_message_t &msg, unsigned long millis, CANInterfaceType_e interface_type) diff --git a/lib/systems/include/IOExpanderUtils.h b/lib/systems/include/IOExpanderUtils.h index ebd5a51..5f8ddb4 100644 --- a/lib/systems/include/IOExpanderUtils.h +++ b/lib/systems/include/IOExpanderUtils.h @@ -7,12 +7,14 @@ namespace IOExpanderUtils { - /* + /** IOExpander's read() only reads. getBit() only get specified bit from previously read dataframe and does not read() - @param port 0=A; 1=B + @param data data from which to get the specified bit + @param port port from which to get the bit from (A=0, B=1) + @param bit bit number of port to get bit from */ - bool getBit(uint16_t data, bool port, int bit); + bool getBit(uint16_t data, bool port, uint8_t bit); } #endif \ No newline at end of file diff --git a/lib/systems/src/IOExpanderUtils.cpp b/lib/systems/src/IOExpanderUtils.cpp index 71d8aeb..a522a45 100644 --- a/lib/systems/src/IOExpanderUtils.cpp +++ b/lib/systems/src/IOExpanderUtils.cpp @@ -1,9 +1,10 @@ #include "IOExpanderUtils.h" -bool IOExpanderUtils::getBit(uint16_t data, bool port, int bit) +/* + * 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) { - if(!port){ //0=A - return (data>>bit)&1; - } - return (data>>(8+bit))&1; // NOLINT (B port is in upper 8 bits, while A port is in lower 8 bits) + 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/src/VCF_Tasks.cpp b/src/VCF_Tasks.cpp index d15616e..ef6c2d5 100644 --- a/src/VCF_Tasks.cpp +++ b/src/VCF_Tasks.cpp @@ -1,6 +1,6 @@ #include "VCF_Tasks.h" #include "SharedFirmwareTypes.h" -#include "VCF_Globals.h" +#include "EthernetAddressDefs.h" #include "VCF_Constants.h" #include #include "ProtobufMsgInterface.h" @@ -36,7 +36,7 @@ HT_TASK::TaskResponse run_read_adc0_task(const unsigned long& sysMicros, const H }); // sample digital steering too TODO: move this to its own task maybe? - // OrbisBRInstance::instance().sample(); + OrbisBRInstance::instance().sample(); return HT_TASK::TaskResponse::YIELD; } @@ -267,92 +267,9 @@ HT_TASK::TaskResponse run_dash_GPIOs_task(const unsigned long& sys_micros, const NeopixelControllerInstance::instance().dim_neopixels(); } - DashboardInterfaceInstance::instance().sync_dashboard_stored_state(); - - return HT_TASK::TaskResponse::YIELD; -} - -HT_TASK::TaskResponse create_ioexpander(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info) -{ - Wire2.begin(); - IOExpanderInstance::create(0x20, Wire2); - IOExpanderInstance::instance().init(); - - IOExpanderInstance::instance().portMode(MCP23017Port::A, 0b00000000); - IOExpanderInstance::instance().portMode(MCP23017Port::B, 0b01111111); - - // IOExpanderInstance::instance().writeRegister(MCP23017Register::GPIO_A, 0x00); //Reset port A - // IOExpanderInstance::instance().writeRegister(MCP23017Register::GPIO_B, 0x00); //Reset port B - - IOExpanderInstance::instance().writeRegister(MCP23017Register::GPPU_B, 0xFF); //Internal pull-ups - - IOExpanderInstance::instance().writeRegister(MCP23017Register::IPOL_B, 0xFF); //Polarity (inverted) + DashboardInterfaceInstance::instance().read_ioexpander(); - return HT_TASK::TaskResponse::YIELD; -} - -HT_TASK::TaskResponse read_ioexpander(const unsigned long& sys_micros, const HT_TASK::TaskInfo& task_info) -{ - uint16_t in = IOExpanderInstance::instance().read(); // NOLINT (linter thinks variable uninitialized) - // for (int i = 0; i < 8; ++i) { - // Serial.printf("%d ", in & 0x01); - // in = in >> 1; - // } - // Serial.println(""); - - //TODO: Double check the harnessing is not wrong this time - if (IOExpanderUtils::getBit(in, 1, 0)) { - DashboardInterfaceInstance::instance().set_dial_state(ControllerMode_e::MODE_0); - } else if (IOExpanderUtils::getBit(in, 1, 1)) { - DashboardInterfaceInstance::instance().set_dial_state(ControllerMode_e::MODE_1); - } else if (IOExpanderUtils::getBit(in, 1, 2)) { - DashboardInterfaceInstance::instance().set_dial_state(ControllerMode_e::MODE_2); - } else if (IOExpanderUtils::getBit(in, 1, 3)) { // NOLINT (pin is magic number) - DashboardInterfaceInstance::instance().set_dial_state(ControllerMode_e::MODE_3); - } else if (IOExpanderUtils::getBit(in, 1, 4)) { // NOLINT (pin is magic number) - DashboardInterfaceInstance::instance().set_dial_state(ControllerMode_e::MODE_4); - } else if (IOExpanderUtils::getBit(in, 1, 5)) { // NOLINT (pin is magic number) - DashboardInterfaceInstance::instance().set_dial_state(ControllerMode_e::MODE_5); - } - - ControllerMode_e state = DashboardInterfaceInstance::instance().get_dashboard_outputs().dial_state; // NOLINT (linter thinks state uninitialized) - switch (state) { - case ControllerMode_e::MODE_0: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b00000010); - break; - } - case ControllerMode_e::MODE_1: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b01010111); - break; - } - case ControllerMode_e::MODE_2: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b00011000); - break; - } - case ControllerMode_e::MODE_3: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b00010100); - break; - } - case ControllerMode_e::MODE_4: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b01000101); - break; - } - case ControllerMode_e::MODE_5: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b00100100); - break; - } - default: - { - IOExpanderInstance::instance().writePort(MCP23017Port::A, 0b11110000); - break; - } - } + DashboardInterfaceInstance::instance().sync_dashboard_stored_state(); return HT_TASK::TaskResponse::YIELD; } @@ -478,6 +395,9 @@ HT_TASK::TaskResponse debug_print(const unsigned long& sysMicros, const HT_TASK: Serial.print(DashboardInterfaceInstance::instance().get_dashboard_outputs().data_btn_is_pressed); Serial.print("\t"); Serial.println(BuzzerController::getInstance().buzzer_is_active(sys_time::hal_millis())); + Serial.println("Digital Steering:"); + Serial.println(OrbisBRInstance::instance().getLastReading().rawValue); + return HT_TASK::TaskResponse::YIELD; } @@ -590,7 +510,7 @@ void setup_all_interfaces() { .DATA_BUTTON = VCFInterfaceConstants::BTN_DATA_READ, .BUTTON_2 = VCFInterfaceConstants::BUTTON_2 }; - DashboardInterfaceInstance::create(dashboard_gpios); //NOLINT + DashboardInterfaceInstance::create(dashboard_gpios, VCFInterfaceConstants::IO_EXPANDER_ADDR, Wire2); //NOLINT ACUInterfaceInstance::create(); VCRInterfaceInstance::create(); diff --git a/src/main.cpp b/src/main.cpp index 2fa31df..3148850 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,7 @@ #include "FlexCAN_T4.h" /* Local includes */ -#include "VCF_Globals.h" + #include "VCF_Constants.h" #include "VCF_Tasks.h" #include "PedalsSystem.h" @@ -50,7 +50,6 @@ HT_TASK::Task adc0_sample(HT_TASK::DUMMY_FUNCTION, &run_read_adc0_task, VCFTaskC 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 read_ioexpander_task(&create_ioexpander, &read_ioexpander, 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); @@ -77,7 +76,6 @@ void setup() { HT_SCHED::Scheduler::getInstance().schedule(adc0_sample); HT_SCHED::Scheduler::getInstance().schedule(adc1_sample); HT_SCHED::Scheduler::getInstance().schedule(read_dash_GPIOs_task); - HT_SCHED::Scheduler::getInstance().schedule(read_ioexpander_task); HT_SCHED::Scheduler::getInstance().schedule(neopixels_task); HT_SCHED::Scheduler::getInstance().schedule(steering_message_enqueue); HT_SCHED::Scheduler::getInstance().schedule(front_suspension_message_enqueue); diff --git a/src/test_ethernet_main.cpp b/src/test_ethernet_main.cpp index 6e38917..46ee94e 100644 --- a/src/test_ethernet_main.cpp +++ b/src/test_ethernet_main.cpp @@ -5,7 +5,7 @@ #include "SharedFirmwareTypes.h" #include "EthernetAddressDefs.h" #include "hytech_msgs.pb.h" -#include "VCF_Globals.h" + #include diff --git a/src/test_pedals_main.cpp b/src/test_pedals_main.cpp index 674f0cd..90b5c15 100644 --- a/src/test_pedals_main.cpp +++ b/src/test_pedals_main.cpp @@ -8,7 +8,7 @@ #include "EEPROMUtilities.h" /* Local includes */ -#include "VCF_Globals.h" + #include "VCF_Constants.h" #include "VCF_Tasks.h" #include "PedalsSystem.h"