diff --git a/.gitignore b/.gitignore index 39e0d67d..3c01a95a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ node_modules/ !/.github/workflows/** /APP/_asn1/icd.html -/APP/_asn1/icd.css \ No newline at end of file +/APP/_asn1/icd.css diff --git a/.idea/OBC.iml b/.idea/OBC.iml new file mode 100644 index 00000000..cf7a77de --- /dev/null +++ b/.idea/OBC.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index fa23ebde..fb81d831 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + @@ -8,18 +11,216 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/APP/BMS/BMS.c b/APP/BMS/BMS.c index 5cd60b0e..fb60659e 100644 --- a/APP/BMS/BMS.c +++ b/APP/BMS/BMS.c @@ -6,63 +6,10 @@ * including ADC setup for current and voltage sensing, GPIO configuration for protection flags, * PWM control for battery heaters, and I2C communications for telemetry and telecommand. * - * ADC channels are assigned to specific pins and memory buffers for multi-channel sweeps. - * GPIO pins are configured for over-voltage, under-voltage, and over-current protection flags. - * PWM outputs control battery heaters, with flexible duty cycle settings. - * Real-Time Clock (RTC) is used for periodic wakeup and routine execution. - * Telemetry and telecommand are handled via a custom protocol (tinyprotocol) over I2C. - * - * * --- BMS.c Code Walkthrough --- - * - * This file implements the Battery Management System (BMS) logic for the MSP430. - * - * Key sections: - * - * 1. Hardware Definitions: - * - ADC pin assignments: Each *_PIN macro maps a physical pin to an ADC input channel. - * - ADC memory buffers: Each *_MEM macro maps an ADC channel to a memory buffer. These buffers store the results of ADC conversions. - * - GPIO pin assignments: Unique macros for each protection flag (over-voltage, under-voltage, over-current) mapped to specific pins. - * - PWM heater pins: Defines which pins are used for heater PWM outputs. - * - External ADC and I2C addresses. - * - * 2. Static Data Buffers: - * - Buffers for system status, current, voltage, flags, and external ADC readings. - * - These are used for telemetry responses and protocol communication. - * - * 3. Initialization Functions: - * - initADCs(): Sets up all ADC channels and memory buffers for multi-channel sweeps. - * - initGPIO(): Configures all GPIO pins for flags, I2C, and PWM outputs. - * - initClockTo16MHz(): Sets the MSP430 clock to 16MHz for fast operation. - * - initRTC(): Initializes the Real-Time Clock for periodic interrupts. - * - initBSP(): Calls all hardware initialization routines. - * - * 4. Communication Setup: - * - InitAppComm(): Initializes I2C and the custom tinyprotocol for telemetry/telecommand. - * - Registers all telemetry channels and telecommands. - * - * 5. Main Periodic Routine: - * - RoutineCycle_Process(): Called by RTC interrupt. Sweeps ADCs, reads GPIO flags, collects external ADC data, and updates buffers. - * - * 6. Interrupt Service Routine: - * - RTC_ISR(): Handles RTC interrupts, triggers periodic routine, and blinks LED for events. - * - * 7. Telemetry and Telecommand Handlers: - * - SendTelemetryResponse(): Responds to telemetry requests. - * - ProcessTelemetryRequest(): Dispatches telemetry responses. - * - SendPWM(): Sets heater PWM duty cycles. - * - ProcessTelecommand(): Handles incoming telecommands (e.g., heater control). - * - * --- Notes for Reviewers --- - * - ADC memory buffers are crucial for storing conversion results; each sensor channel has a dedicated buffer. - * - GPIO flag assignments should be unique and clearly mapped to physical pins. - * - All hardware initialization is grouped for clarity and maintainability. - * - Telemetry/telecommand protocol is modular and easily extendable. - * - RoutineCycle_Process is the main data acquisition and update loop, triggered by RTC. - * - Comments throughout the file explain hardware mapping and logic flow. * Author: Brendan Kelly */ -#include +#include #include "BMS.h" #include "ADC_Read.h" @@ -72,6 +19,16 @@ #include "PWM.h" #include "swi2c.h" #include "ads7138irter.h" +#include "tinyprotocol.h" +#include "i2c.h" +#include "lfp.h" +#include "lfp/stream.h" +#include "asn1/bms.h" +#include "ASN1SCC/asn1_lfp.h" +#include "asn1/_systems.h" +#include "asn1/bms.h" +#include "i2c.h" + #if defined (__MSP430FR5989__) #include "rtc_c.h" #elif defined (__MSP430FR5969__) @@ -150,50 +107,161 @@ #define HEATER4_CCR TIMER_B_CAPTURECOMPARE_REGISTER_6 #endif -#define SLAVE_ADDR 0x08 +#define BMS_SLAVE_ADDR 0x09 -// Static data buffers to be sent back to CDH via tinyprotocol -static const SystemStatusResp_t sSystemStatus = { - .runtime = 0x12, - .fw_version = 0xA, +// Static serialized structs to be populated periodically from sensor data etc... +static const BMSSystemStatusResponse s_systemstatus = { + .uptime = 0xDEADBEEF, + .version = 12 }; +static volatile BMSPowerStatusResponse s_powerstatus; +static volatile BMSTemperatureStatusResponse s_temperature_status; +static BMSSetHeaterDutyResponse s_heaterduty_response; // this -static CurrentResp_t sCurrentDraw = { - .isense1 = 0, - .isense2 = 0, -}; +// Static asn1 encoded data buffers to be sent back to CDH on request +static volatile uint8_t s_systemstatus_tx_buf[ASN1_LFP_SEND_BUF_SIZE(BMSSystemStatusResponse)]; +static volatile uint16_t s_powerstatus_size = 0; +static volatile uint8_t s_powerstatus_tx_buf[ASN1_LFP_SEND_BUF_SIZE(BMSPowerStatusResponse)]; +static volatile uint16_t s_temperature_status_size = 0; +static volatile uint8_t s_temperature_status_tx_buf[ASN1_LFP_SEND_BUF_SIZE(BMSTemperatureStatusResponse)]; +static uint16_t s_heaterduty_response_size = 0; +static uint8_t s_heaterduty_response_tx_buf[ASN1_LFP_SEND_BUF_SIZE(BMSSetHeaterDutyResponse)]; -static CurrentResp_t sCurrentCharge = { - .isense1 = 0, - .isense2 = 0, -}; -static VoltageResp_t sVoltageBattery1 = { - .vcell_a = 0, - .vcell_b = 0, -}; +// Global SWI2C config "descriptor" +static SWI2C_Descriptor sADS7138_SWI2C_Descriptor; -static VoltageResp_t sVoltageBattery2 = { - .vcell_a = 0, - .vcell_b = 0, -}; +// LFP +typedef struct { + const lfp_header_t* p_header; + const uint8_t* p_body; + uint16_t body_length; + lfp_code_t reason; +} user_ctx_t; -static CombinedVoltageResp_t sCombinedBatteryVoltage = { - .vbatt1 = 0, - .vbatt2 = 0, -}; +static lfp_stream_ctx_t s_lfp_ctx; -static Flag_t sFlags = { - .val = 0x00, -}; +// FIXME: arbitrary temporary size +#define RX_BODY_BUFFER_SIZE 16 -// Need 2 buffers since max buffer size for tinyprotocol is 11 and we have 8 16 bit -static uint8_t sExtADCBuffer03[8] = {}; -static uint8_t sExtADCBuffer47[8] = {}; +static uint8_t s_rx_body_buffer[RX_BODY_BUFFER_SIZE]; +static user_ctx_t s_user_ctx; +static void collect_power_status(); +static void collect_power_status_mock(); -// Global SWI2C config "descriptor" -static SWI2C_Descriptor sADS7138_SWI2C_Descriptor; +static bool on_header(const lfp_header_t* p_header, void* p_ctx) +{ + if (i2c_slave_current_state() == I2C_SLAVE_STATE_RESPONSE) { + i2c_transition(I2C_SLAVE_STATE_REQUEST); + } + return true; +} + +static void on_error(int error_code, const struct asn1_lfp_decode_data_t * p_data) +{ + +} + +// NOTE!! If we don't copy buffers into a seperate i2c transfer buffer, idk if it's possible for buffers to be updated mid transfer or not +// I don't think so, but wouldn't hurt testing this just in casee +// NOTE2: these callbacks are technically doing work in the isr, but on_msg only ever gets called on the last byte of the write +// TODO: Make put them in helper function +static void bms_system_status_req_cb(const BMSSystemStatusRequest * p_payload, const asn1_lfp_decode_data_t * p_data) { + (void)p_payload; + i2c_transition(I2C_SLAVE_STATE_PROCESSING); + // GIE -- this is technically in the i2c isr, we don't want getting stuck here to stall BMS + __enable_interrupt(); + + uint16_t size = ASN1_LFP_SERIALIZE( + p_data->p_header->initiator, bmsSystemId, + BMSSystemStatusResponse, + s_systemstatus_tx_buf, sizeof(s_systemstatus_tx_buf), + s_systemstatus + ); + __disable_interrupt(); + i2c_reassign_txbuf(s_systemstatus_tx_buf, size); +} + +static void bms_power_status_req_cb(const BMSPowerStatusRequest * p_payload, const asn1_lfp_decode_data_t * p_data) { + (void)p_payload; + i2c_transition(I2C_SLAVE_STATE_PROCESSING); + __enable_interrupt(); + uint16_t size = ASN1_LFP_SERIALIZE( + p_data->p_header->initiator, bmsSystemId, + BMSPowerStatusResponse, + s_powerstatus_tx_buf, sizeof(s_powerstatus_tx_buf), + s_powerstatus + ); + __disable_interrupt(); + i2c_reassign_txbuf(s_powerstatus_tx_buf, size); +} + +static void bms_temperature_status_req_cb(const BMSTemperatureStatusRequest * p_payload, const asn1_lfp_decode_data_t * p_data) { + (void)p_payload; + i2c_transition(I2C_SLAVE_STATE_PROCESSING); + __enable_interrupt(); + uint16_t size = ASN1_LFP_SERIALIZE( + p_data->p_header->initiator, bmsSystemId, + BMSTemperatureStatusResponse, + s_temperature_status_tx_buf, + sizeof(s_temperature_status_tx_buf), + s_temperature_status + ); + __disable_interrupt(); + i2c_reassign_txbuf(s_temperature_status_tx_buf, size); +} + +static void bms_set_heater_duty_cb(const BMSSetHeaterDutyRequest * p_payload, const asn1_lfp_decode_data_t * p_data) { + // It's 100-1 and not 99 because that's what they do in the TI examples for PWM, IDK why the do that but best to stick to a standard if it exists + i2c_transition(I2C_SLAVE_STATE_PROCESSING); + if (p_payload->exist.heater1) { + PWM_Generate(100-1, p_payload->heater1, HEATER1_CCR); + } + if (p_payload->exist.heater2) { + PWM_Generate(100-1, p_payload->heater2, HEATER2_CCR); + } + if (p_payload->exist.heater3) { + PWM_Generate(100-1, p_payload->heater3, HEATER3_CCR); + } + if (p_payload->exist.heater4) { + PWM_Generate(100-1, p_payload->heater4, HEATER4_CCR); + } + + // Send response (Empty body basically an ACK) + i2c_reassign_txbuf(s_temperature_status_tx_buf, s_temperature_status_size); +} + +static void on_msg(const lfp_header_t * p_header, const uint8_t * p_body, uint16_t body_length, void * p_ctx) +{ + // if we get a valid message while responding to something else, forget what we were doing before respond to the new request + if (i2c_slave_current_state() == I2C_SLAVE_STATE_RESPONSE) { + i2c_transition(I2C_SLAVE_STATE_REQUEST); + } + const asn1_lfp_decode_data_t data = { + .p_header = p_header, + .p_body = p_body, + .p_ctx = p_ctx, + .body_length = body_length, + .p_on_error_cb = on_error, + }; + + if (ASN1_LFP_HANDLE_MSG(data, bmsSystemId, BMSSystemStatusRequest, bms_system_status_req_cb)) { + return; + } + + if (ASN1_LFP_HANDLE_MSG(data, bmsSystemId, BMSPowerStatusRequest, bms_power_status_req_cb)) { + return; + } + + if (ASN1_LFP_HANDLE_MSG(data, bmsSystemId, BMSTemperatureStatusRequest, bms_temperature_status_req_cb)) { + return; + } + + if (ASN1_LFP_HANDLE_MSG(data, bmsSystemId, BMSSetHeaterDutyRequest, bms_set_heater_duty_cb)) { + return; + } +} static volatile bool sISRTriggered = false; @@ -308,86 +376,30 @@ static void initGPIO() PWM_PinSelect(HEATER_PWM_PORT, HEATER4_PWM_PIN); } - - // Initialize the Real-Time Clock (RTC) for periodic interrupts // Uses RTC_C or RTC_B driverlib depending on device -#if defined (__MSP430FR5989__) static void initRTC() { - Calendar currentTime; - - //Setup for Calendar - currentTime.Seconds = 0x00; - currentTime.Minutes = 0x00; - currentTime.Hours = 0x00; - currentTime.DayOfWeek = 0x00; - currentTime.DayOfMonth = 0x00; - currentTime.Month = 0x00; - currentTime.Year = 0x7E9; // 2025 - - //Initialize Calendar Mode of RTC - RTC_C_initCalendar(RTC_C_BASE, ¤tTime, RTC_C_FORMAT_BCD); - - //Setup Calendar Alarm for 30 minutes after start. - RTC_C_configureCalendarAlarmParam param = {0}; - param.minutesAlarm = 0x2; // Currently set to 2 minute for testing - TODO change to 24 hours - param.hoursAlarm = 0x0; - param.dayOfWeekAlarm = 0x0; - param.dayOfMonthAlarm = 0x0; - RTC_C_configureCalendarAlarm(RTC_C_BASE, ¶m); - +#if defined (__MSP430FR5989__) RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_CLOCK_READ_READY_INTERRUPT + RTC_C_TIME_EVENT_INTERRUPT + RTC_C_CLOCK_ALARM_INTERRUPT ); - //Enable interrupt for RTC Ready Status, which asserts when the RTC - //Calendar registers are ready to read. - //Also, enable interrupts for the Calendar alarm and Calendar event. RTC_C_enableInterrupt(RTC_C_BASE, RTC_C_CLOCK_READ_READY_INTERRUPT + RTC_C_TIME_EVENT_INTERRUPT + RTC_C_CLOCK_ALARM_INTERRUPT ); - //Start RTC Clock + //Start RTC RTC_C_startClock(RTC_C_BASE); -} - #elif defined (__MSP430FR5969__) -static void initRTC() -{ - Calendar currentTime; - - //Setup for Calendar - currentTime.Seconds = 0x00; - currentTime.Minutes = 0x00; - currentTime.Hours = 0x00; - currentTime.DayOfWeek = 0x00; - currentTime.DayOfMonth = 0x00; - currentTime.Month = 0x00; - currentTime.Year = 0x7E9; // 2025 - - //Initialize Calendar Mode of RTC - RTC_B_initCalendar(RTC_B_BASE, ¤tTime, RTC_B_FORMAT_BCD); - - //Setup Calendar Alarm for 30 minutes after start. - RTC_B_configureCalendarAlarmParam param = {0}; - param.minutesAlarm = 0x2; // Currently set to 2 minute for testing - TODO change to 24 hours - param.hoursAlarm = 0x0; - param.dayOfWeekAlarm = 0x0; - param.dayOfMonthAlarm = 0x0; - RTC_B_configureCalendarAlarm(RTC_B_BASE, ¶m); - RTC_B_clearInterrupt(RTC_B_BASE, RTC_B_CLOCK_READ_READY_INTERRUPT + RTC_B_TIME_EVENT_INTERRUPT + RTC_B_CLOCK_ALARM_INTERRUPT ); - //Enable interrupt for RTC Ready Status, which asserts when the RTC - //Calendar registers are ready to read. - //Also, enable interrupts for the Calendar alarm and Calendar event. RTC_B_enableInterrupt(RTC_B_BASE, RTC_B_CLOCK_READ_READY_INTERRUPT + RTC_B_TIME_EVENT_INTERRUPT + @@ -396,74 +408,12 @@ static void initRTC() //Start RTC Clock RTC_B_startClock(RTC_B_BASE); -} #endif - - -// Private helper functions for telemetry and telecommand processing -static void I2C_Proc_RX_Data(uint8_t data); - -static uint16_t SendTelemetryResponse(uint8_t request) -{ - uint8_t bytes[TINYPROTOCOL_MAX_PACKET_SIZE]; - uint8_t count = 0; - uint8_t* pbyte = bytes; - - while(TINYPROTOCOL_TelemetryBytesLeft() > 0) { - int16_t result = TINYPROTOCOL_ReadNextTelemetryByte(pbyte); - volatile uint8_t byte = *pbyte; - if (result == ETINYPROTOCOL_SUCCESS) { - pbyte++; - count++; - } else { - return result; - } - } - - transmitI2C(bytes, count); - - return ETINYPROTOCOL_SUCCESS; -} - -static int16_t ProcessTelemetryRequest(uint8_t request) -{ - return SendTelemetryResponse(request); -} - -// NOTE: Likely just going to be turning heaters all the way on and all the way off, but for now the API is flexible -// NOTE: Once PWM generate is set, it goes on forever. Those pins are set to generate that PWM signal until we tell them not to -static void SendPWM(const uint8_t* buffer, uint8_t size) -{ - // It's 100-1 and not 99 because that's what they do in the TI examples for PWM, IDK why the do that but best to stick to a standard if it exists - PWM_Generate(100-1, buffer[0], HEATER1_CCR); - PWM_Generate(100-1, buffer[1], HEATER2_CCR); - PWM_Generate(100-1, buffer[2], HEATER3_CCR); - PWM_Generate(100-1, buffer[3], HEATER4_CCR); -} - -static int16_t ProcessTelecommand(uint8_t command, const uint8_t* buffer, uint8_t size) -{ - switch (command) { - case BMS_HEATERS_CONTROLLER_ID: - SendPWM(buffer, size); - break; - - default: - return ETINYPROTOCOL_INVALID_CMD_ID; - } - return ETINYPROTOCOL_SUCCESS; } -const struct TINYPROTOCOL_Config protocolConfig = -{ - .TINYPROTOCOL_ProcessTelecommand = ProcessTelecommand, - .TINYPROTOCOL_ProcessTelemetryRequest = ProcessTelemetryRequest, - .TINYPROTOCOL_WriteBuffer = transmitI2C -}; - -static void I2C_Proc_RX_Data(uint8_t data) +static void i2c_rx_cb(uint8_t data) { - TINYPROTOCOL_ParseByte(&protocolConfig, data); + lfp_stream_update(&s_lfp_ctx, data); } // Hardware initialization. Initializes MSP430 specific device modules for I2C, ADC, GPIO, Clock, and RTC @@ -479,11 +429,11 @@ static void initHardware() // NOTE: Must be called after initBSP since it uses I2C pins static void InitAppComm() { - sI2cConfigCb_t i2cConfig = { - .Rx_Proc_Data = I2C_Proc_RX_Data, - .slave_addr = SLAVE_ADDR, + i2c_ctx_t i2c_ctx = { + .i2c_rx_cb = i2c_rx_cb, + .slave_addr = BMS_SLAVE_ADDR, }; - initI2C(&i2cConfig); + i2c_init(&i2c_ctx); // SW I2C sADS7138_SWI2C_Descriptor.sda_port_out = &P4OUT; @@ -506,18 +456,13 @@ static void InitAppComm() ADS7138IRTER_Initialize(&sADS7138_SWI2C_Descriptor); - TINYPROTOCOL_Initialize(); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_SYSTEM_STATUS_ID, sSystemStatus.buffer , sizeof(sSystemStatus.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_FLAG_ID, sFlags.buffer, sizeof(sFlags.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_CURRENT_DRAW_ID, sCurrentDraw.buffer, sizeof(sCurrentDraw.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_CURRENT_CHARGE_ID, sCurrentCharge.buffer, sizeof(sCurrentCharge.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_VOLTAGE_BATTERY1_ID, sVoltageBattery1.buffer, sizeof(sVoltageBattery1.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_VOLTAGE_BATTERY2_ID, sVoltageBattery2.buffer, sizeof(sVoltageBattery2.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_VOLTAGE_COMBINED_ID, sCombinedBatteryVoltage.buffer, sizeof(sCombinedBatteryVoltage.buffer)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_THERMISTOR03_DATA_ID, sExtADCBuffer03, sizeof(sExtADCBuffer03)); - TINYPROTOCOL_RegisterTelemetryChannel(BMS_THERMISTOR47_DATA_ID, sExtADCBuffer47, sizeof(sExtADCBuffer47)); - - TINYPROTOCOL_RegisterTelecommand(BMS_HEATERS_CONTROLLER_ID, 4); + // We only every have to do this once since it's just an empty body used as an ACK. + s_heaterduty_response_size = ASN1_LFP_SERIALIZE(bmsSystemId, cdhSystemId, BMSSetHeaterDutyResponse, s_heaterduty_response_tx_buf, sizeof(s_heaterduty_response_tx_buf), s_heaterduty_response); + if (!s_heaterduty_response_size) { + __no_operation(); + } + + lfp_stream_init(&s_lfp_ctx, s_rx_body_buffer, sizeof(s_rx_body_buffer), on_header, on_msg, on_error, &s_user_ctx); } // Public BMS initialization. Calls initBSP and InitAppComm @@ -530,89 +475,102 @@ void BMS_init() /* * RTC ISR and main program logic. - * This is where data is collected and stored into static buffers as per tinyprotocol - * NOTE: inlining functions is entirely up to the compiler, therefore logic for different buffers (i.e. ADC, GPIO, etc) is kept in one function - * due to paranoia that the compiler might not inline it. This is subject to refactor. It is possible to force inline or use macros. */ -extern void BMS_collectData() + +static void collect_power_status() { - /* MSP430xxxx ON DEVICE ADCs */ - // Collect ADC data and put it into buffers + // Collect voltage and current ADC values // Must do this this way (all at once) if using SEQOFCHANNELS mode - /* trigger the ten‑channel sweep */ + // trigger the ten‑channel sweep ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0, - ADC12_B_SEQOFCHANNELS); // ENC+SC, walk MEM0→MEM9 - - while (ADC12_B_isBusy(ADC12_B_BASE)); - - /* pull results out */ - sCurrentDraw.isense1 = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_VUR_1_CP_MEM); - sCurrentDraw.isense2 = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_VUR_2_CP_MEM); - sCurrentCharge.isense1 = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_CHR_1_CP_MEM); - sCurrentCharge.isense2 = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_CHR_2_CP_MEM); - sVoltageBattery1.vcell_a = ADC12_B_getResults(ADC12_B_BASE, V_CELL_1A_CP_MEM); - sVoltageBattery1.vcell_b = ADC12_B_getResults(ADC12_B_BASE, V_CELL_1B_CP_MEM); - sVoltageBattery2.vcell_a = ADC12_B_getResults(ADC12_B_BASE, V_CELL_2A_CP_MEM); - sVoltageBattery2.vcell_b = ADC12_B_getResults(ADC12_B_BASE, V_CELL_2B_CP_MEM); - sCombinedBatteryVoltage.vbatt1 = ADC12_B_getResults(ADC12_B_BASE, V_BATTPACK_1_CP_MEM); - sCombinedBatteryVoltage.vbatt2 = ADC12_B_getResults(ADC12_B_BASE, V_BATTPACK_2_CP_MEM); - - /* FLAGS */ - // Read GPIO flags and put them into buffer - sFlags.val = 0x00; - volatile uint8_t ovp1Aval = GPIO_getInputPinValue(GPIO_PORT_P5, OVP_FLAG_1A_PIN); - sFlags.val |= ovp1Aval << 9; - - volatile uint8_t uvp1Bval = GPIO_getInputPinValue(GPIO_PORT_P5, UVP_FLAG_1B_PIN); - sFlags.val |= uvp1Bval << 8; - - volatile uint8_t uvp1Aval = GPIO_getInputPinValue(GPIO_PORT_P5, UVP_FLAG_1A_PIN); - sFlags.val |= uvp1Aval << 7; - - volatile uint8_t ovp1Bval = GPIO_getInputPinValue(GPIO_PORT_P5, OVP_FLAG_1B_PIN); - sFlags.val |= ovp1Bval << 6; - - volatile uint8_t ocp1val = GPIO_getInputPinValue(GPIO_PORT_P3, OCP_FLAG_1_PIN); - sFlags.val |= ocp1val << 5; - - volatile uint8_t ovp2Aval = GPIO_getInputPinValue(GPIO_PORT_P3, OVP_FLAG_2A_PIN); - sFlags.val |= ovp2Aval << 4; - - volatile uint8_t ovp2Bval = GPIO_getInputPinValue(GPIO_PORT_P3, OVP_FLAG_2B_PIN); - sFlags.val |= ovp2Bval << 3; - - volatile uint8_t uvp2Aval = GPIO_getInputPinValue(GPIO_PORT_P3, UVP_FLAG_2A_PIN); - sFlags.val |= uvp2Aval << 2; - - volatile uint8_t uvp2Bval = GPIO_getInputPinValue(GPIO_PORT_P3, UVP_FLAG_2B_PIN); - sFlags.val |= uvp2Bval << 1; - - volatile uint8_t ocp2val = GPIO_getInputPinValue(GPIO_PORT_P3, OCP_FLAG_2_PIN); - sFlags.val |= ocp2val; - - /* TI ADS7138IRTER EXTERNAL ADC DATA (THERMISTORS)*/ - // Get External ADC data - uint8_t i; - uint16_t val = 0; - uint8_t num_half_channels = 4; - uint8_t buffer_idx = 0; - for (i = 0 ; i < num_half_channels; i++) { - ADS7138IRTER_SingleRegisterWrite(&sADS7138_SWI2C_Descriptor, ADS7138_CHANNEL_SEL_REGISTER, i); - val = ADS7138IRTER_Read(&sADS7138_SWI2C_Descriptor); - sExtADCBuffer03[buffer_idx] = val >> 8; - sExtADCBuffer03[buffer_idx + 1u] = val & 0xff; - buffer_idx += 2; + ADC12_B_SEQOFCHANNELS); // ENC+SC, walk MEM0->MEM9 + + // Profile this irl... can probably get away with having this in callback so we can get most accurate data immediately on asking + // I'm not sure how possible it is for this to spin forever if at all. + uint16_t counter = 0; + while (ADC12_B_isBusy(ADC12_B_BASE)) { + counter++; } + + // Current + s_powerstatus.batteryPack1.currentDraw = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_VUR_1_CP_MEM); + s_powerstatus.batteryPack2.currentDraw = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_VUR_2_CP_MEM); + s_powerstatus.batteryPack1.currentCharge = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_CHR_1_CP_MEM); + s_powerstatus.batteryPack2.currentCharge = ADC12_B_getResults(ADC12_B_BASE, I_SENSE_CHR_2_CP_MEM); + + // Voltage per cell + s_powerstatus.batteryPack1.cellA.voltage = ADC12_B_getResults(ADC12_B_BASE, V_CELL_1A_CP_MEM); + s_powerstatus.batteryPack1.cellB.voltage = ADC12_B_getResults(ADC12_B_BASE, V_CELL_1B_CP_MEM); + s_powerstatus.batteryPack2.cellA.voltage = ADC12_B_getResults(ADC12_B_BASE, V_CELL_2A_CP_MEM); + s_powerstatus.batteryPack2.cellB.voltage = ADC12_B_getResults(ADC12_B_BASE, V_CELL_2B_CP_MEM); + + // Combined voltage per battery + s_powerstatus.batteryPack1.voltage = ADC12_B_getResults(ADC12_B_BASE, V_BATTPACK_1_CP_MEM); + s_powerstatus.batteryPack2.voltage = ADC12_B_getResults(ADC12_B_BASE, V_BATTPACK_2_CP_MEM); + + // Collect voltage and current flags + s_powerstatus.batteryPack1.cellA.overvoltage = GPIO_getInputPinValue(GPIO_PORT_P5, OVP_FLAG_1A_PIN); + s_powerstatus.batteryPack1.cellA.undervoltage = GPIO_getInputPinValue(GPIO_PORT_P5, UVP_FLAG_1A_PIN); + s_powerstatus.batteryPack1.cellB.overvoltage = GPIO_getInputPinValue(GPIO_PORT_P5, OVP_FLAG_1B_PIN); + s_powerstatus.batteryPack1.cellB.undervoltage = GPIO_getInputPinValue(GPIO_PORT_P5, UVP_FLAG_1B_PIN); + s_powerstatus.batteryPack1.overcurrent = GPIO_getInputPinValue(GPIO_PORT_P3, OCP_FLAG_1_PIN); + + s_powerstatus.batteryPack2.cellA.overvoltage = GPIO_getInputPinValue(GPIO_PORT_P3, OVP_FLAG_2A_PIN); + s_powerstatus.batteryPack2.cellA.undervoltage = GPIO_getInputPinValue(GPIO_PORT_P3, UVP_FLAG_2A_PIN); + s_powerstatus.batteryPack2.cellB.overvoltage = GPIO_getInputPinValue(GPIO_PORT_P3, OVP_FLAG_2B_PIN); + s_powerstatus.batteryPack2.cellB.undervoltage = GPIO_getInputPinValue(GPIO_PORT_P3, UVP_FLAG_2B_PIN); + s_powerstatus.batteryPack2.overcurrent = GPIO_getInputPinValue(GPIO_PORT_P3, OCP_FLAG_2_PIN); +} - buffer_idx = 0; - for (i = 0 ; i < num_half_channels; i++) { - ADS7138IRTER_SingleRegisterWrite(&sADS7138_SWI2C_Descriptor, ADS7138_CHANNEL_SEL_REGISTER, i + num_half_channels); - val = ADS7138IRTER_Read(&sADS7138_SWI2C_Descriptor); - sExtADCBuffer47[buffer_idx] = val >> 8; - sExtADCBuffer47[buffer_idx + 1u] = val & 0xff; - buffer_idx += 2; +// Mock version using easy-to-identify test values +static void collect_power_status_mock() +{ + s_powerstatus.batteryPack1.currentDraw = 0x11ee; + s_powerstatus.batteryPack1.currentCharge = 0x12ee; + + s_powerstatus.batteryPack1.cellA.voltage = 0x1Aee; + s_powerstatus.batteryPack1.cellB.voltage = 0x1Bee; + + s_powerstatus.batteryPack1.voltage = 0x1111; + + s_powerstatus.batteryPack1.cellA.overvoltage = 0; + s_powerstatus.batteryPack1.cellA.undervoltage = 1; + s_powerstatus.batteryPack1.cellB.overvoltage = 0; + s_powerstatus.batteryPack1.cellB.undervoltage = 0; + s_powerstatus.batteryPack1.overcurrent = 1; + + s_powerstatus.batteryPack2.currentDraw = 0x21ee; + s_powerstatus.batteryPack2.currentCharge = 0x22ee; + + s_powerstatus.batteryPack2.cellA.voltage = 0x2Aee; + s_powerstatus.batteryPack2.cellB.voltage = 0x2Bee; + s_powerstatus.batteryPack2.voltage = 0x2222; + + s_powerstatus.batteryPack2.cellA.overvoltage = 1; + s_powerstatus.batteryPack2.cellA.undervoltage = 0; + s_powerstatus.batteryPack2.cellB.overvoltage = 1; + s_powerstatus.batteryPack2.cellB.undervoltage = 0; + s_powerstatus.batteryPack2.overcurrent = 0; +} + +#define ADC_NUM_CHANNELS 8 + +void BMS_collectData() +{ +#ifdef MOCK_POWER + collect_power_status_mock(); +#else + collect_power_status(); +#endif + + // TI ADS7138IRTER EXTERNAL ADC DATA (THERMISTORS) + // NOTE: Profile this.. might be able to ask for this directly in callback + for (uint8_t i = 0 ; i < ADC_NUM_CHANNELS; i++) { + ADS7138IRTER_SingleRegisterWrite(&sADS7138_SWI2C_Descriptor, ADS7138_CHANNEL_SEL_REGISTER, i); + s_temperature_status.thermistors.arr[i] = ADS7138IRTER_Read(&sADS7138_SWI2C_Descriptor); } + sISRTriggered = false; } @@ -637,7 +595,7 @@ void RTC_ISR (void) case RTCIV_RTCRDYIFG: sISRTriggered = true; break; - case RTCIV_RTCTEVIFG: P1OUT |= BIT0; break; // I think this is blinking an LED or some shit + case RTCIV_RTCTEVIFG: break; case RTCIV_RTCAIFG: /* alarm */ break; case RTCIV_RT0PSIFG: /* prescale 0 */ break; case RTCIV_RT1PSIFG: /* prescale 1 */ break; diff --git a/APP/BMS/BMS.h b/APP/BMS/BMS.h index 84483e89..4defaccb 100644 --- a/APP/BMS/BMS.h +++ b/APP/BMS/BMS.h @@ -2,171 +2,38 @@ * @file * @brief Battery Management System (BMS) application interface for MSP430. * - * @details - * This module provides hardware abstraction and telemetry/telecommand definitions for - * battery monitoring and control. It includes ADC channel assignments, protection flag - * mapping, and protocol response structures for system status, current, voltage, and - * heater control. Initialization routines set up all hardware and register protocol - * channels for communication with the central data handler. - * * @author Brendan Kelly */ #ifndef BMS_H #define BMS_H -#include #include -#include "tinyprotocol.h" -#include "i2c.h" - - -/** - * @def SYSTEM_STATUS_RESP_LEN - * @brief Number of bytes in system status telemetry response. - */ -#define SYSTEM_STATUS_RESP_LEN 5 - -/** - * @def CURRENT_VOLTAGE_RESP_LEN - * @brief Number of bytes in current or voltage telemetry response. - */ -#define CURRENT_VOLTAGE_RESP_LEN 4 - -/** - * @def ADC_NUM_CHANNELS - * @brief Number of ADC channels used for battery monitoring. - */ -#define ADC_NUM_CHANNELS 8 - -/** - * @enum BMS_TelemetryRequestCmdId - * @brief Command IDs for BMS telemetry requests. - * @note If you don't manually assign these values, bad things happen that I don't understand. - */ -enum BMS_TelemetryRequestCmdId { - BMS_SYSTEM_STATUS_ID = 1, /**< System status telemetry */ - BMS_HEALTH_CHECK_ID = 2, /**< Health check telemetry */ - BMS_FLAG_ID = 3, /**< Protection flags telemetry */ - BMS_CURRENT_DRAW_ID = 4, /**< Discharge current telemetry */ - BMS_CURRENT_CHARGE_ID = 5, /**< Charge current telemetry */ - BMS_VOLTAGE_BATTERY1_ID = 6, /**< Battery 1 voltage telemetry */ - BMS_VOLTAGE_BATTERY2_ID = 7, /**< Battery 2 voltage telemetry */ - BMS_VOLTAGE_COMBINED_ID = 8, /**< Combined battery voltage telemetry */ - BMS_HEATERS_CONTROLLER_ID = 9, /**< Heater controller telecommand */ - BMS_THERMISTOR03_DATA_ID = 10, /**< Thermistor 0-3 external ADC telemetry */ - BMS_THERMISTOR47_DATA_ID = 11, /**< Thermistor 4-7 external ADC telemetry */ -}; - -/** - * @union SystemStatusResp_t - * @brief Telemetry response for system status. - */ -typedef union SystemStatusResp { - struct { - uint32_t runtime; /**< System runtime in seconds */ - uint8_t fw_version; /**< Firmware version */ - }; - uint8_t buffer[SYSTEM_STATUS_RESP_LEN]; /**< Raw buffer for protocol transmission */ -} SystemStatusResp_t; - -/** - * @union CurrentResp_t - * @brief Telemetry response for current sensing. - */ -typedef union CurrentResp { - struct { - uint16_t isense1; /**< Current sensor 1 reading */ - uint16_t isense2; /**< Current sensor 2 reading */ - }; - uint8_t buffer[CURRENT_VOLTAGE_RESP_LEN]; /**< Raw buffer for protocol transmission */ -} CurrentResp_t; - -/** - * @union VoltageResp_t - * @brief Telemetry response for voltage sensing. - */ -typedef union VoltageResp { - struct { - uint16_t vcell_a; /**< Voltage cell A reading */ - uint16_t vcell_b; /**< Voltage cell B reading */ - }; - uint8_t buffer[CURRENT_VOLTAGE_RESP_LEN]; /**< Raw buffer for protocol transmission */ -} VoltageResp_t; - -/** - * @union CombinedVoltageResp_t - * @brief Telemetry response for combined battery voltages. - */ -typedef union CombinedVoltageResp { - struct { - uint16_t vbatt1; /**< Battery 1 voltage */ - uint16_t vbatt2; /**< Battery 2 voltage */ - }; - uint8_t buffer[CURRENT_VOLTAGE_RESP_LEN]; /**< Raw buffer for protocol transmission */ -} CombinedVoltageResp_t; - -/** - * @union Flag_t - * @brief Telemetry response for protection flags. - */ -typedef union Flag { - uint16_t val; /**< Packed flag value (bitfield) */ - uint8_t buffer[2]; /**< Raw buffer for protocol transmission */ -} Flag_t; +extern const struct TINYPROTOCOL_Config protocolConfig; /** * @brief Initializes the Battery Management System hardware and communication. * * Sets up ADCs, GPIOs, PWM, RTC, and registers telemetry/telecommand channels. - * - * @code - * int main(void) - * { - * BMS_init(); - * - * __bis_SR_register(GIE); - * while (1) { - * if (BMS_ISRTriggered()) { - * BMS_collectData(); - * } - * } - * return 0; - * } - * @endcode - */ -extern void BMS_init(); + */ +void BMS_init(); /** * @brief Synchronous data-acquisition pass that refreshes telemetry buffers. * - * Starts one ADC12_B sequence-of-channels sweep (MEM0→MEM9) and *busy-waits* - * until it completes, then copies results into current/voltage unions. Also - * samples protection-flag GPIOs and reads 8 channels from the external - * ADS7138 (thermistors) over software I²C into the two 8-byte buffers. - * - * @details - * - **Synchronous/blocking:** contains a busy-wait on ADC completion. - * - **Side effects:** clears the internal “RTC fired” flag exposed by - * ::BMS_ISRTriggered(), acknowledging the event, and modifies internal static - * data buffers to be read by master (CDH) via Tiny Protocol - * * @pre ::BMS_init() has been called. - * @post Telemetry buffers registered with tinyprotocol contain fresh data. + * @post Collect temperature data over i2c */ -extern void BMS_collectData(); +void BMS_collectData(); /** * @brief Check whether an RTC event occurred since the last collection. * - * This returns a latch set by the RTC ISR. The latch is cleared by - * ::BMS_collectData() after it completes a refresh cycle. - * * @return `true` if an RTC event has occurred and data collection is due; * `false` otherwise. */ -extern bool BMS_ISRTriggered(); +bool BMS_ISRTriggered(); #endif \ No newline at end of file diff --git a/APP/BMS/main.c b/APP/BMS/main.c index 57db932a..a5cf535c 100644 --- a/APP/BMS/main.c +++ b/APP/BMS/main.c @@ -22,6 +22,8 @@ #include "BMS.h" #include "i2c.h" +#include "tinyprotocol.h" + int main(void) { @@ -29,7 +31,8 @@ int main(void) __bis_SR_register(GIE); while (1) { - if (BMS_ISRTriggered()) { + // Probably, I don't know if we can get here while transmitting i2c data or not + if (BMS_ISRTriggered() && !I2C_IS_TRANSMITTING) { BMS_collectData(); } } diff --git a/APP/CDH_App/CMakeLists.txt b/APP/CDH_App/CMakeLists.txt index 36f0a0ab..8c009d94 100644 --- a/APP/CDH_App/CMakeLists.txt +++ b/APP/CDH_App/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(app PRIVATE src/main.c + ../../MIDDLEWARE/tinyprotocol/tinyprotocol.c ) @@ -23,4 +24,7 @@ add_custom_command( POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/icd.html ${CMAKE_CURRENT_LIST_DIR}/../_asn1/icd.html COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/icd.css ${CMAKE_CURRENT_LIST_DIR}/../_asn1/icd.css -) \ No newline at end of file +) +target_include_directories(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../../MIDDLEWARE/shared_types +) diff --git a/APP/CDH_App/app.overlay b/APP/CDH_App/app.overlay index 34bec1d1..427e4099 100644 --- a/APP/CDH_App/app.overlay +++ b/APP/CDH_App/app.overlay @@ -1,2 +1,12 @@ / { -}; \ No newline at end of file + chosen { + ulog,usart = &usart1; + }; +}; + +&ext1_i2c { + bms: bms@9 { + compatible = "vnd,i2c-device"; + reg = <0x09>; + }; +}; diff --git a/APP/CDH_App/prj.conf b/APP/CDH_App/prj.conf index 697363b4..5baf1bbe 100644 --- a/APP/CDH_App/prj.conf +++ b/APP/CDH_App/prj.conf @@ -7,6 +7,8 @@ CONFIG_WDT_DISABLE_AT_BOOT=y CONFIG_LOG=y CONFIG_CONSOLE=y CONFIG_LFP=y +CONFIG_I2C=y +# CONFIG_I2C_ALLOW_NO_STOP_TRANSACTIONS=y CONFIG_ARM_MPU=y CONFIG_THREAD_MONITOR=y CONFIG_THREAD_NAME=y diff --git a/APP/CDH_App/src/main.c b/APP/CDH_App/src/main.c index ffa836fe..2557b6bf 100644 --- a/APP/CDH_App/src/main.c +++ b/APP/CDH_App/src/main.c @@ -12,6 +12,7 @@ #define SYSID_CDH 1 #define SYSID_COMMS 3 +#define SYSID_BMS 5 #define ENDPOINT_COMMS_TEST 154 LOG_MODULE_REGISTER(main); @@ -77,7 +78,8 @@ void asn1_example(void) { lfp_stream_update_buf(&stream, payload, size); } + int main(void) { asn1_example(); -} \ No newline at end of file +} diff --git a/APP/_asn1/bms.asn1 b/APP/_asn1/bms.asn1 index 7c41998c..4d49640d 100644 --- a/APP/_asn1/bms.asn1 +++ b/APP/_asn1/bms.asn1 @@ -28,10 +28,6 @@ BMSCellStatus ::= SEQUENCE { overvoltage BOOLEAN, -- Cell Under Voltage undervoltage BOOLEAN, - -- Cell Over Current - overcurrent BOOLEAN, - -- Cell Under Current - undercurrent BOOLEAN, -- Direct Reading Voltage voltage BMSADCValue } @@ -47,7 +43,9 @@ BMSBatteryPackStatus ::= SEQUENCE { -- Direct Reading of Current Current Sensor CHR currentCharge BMSADCValue, -- Direct Reading of Combined Voltage - voltage BMSADCValue + voltage BMSADCValue, + -- Battery Over Current flag + overcurrent BOOLEAN } diff --git a/DRIVERS/MSP430/I2C/i2c.c b/DRIVERS/MSP430/I2C/i2c.c index fef784b8..67fbe6ff 100644 --- a/DRIVERS/MSP430/I2C/i2c.c +++ b/DRIVERS/MSP430/I2C/i2c.c @@ -1,53 +1,69 @@ #include "i2c.h" #include "utils.h" +#include "lfp.h" +#include "lfp/stream.h" -typedef enum eI2C_Mode { - I2C_IDLE_MODE, /**< I2C is idle */ - I2C_RX_MODE, /**< Receiving Data */ - I2C_TX_MODE, /**< Transmiting Data */ - I2C_MODE_MAX -} eI2C_Mode_t; +static i2c_ctx_t s_ctx; -typedef struct sI2cCtxPriv -{ - void (*Rx_Proc_Data)(uint8_t data); - eI2C_Mode_t i2c_mode; -} sI2cCtxPriv; - -/** I2C SlaveMode - Tracks the current mode of the I2C software state machine */ -static sI2cCtxPriv i2cSlaveCtx = { - .Rx_Proc_Data = NULL, - .i2c_mode = I2C_IDLE_MODE -}; +static volatile uint8_t* p_txbuf; // this is redirected to a static buffer in whichever slave application +static volatile uint8_t s_tx_idx = 0; +static volatile uint16_t s_msg_len = 0; +static volatile i2c_slave_state_t s_current_state = I2C_SLAVE_STATE_REQUEST; -uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; -uint8_t ReceiveIndex = 0; +void i2c_init_registers(uint8_t slave_addr) +{ + UCB0CTLW0 = UCSWRST; // Software reset enabled + UCB0CTLW0 |= UCMODE_3 | UCSYNC; // I2C mode, sync mode + UCB0I2COA0 = slave_addr | UCOAEN; // Own Address and enable + UCB0CTLW0 &= ~UCSWRST; // clear reset register + + UCB0IE |= UCSTTIE; // Enable START interrupt + UCB0IE |= UCRXIE; // Enable RX interrupt + UCB0IE |= UCTXIE; // Enable TX interrupt +} -uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; -uint8_t TransmitIndex = 0; +void i2c_init(i2c_ctx_t* ctx) +{ + s_ctx.slave_addr = ctx->slave_addr; + s_ctx.i2c_rx_cb = ctx->i2c_rx_cb; + i2c_init_registers(ctx->slave_addr); +} -void initI2C(sI2cConfigCb_t* cb_config) +i2c_slave_state_t i2c_slave_current_state() { - UCB0CTLW0 = UCSWRST; // Software reset enabled - UCB0CTLW0 |= UCMODE_3 | UCSYNC; // I2C mode, sync mode - UCB0I2COA0 = cb_config->slave_addr | UCOAEN; // Own Address and enable - UCB0CTLW0 &= ~UCSWRST; // clear reset register + return s_current_state; +} - UCB0IE |= UCSTPIE; // Enable STOP interrupt - UCB0IE |= UCRXIE; // Enable RX interrupt - UCB0IE |= UCTXIE; // Enable TX interrupt +// FIXME: We should only ever transition REQUEST -> PROCESSING -> RESPONSE -> REQUEST ... +void i2c_transition(i2c_slave_state_t state) +{ + // naive for now + if (state == I2C_SLAVE_STATE_REQUEST) { + // discard tx buffer and reset + p_txbuf = NULL; + s_tx_idx = 0; + s_msg_len = 0; + } + + // NACK if we are in processing stage + if (state == I2C_SLAVE_STATE_PROCESSING) { + UCB0CTLW0 |= UCTXNACK; + } else { + UCB0CTLW0 &= ~UCTXNACK; + } - i2cSlaveCtx.Rx_Proc_Data = cb_config->Rx_Proc_Data; - i2cSlaveCtx.i2c_mode = I2C_IDLE_MODE; + s_current_state = state; } -int16_t transmitI2C(const uint8_t* data, uint8_t size) +// NOTE: this is a tad dangerous since we trust the user to pass in memory that is allocated and will stay allocated +int16_t i2c_reassign_txbuf(volatile uint8_t* data, uint8_t size) { - // Copy response to TransmitBuffer - CopyArray((uint8_t*)data, TransmitBuffer, MIN(size, MAX_BUFFER_SIZE)); - - i2cSlaveCtx.i2c_mode = I2C_TX_MODE; + s_tx_idx = 0; + s_msg_len = size; + p_txbuf = data; + // We're ready to start transmitting data + i2c_transition(I2C_SLAVE_STATE_RESPONSE); return 0; // TODO switch to project defined error flags } @@ -71,20 +87,17 @@ void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: break; // Vector 4: NACKIFG - case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG - case USCI_I2C_UCSTPIFG: // Vector 8: STPIFG - if (i2cSlaveCtx.i2c_mode == I2C_RX_MODE) { // Recieve - ReceiveIndex = 0; - } else if (i2cSlaveCtx.i2c_mode == I2C_TX_MODE) { // Transmit - TransmitIndex = 0; - } - // else { - // TODO: throw an error. - // } - - // Done - i2cSlaveCtx.i2c_mode = I2C_IDLE_MODE; + case USCI_I2C_UCSTTIFG: // Vector 6: STTIFG + if (s_current_state == I2C_SLAVE_STATE_PROCESSING) { + UCB0CTLW0 |= UCTXNACK; // NACK master writes while we're processing + } + + // Roll back 1 byte on start to transmit the byte that was missed during the last transmission + if (s_tx_idx > 0 && s_tx_idx <= s_msg_len) { + s_tx_idx--; + } break; + case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3 case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2 @@ -92,18 +105,23 @@ void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1 case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1 case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0 -> Receive one byte from MASTER (SAMV71) - ReceiveBuffer[ReceiveIndex] = UCB0RXBUF; // -> Get the single byte - i2cSlaveCtx.Rx_Proc_Data(ReceiveBuffer[ReceiveIndex]); - - ReceiveIndex = (ReceiveIndex + 1) % MAX_BUFFER_SIZE; - i2cSlaveCtx.i2c_mode = I2C_RX_MODE; + s_ctx.i2c_rx_cb(UCB0RXBUF); break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 -> Send one byte to MASTER (SAMV71) - UCB0TXBUF = TransmitBuffer[TransmitIndex]; - - TransmitIndex = (TransmitIndex + 1) % MAX_BUFFER_SIZE; - i2cSlaveCtx.i2c_mode = I2C_TX_MODE; - break; // Interrupt Vector: I2C Mode: UCTXIFG + if (s_current_state != I2C_SLAVE_STATE_RESPONSE) { // Unless we are in response state, just return 0xFF + UCB0TXBUF = 0xFF; + } else if (!p_txbuf || s_tx_idx >= s_msg_len) { // if we are asked for more bytes than we have, send 0xFF + // If we are at the byte after the last byte, go one over to make sure we dont roll back on start + // (by now the controller has received atleast one 0xFF) + if (s_tx_idx == s_msg_len) { + s_tx_idx++; + } + UCB0TXBUF = 0xFF; + } else { + UCB0TXBUF = p_txbuf[s_tx_idx++]; + } + break; + default: break; } diff --git a/DRIVERS/MSP430/I2C/i2c.h b/DRIVERS/MSP430/I2C/i2c.h index b3d094c0..ab4c1057 100644 --- a/DRIVERS/MSP430/I2C/i2c.h +++ b/DRIVERS/MSP430/I2C/i2c.h @@ -1,12 +1,6 @@ /** * @file MSP430_I2C.h - * @brief I2C driver header for MSP430. This header defines configurations, command IDs, - * state machine variables, and functions used for I2C communication between an MSP430 - * device (slave) and a master device. - * - * @requirements: - * - Compatible with MSP430FR59xx series running at 16 MHz. - * - Configures I2C in slave mode with specific commands and response structures. + * @brief I2C slave driver header for MSP430. */ #ifndef _I2C_ @@ -15,27 +9,48 @@ #include #include #include +#include +#include -//******************************************************************************* -// General I2C State Machine *************************************************** -//******************************************************************************* +#define I2C_IS_TRANSMITTING (UCB0CTLW0 & UCTR) -#define MAX_BUFFER_SIZE 20 /**< Maximum buffer size for I2C data transmission */ +extern uint8_t I2C_CLOCK_HANG; -typedef struct sI2cConfigCb -{ - void (*Rx_Proc_Data)(uint8_t data); +typedef void (*i2c_proc_byte_cb_t)(uint8_t byte); +typedef struct { + i2c_proc_byte_cb_t i2c_rx_cb; uint8_t slave_addr; -} sI2cConfigCb_t; - +} i2c_ctx_t; + +typedef enum { + I2C_SLAVE_STATE_REQUEST, + I2C_SLAVE_STATE_PROCESSING, + I2C_SLAVE_STATE_RESPONSE +} i2c_slave_state_t; + +/** + * Configures i2c module (usci_b) in slave mode + * + * @param slave_addr our i2c slave address + */ +void i2c_init_registers(uint8_t slave_addr); /** - * @brief Initializes the I2C module in slave mode with the specified slave address. + * Sets config data and configures i2c module (usci_b) in slave mode + * + * @param cb_config context with callback and slave address */ -void initI2C(sI2cConfigCb_t* cb_config); +void i2c_init(i2c_ctx_t* cb_config); + +void i2c_transition(i2c_slave_state_t slave); + +i2c_slave_state_t i2c_slave_current_state(); + /** -* @brief Write -*/ -int16_t transmitI2C(const uint8_t* data, uint8_t size) ; + * Reassigns the transmit buffer pointer. Basically assumes data is a static global buffer. + * @param data Static data buffer which we will be sending directly over i2c when asked + * @param size How much data is available to be sent + */ +int16_t i2c_reassign_txbuf(volatile uint8_t* data, uint8_t size); #endif /* I2C */ diff --git a/MIDDLEWARE/asn1/_systems.c b/MIDDLEWARE/asn1/_systems.c new file mode 100644 index 00000000..0d6aeaa6 --- /dev/null +++ b/MIDDLEWARE/asn1/_systems.c @@ -0,0 +1,16 @@ +/* +Code automatically generated by asn1scc tool +*/ +#include +#include +#include + +#include "asn1crt_encoding.h" +#include "asn1crt_encoding_uper.h" + +#include "_systems.h" + +const asn1SccSint groundSystemId = 0LL; +const asn1SccSint cdhSystemId = 1LL; +const asn1SccSint bmsSystemId = 2LL; + diff --git a/MIDDLEWARE/asn1/_systems.h b/MIDDLEWARE/asn1/_systems.h new file mode 100644 index 00000000..6d1074cc --- /dev/null +++ b/MIDDLEWARE/asn1/_systems.h @@ -0,0 +1,32 @@ +#ifndef GENERATED_ASN1SCC__systems_H +#define GENERATED_ASN1SCC__systems_H +/* +Code automatically generated by asn1scc tool +*/ +#include "asn1crt.h" +#include "asn1crt_encoding.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +extern const asn1SccSint groundSystemId; +extern const asn1SccSint cdhSystemId; +extern const asn1SccSint bmsSystemId; + +/* ================= Encoding/Decoding function prototypes ================= + * These functions are placed at the end of the file to make sure all types + * have been declared first, in case of parameterized ACN encodings + * ========================================================================= */ + + + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/MIDDLEWARE/asn1/asn1crt.c b/MIDDLEWARE/asn1/asn1crt.c new file mode 100644 index 00000000..2d2da855 --- /dev/null +++ b/MIDDLEWARE/asn1/asn1crt.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +#include "asn1crt.h" + +#if WORD_SIZE==8 +const asn1SccUint64 ber_aux[] = { + 0xFF, + 0xFF00, + 0xFF0000, + 0xFF000000, + 0xFF00000000ULL, + 0xFF0000000000ULL, + 0xFF000000000000ULL, + 0xFF00000000000000ULL }; +#else +const asn1SccUint32 ber_aux[] = { + 0xFF, + 0xFF00, + 0xFF0000, + 0xFF000000 }; +#endif + +asn1SccUint int2uint(asn1SccSint v) { + asn1SccUint ret = 0; + if (v < 0) { + ret = (asn1SccUint)(-v - 1); + ret = ~ret; + } + else { + ret = (asn1SccUint)v; + }; + return ret; +} + +asn1SccSint uint2int(asn1SccUint v, int uintSizeInBytes) { + int i; + asn1SccUint tmp = 0x80; + flag bIsNegative = (v & (tmp << ((uintSizeInBytes - 1) * 8)))>0; + if (!bIsNegative) + return (asn1SccSint)v; + for (i = WORD_SIZE - 1; i >= uintSizeInBytes; i--) + v |= ber_aux[i]; + return -(asn1SccSint)(~v) - 1; +} + + + + + +int binarySearch(const asn1SccSint arr[], int size, asn1SccSint value) { + int low = 0; + int high = size - 1; + while (low <= high) { + int mid = low + (high - low) / 2; // This prevents overflow. + if (arr[mid] == value) + return mid; // Value found + else if (arr[mid] < value) + low = mid + 1; // Search the right half + else + high = mid - 1; // Search the left half + } + return -1; // Value not found +} + +int linearSearch(const asn1SccSint arr[], int size, asn1SccSint value) { + for (int i = 0; i < size; i++) { + if (arr[i] == value) + return i; // Value found + } + return -1; // Value not found +} + + +/* + +####### ### +# # ##### # ###### #### ##### # ##### ###### # # ##### # ###### # ###### ##### +# # # # # # # # # # # # # ## # # # # # # # # +# # ##### # ##### # # # # # ##### # # # # # ##### # ##### # # +# # # # # # # # # # # # # # # # # # # # ##### +# # # # # # # # # # # # # # # ## # # # # # # # +####### ##### #### ###### #### # ### ##### ###### # # # # # # ###### # # + +Object Identifier + +*/ + + + + + + + + diff --git a/MIDDLEWARE/asn1/asn1crt.h b/MIDDLEWARE/asn1/asn1crt.h new file mode 100644 index 00000000..59a27c06 --- /dev/null +++ b/MIDDLEWARE/asn1/asn1crt.h @@ -0,0 +1,316 @@ +#ifndef ASN1SCC_ASN1CRT_H_ +#define ASN1SCC_ASN1CRT_H_ + +#include + + +#ifdef __cplusplus +extern "C" { +# include +# include + /* C99 check */ +#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || _MSC_VER >= 1900 +# include +# include +# include +#else /* No C++ nor C99 */ +# ifndef _MSC_VER +typedef unsigned char bool; +# define true 1u +# define false 0u +# endif /* _MSC_VER */ + +typedef unsigned char uint8_t; + +typedef int int32_t; +typedef unsigned int uint32_t; + +typedef long long int64_t; +typedef unsigned long long uint64_t; + +#endif /* C++/C99 */ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE true +#endif + +#ifndef FALSE +#define FALSE false +#endif + +#ifndef WORD_SIZE +#define WORD_SIZE 8 +#endif + +#ifndef FP_WORD_SIZE +#define FP_WORD_SIZE 8 +#endif + +#ifndef NO_OF_BITS_IN_BYTE +#define NO_OF_BITS_IN_BYTE 8 +#endif + +#ifndef NO_OF_BYTES_IN_INT16 +#define NO_OF_BYTES_IN_INT16 (sizeof(int16_t)) // 2 +#endif + +#ifndef NO_OF_BYTES_IN_INT32 +#define NO_OF_BYTES_IN_INT32 (sizeof(int32_t)) // 4 +#endif + +#ifndef NO_OF_BITS_IN_INT16 +#define NO_OF_BITS_IN_INT16 (NO_OF_BYTES_IN_INT16 * NO_OF_BITS_IN_BYTE) // 16 +#endif + +#ifndef NO_OF_BITS_IN_INT32 +#define NO_OF_BITS_IN_INT32 (NO_OF_BYTES_IN_INT32 * NO_OF_BITS_IN_BYTE) // 32 +#endif + +#ifndef PRId32 +#define PRId32 "d" +#endif + +#ifndef PRId64 +#define PRId64 "lld" +#endif + +#ifndef PRIu32 +#define PRIu32 "u" +#endif + +#ifndef PRIu64 +#define PRIu64 "llu" +#endif + +#define OBJECT_IDENTIFIER_MAX_LENGTH 20 + + +typedef float asn1Real32; +typedef double asn1Real64; + +typedef uint8_t byte; + +typedef int32_t asn1SccSint32; +typedef uint32_t asn1SccUint32; + +typedef int64_t asn1SccSint64; +typedef uint64_t asn1SccUint64; + +#if WORD_SIZE==8 +typedef asn1SccUint64 asn1SccUint; +typedef asn1SccSint64 asn1SccSint; +#define ASN1SCC_PRId PRId64 +#define ASN1SCC_PRIu PRIu64 +#else +typedef asn1SccUint32 asn1SccUint; +typedef asn1SccSint32 asn1SccSint; +#define ASN1SCC_PRId PRId32 +#define ASN1SCC_PRIu PRIu32 +#endif + +asn1SccUint int2uint(asn1SccSint v); +asn1SccSint uint2int(asn1SccUint v, int uintSizeInBytes); + +#if FP_WORD_SIZE==8 +typedef asn1Real64 asn1Real; +#else +typedef asn1Real32 asn1Real; +#endif + +#if WORD_SIZE==8 +#define MAX_INT 0xFFFFFFFFFFFFFFFFULL +#else +#define MAX_INT 0xFFFFFFFF +#endif + +#ifdef _MSC_VER +# ifndef INFINITY +# define INFINITY (DBL_MAX+DBL_MAX) +# endif +# ifndef NAN +# define NAN (INFINITY-INFINITY) +# endif +#endif + +typedef bool flag; + +typedef char NullType; + +struct BitStream_t; + +//typedef void(*PushDataFnc)(struct BitStream_t* pThis, void* pushDataPrm); +//typedef void(*FetchDataFnc)(struct BitStream_t* pThis, void* fetchDataPrm); + +typedef struct BitStream_t { + byte* buf; + long count; + long currentByte; + /* Next available bit for writting. + Possible vallues 0..7, 0 is most significant + bit of current byte*/ + int currentBit; + //PushDataFnc pushData; + void* pushDataPrm; + //FetchDataFnc fetchData; + void* fetchDataPrm; +} BitStream; + + + + + +typedef struct { + byte* buf; + long count; + long currentByte; + flag EncodeWhiteSpace; +} ByteStream; + +typedef struct { + int TokenID; + char Value[100]; +} Token; + +typedef struct { + char Name[50]; + char Value[100]; +} XmlAttribute; + +typedef struct { + XmlAttribute attrs[20]; + int nCount; +} XmlAttributeArray; + +typedef struct { + int nCount; + asn1SccUint values[OBJECT_IDENTIFIER_MAX_LENGTH]; +} Asn1ObjectIdentifier; + +#define ERR_INSUFFICIENT_DATA 101 +#define ERR_INCORRECT_PER_STREAM 102 +#define ERR_INVALID_CHOICE_ALTERNATIVE 103 +#define ERR_INVALID_ENUM_VALUE 104 +#define ERR_INVALID_XML_FILE 200 +#define ERR_INVALID_BER_FILE 201 +#define ERR_BER_LENGTH_MISMATCH 202 + + + +/** + * Performs a binary search on a sorted array to find the index of a given value. + * + * @param arr The sorted array to search. + * @param size The size of the array. + * @param value The value to search for. + * @return The index of the value if found, -1 otherwise. + */ +int binarySearch(const asn1SccSint arr[], int size, asn1SccSint value); + +/** + * Performs a linear search on an array to find a specific value. + * + * @param arr The array to be searched. + * @param size The size of the array. + * @param value The value to be searched for. + * @return The index of the value if found, or -1 if not found. + */ +int linearSearch(const asn1SccSint arr[], int size, asn1SccSint value); + + +/* Time Classes + Asn1LocalTime, // TIME-OF-DAY ::= TIME(SETTINGS "Basic=Time Time=HMS Local-or-UTC=L") + Asn1UtcTime, // TIME(SETTINGS "Basic=Time Time=HMS Local-or-UTC=Z") + Asn1LocalTimeWithTimeZone, // TIME(SETTINGS "Basic=Time Time=HMS Local-or-UTC=LD") + Asn1Date, // DATE ::= TIME(SETTINGS "Basic=Date Date=YMD Year=Basic") + Asn1Date_LocalTime, // DATE-TIME ::= TIME(SETTINGS "Basic=Date-Time Date=YMD Year=Basic Time=HMS Local-or-UTC=L") + Asn1Date_UtcTime, // TIME(SETTINGS "Basic=Date-Time Date=YMD Year=Basic Time=HMS Local-or-UTC=Z") + Asn1Date_LocalTimeWithTimeZone // TIME(SETTINGS "Basic=Date-Time Date=YMD Year=Basic Time=HMS Local-or-UTC=LD") +*/ +typedef struct { + int sign; //-1 or +1 + int hours; + int mins; +} Asn1TimeZone; + +typedef struct { + int hours; + int mins; + int secs; + int fraction; + Asn1TimeZone tz; +} Asn1TimeWithTimeZone; + +typedef struct { + int hours; + int mins; + int secs; + int fraction; +} Asn1UtcTime; + +typedef struct { + int hours; + int mins; + int secs; + int fraction; +} Asn1LocalTime; + +typedef struct { + int years; + int months; + int days; +} Asn1Date; + +typedef struct { + Asn1Date date; + Asn1LocalTime time; +} Asn1DateLocalTime; + +typedef struct { + Asn1Date date; + Asn1UtcTime time; +} Asn1DateUtcTime; + +typedef struct { + Asn1Date date; + Asn1TimeWithTimeZone time; +} Asn1DateTimeWithTimeZone; + +typedef enum { + Asn1TC_LocalTimeStamp, + Asn1TC_UtcTimeStamp, + Asn1TC_LocalTimeTZStamp +} Asn1TimeZoneClass; + +typedef asn1SccUint BerTag; + +#if WORD_SIZE==8 +extern const asn1SccUint64 ber_aux[]; +#else +extern const asn1SccUint32 ber_aux[]; +#endif + +#define CHECK_BIT_STREAM(pBitStrm) assert((pBitStrm)->currentByte*8+(pBitStrm)->currentBit<=(pBitStrm)->count*8) + +// check if nBits still have space in pBitStrm (only for non streaming mode) +#ifndef ASN1SCC_STREAMING +#define CHECK_BIT_STREAM_PRE(pBitStrm, nBits) assert( (long)((pBitStrm)->currentByte * 8 + (pBitStrm)->currentBit + (nBits)) <= ((pBitStrm)->count * 8)) +#else +#define CHECK_BIT_STREAM_PRE(pBitStrm, nBits) ((void)pBitStrm) +#endif + +#ifdef _MSC_VER +#pragma warning( disable : 4127) +#endif + +#define ASSERT_OR_RETURN_FALSE(_Expression) do { assert(_Expression); if (!(_Expression)) return FALSE;} while(0) + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/MIDDLEWARE/asn1/asn1crt_encoding.c b/MIDDLEWARE/asn1/asn1crt_encoding.c new file mode 100644 index 00000000..106636de --- /dev/null +++ b/MIDDLEWARE/asn1/asn1crt_encoding.c @@ -0,0 +1,744 @@ +#include +#include +#include +#include + +#include "asn1crt_encoding.h" + + + +const byte masks[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; +const byte masksb[] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF }; + +const asn1SccUint32 masks2[] = { 0x0, +0xFF, +0xFF00, +0xFF0000, +0xFF000000 }; + +flag OctetString_equal(int len1, int len2, const byte arr1[], const byte arr2[]) +{ + return (len1 == len2) && (memcmp(arr1, arr2, len1) == 0); +} + +/***********************************************************************************************/ +/* Byte Stream Functions */ +/***********************************************************************************************/ + + + + +asn1SccSint ByteStream_GetLength(ByteStream* pStrm) +{ + return pStrm->currentByte; +} + + +/***********************************************************************************************/ +/* Bit Stream Functions */ +/***********************************************************************************************/ + + + + +void BitStream_Init(BitStream* pBitStrm, unsigned char* buf, long count) +{ + pBitStrm->count = count; + pBitStrm->buf = buf; + memset(pBitStrm->buf, 0x0, (size_t)count); + pBitStrm->currentByte = 0; + pBitStrm->currentBit = 0; + pBitStrm->pushDataPrm = NULL; + pBitStrm->fetchDataPrm = NULL; +} + + + +void BitStream_AttachBuffer(BitStream* pBitStrm, unsigned char* buf, long count) +{ + pBitStrm->count = count; + pBitStrm->buf = buf; + pBitStrm->currentByte = 0; + pBitStrm->currentBit = 0; + pBitStrm->pushDataPrm = NULL; + pBitStrm->fetchDataPrm = NULL; +} + +void BitStream_AttachBuffer2(BitStream* pBitStrm, unsigned char* buf, long count, void* pushDataPrm, void* fetchDataPrm) +{ + BitStream_AttachBuffer(pBitStrm, buf, count); + pBitStrm->pushDataPrm = pushDataPrm; + pBitStrm->fetchDataPrm = fetchDataPrm; +} + + +asn1SccSint BitStream_GetLength(BitStream* pBitStrm) +{ + int ret = pBitStrm->currentByte; + if (pBitStrm->currentBit) + ret++; + return ret; +} + +/* +Append bit one. + +Example + cur bit = 3 + x x x | + |_|_|_|_|_|_|_|_| + 0 1 2 3 4 5 6 7 + + xxxy???? +or 00010000 +------------ + xxx1???? +*/ + + + +/* + Append bit zero. + + Example + cur bit = 3 + x x x | + |_|_|_|_|_|_|_|_| + 0 1 2 3 4 5 6 7 + + xxxy???? + and 11101111 + ------------ + xxx0???? +*/ + + + +void BitStream_AppendNBitZero(BitStream* pBitStrm, int nbits) +{ + int totalBits = pBitStrm->currentBit + nbits; + int totalBytes = totalBits / 8; + pBitStrm->currentBit = totalBits % 8; + //pBitStrm->currentByte += totalBits / 8; + if (pBitStrm->currentByte + totalBytes <= pBitStrm->count) { + pBitStrm->currentByte += totalBytes; + bitstream_push_data_if_required(pBitStrm); + } else { + int extraBytes = pBitStrm->currentByte + totalBytes - pBitStrm->count; + pBitStrm->currentByte = pBitStrm->count; + bitstream_push_data_if_required(pBitStrm); + pBitStrm->currentByte = extraBytes; + } +} + + + + + +void BitStream_AppendBit(BitStream* pBitStrm, flag v) +{ + if (v) { + pBitStrm->buf[pBitStrm->currentByte] |= masks[pBitStrm->currentBit]; + } + else { + byte nmask = (byte)~masks[pBitStrm->currentBit]; + pBitStrm->buf[pBitStrm->currentByte] &= nmask; + } + + if (pBitStrm->currentBit<7) + pBitStrm->currentBit++; + else { + pBitStrm->currentBit = 0; + pBitStrm->currentByte++; + bitstream_push_data_if_required(pBitStrm); + } + assert(pBitStrm->currentByte * 8 + pBitStrm->currentBit <= pBitStrm->count * 8); +} + + +flag BitStream_ReadBit(BitStream* pBitStrm, flag* v) +{ + *v = pBitStrm->buf[pBitStrm->currentByte] & masks[pBitStrm->currentBit]; + + if (pBitStrm->currentBit<7) + pBitStrm->currentBit++; + else { + pBitStrm->currentBit = 0; + pBitStrm->currentByte++; + bitstream_fetch_data_if_required(pBitStrm); + } + return pBitStrm->currentByte * 8 + pBitStrm->currentBit <= pBitStrm->count * 8; +} + + + + +/* +Append byte. + +Example +cur bit = 3 + | + x x x b b b b b b b b +|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| + 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + +first byte + xxx????? +and 11100000 (mask) +------------ + xxx00000 +or 000bbbbb +------------ + xxxbbbbb + +*/ + + +void BitStream_AppendByte(BitStream* pBitStrm, byte v, flag negate) +{ + //static byte masksb[] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF }; + int cb = pBitStrm->currentBit; + int ncb = 8 - cb; + if (negate) + v = (byte)~v; + byte mask = (byte)~masksb[ncb]; + + pBitStrm->buf[pBitStrm->currentByte] &= mask; + pBitStrm->buf[pBitStrm->currentByte++] |= (byte)(v >> cb); + bitstream_push_data_if_required(pBitStrm); + assert(pBitStrm->currentByte * 8 + pBitStrm->currentBit <= pBitStrm->count * 8); + + if (cb) { + mask = (byte)~mask; + pBitStrm->buf[pBitStrm->currentByte] &= mask; + pBitStrm->buf[pBitStrm->currentByte] |= (byte)(v << ncb); + } + +} + + + + + + +flag BitStream_ReadByte(BitStream* pBitStrm, byte* v) +{ + int cb = pBitStrm->currentBit; //bit position in the current byte + + //check if the available bytes are enough + int requiredBytes = (cb > 0) ? 2 : 1; + int availableBytes = pBitStrm->count - pBitStrm->currentByte; + + if (availableBytes < requiredBytes) { + return FALSE; + } + + *v = (byte)(pBitStrm->buf[pBitStrm->currentByte++] << cb); + bitstream_fetch_data_if_required(pBitStrm); + + if (cb > 0) { + // we need to read bits from the next byte + int ncb = 8 - cb; + *v |= (byte)(pBitStrm->buf[pBitStrm->currentByte] >> ncb); + } + + return TRUE; +} + + + + + + + +/* +flag BitStream_ReadByte2(BitStream2* pBitStrm, byte* v) +{ + int cb = pBitStrm->currentBit; + int ncb = 8 - pBitStrm->currentBit; + *v = (byte)(pBitStrm->buf[pBitStrm->currentByte++] << cb); + + if (pBitStrm->currentByte == pBitStrm->count && pBitStrm->fetchData != NULL) { + pBitStrm->fetchData(pBitStrm); + } + + if (cb) { + *v |= (byte)(pBitStrm->buf[pBitStrm->currentByte] >> ncb); + } + + return pBitStrm->currentByte * 8 + pBitStrm->currentBit <= pBitStrm->count * 8; +} + +*/ + + + +/* nbits 1..7*/ +void BitStream_AppendPartialByte(BitStream* pBitStrm, byte v, byte nbits, flag negate) +{ + int cb = pBitStrm->currentBit; + int totalBits = cb + nbits; + int ncb = 8 - cb; + int totalBitsForNextByte; + if (negate) + v = masksb[nbits] & ((byte)~v); + byte mask1 = (byte)~masksb[ncb]; + + if (totalBits <= 8) { + //static byte masksb[] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF }; + byte mask2 = masksb[8 - totalBits]; + byte mask = mask1 | mask2; + //e.g. current bit = 3 --> mask = 1110 0000 + //nbits = 3 --> totalBits = 6 + // mask= 1110 0000 + // and 0000 0011 <- masks[totalBits - 1] + // ----------- + // final mask 1110 0011 + pBitStrm->buf[pBitStrm->currentByte] &= mask; + pBitStrm->buf[pBitStrm->currentByte] |= (byte)(v << (8 - totalBits)); + pBitStrm->currentBit += nbits; + if (pBitStrm->currentBit == 8) { + pBitStrm->currentBit = 0; + pBitStrm->currentByte++; + bitstream_push_data_if_required(pBitStrm); + } + } + else { + totalBitsForNextByte = totalBits - 8; + pBitStrm->buf[pBitStrm->currentByte] &= mask1; + pBitStrm->buf[pBitStrm->currentByte++] |= (byte)(v >> totalBitsForNextByte); + bitstream_push_data_if_required(pBitStrm); + byte mask = (byte)~masksb[8 - totalBitsForNextByte]; + pBitStrm->buf[pBitStrm->currentByte] &= mask; + pBitStrm->buf[pBitStrm->currentByte] |= (byte)(v << (8 - totalBitsForNextByte)); + pBitStrm->currentBit = totalBitsForNextByte; + } + assert(pBitStrm->currentByte * 8 + pBitStrm->currentBit <= pBitStrm->count * 8); + +} + +/* nbits 1..7*/ +flag BitStream_ReadPartialByte(BitStream* pBitStrm, byte *v, byte nbits) +{ + int cb = pBitStrm->currentBit; + int totalBits = cb + nbits; + int totalBitsForNextByte; + + if (totalBits <= 8) { + *v = (byte)((pBitStrm->buf[pBitStrm->currentByte] >> (8 - totalBits)) & masksb[nbits]); + pBitStrm->currentBit += nbits; + if (pBitStrm->currentBit == 8) { + pBitStrm->currentBit = 0; + pBitStrm->currentByte++; + bitstream_fetch_data_if_required(pBitStrm); + } + } + else { + totalBitsForNextByte = totalBits - 8; + *v = (byte)(pBitStrm->buf[pBitStrm->currentByte++] << totalBitsForNextByte); + bitstream_fetch_data_if_required(pBitStrm); + *v |= (byte)(pBitStrm->buf[pBitStrm->currentByte] >> (8 - totalBitsForNextByte)); + *v &= masksb[nbits]; + pBitStrm->currentBit = totalBitsForNextByte; + } + return pBitStrm->currentByte * 8 + pBitStrm->currentBit <= pBitStrm->count * 8; +} + + + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/***********************************************************************************************/ +/***********************************************************************************************/ +/* Integer Functions */ +/***********************************************************************************************/ +/***********************************************************************************************/ +/***********************************************************************************************/ +/***********************************************************************************************/ + + + +static void BitStream_EncodeNonNegativeInteger32Neg(BitStream* pBitStrm, + asn1SccUint32 v, + flag negate) +{ + int cc; + asn1SccUint32 curMask; + int pbits; + + if (v == 0) + return; + + if (v<0x100) { + cc = 8; + curMask = 0x80; + } + else if (v<0x10000) { + cc = 16; + curMask = 0x8000; + } + else if (v<0x1000000) { + cc = 24; + curMask = 0x800000; + } + else { + cc = 32; + curMask = 0x80000000; + } + + while ((v & curMask) == 0) { + curMask >>= 1; + cc--; + } + + pbits = cc % 8; + if (pbits) { + cc -= pbits; + BitStream_AppendPartialByte(pBitStrm, (byte)(v >> cc), (byte)pbits, negate); + } + + while (cc) { + asn1SccUint32 t1 = v & masks2[cc >> 3]; + cc -= 8; + BitStream_AppendByte(pBitStrm, (byte)(t1 >> cc), negate); + } + +} + +static flag BitStream_DecodeNonNegativeInteger32Neg(BitStream* pBitStrm, + asn1SccUint32* v, + int nBits) +{ + byte b; + *v = 0; + while (nBits >= 8) { + *v <<= 8; + if (!BitStream_ReadByte(pBitStrm, &b)) + return FALSE; + *v |= b; + nBits -= 8; + } + if (nBits) + { + *v <<= nBits; + if (!BitStream_ReadPartialByte(pBitStrm, &b, (byte)nBits)) + return FALSE; + *v |= b; + } + + return TRUE; +} + + + +void BitStream_EncodeNonNegativeInteger(BitStream* pBitStrm, asn1SccUint v) +{ + +#if WORD_SIZE==8 + if (v<0x100000000LL) + BitStream_EncodeNonNegativeInteger32Neg(pBitStrm, (asn1SccUint32)v, 0); + else { + asn1SccUint32 hi = (asn1SccUint32)(v >> 32); + asn1SccUint32 lo = (asn1SccUint32)v; + int nBits; + BitStream_EncodeNonNegativeInteger32Neg(pBitStrm, hi, 0); + + nBits = GetNumberOfBitsForNonNegativeInteger(lo); + BitStream_AppendNBitZero(pBitStrm, 32 - nBits); + BitStream_EncodeNonNegativeInteger32Neg(pBitStrm, lo, 0); + } +#else + BitStream_EncodeNonNegativeInteger32Neg(pBitStrm, v, 0); +#endif +} + + +flag BitStream_DecodeNonNegativeInteger(BitStream* pBitStrm, asn1SccUint* v, int nBits) +{ +#if WORD_SIZE==8 + asn1SccUint32 hi = 0; + asn1SccUint32 lo = 0; + flag ret; + + if (nBits <= 32) + { + ret = BitStream_DecodeNonNegativeInteger32Neg(pBitStrm, &lo, nBits); + *v = lo; + return ret; + } + + ret = BitStream_DecodeNonNegativeInteger32Neg(pBitStrm, &hi, 32) && BitStream_DecodeNonNegativeInteger32Neg(pBitStrm, &lo, nBits - 32); + + *v = hi; + *v <<= nBits - 32; + *v |= lo; + return ret; +#else + return BitStream_DecodeNonNegativeInteger32Neg(pBitStrm, v, nBits); +#endif +} + + + + +int GetNumberOfBitsForNonNegativeInteger32(asn1SccUint32 v) +{ + int ret = 0; + + if (v<0x100) { + ret = 0; + } + else if (v<0x10000) { + ret = 8; + v >>= 8; + } + else if (v<0x1000000) { + ret = 16; + v >>= 16; + } + else { + ret = 24; + v >>= 24; + } + while (v>0) { + v >>= 1; + ret++; + } + return ret; +} + +int GetNumberOfBitsForNonNegativeInteger(asn1SccUint v) +{ +#if WORD_SIZE==8 + if (v<0x100000000LL) + return GetNumberOfBitsForNonNegativeInteger32((asn1SccUint32)v); + else { + asn1SccUint32 hi = (asn1SccUint32)(v >> 32); + return 32 + GetNumberOfBitsForNonNegativeInteger32(hi); + } +#else + return GetNumberOfBitsForNonNegativeInteger32(v); +#endif +} + + + + + + + + + + + +void BitStream_EncodeConstraintPosWholeNumber(BitStream* pBitStrm, asn1SccUint v, asn1SccUint min, asn1SccUint max) +{ + int nRangeBits; + int nBits; + asn1SccUint range; + assert(min <= v); + assert(v <= max); + range = (asn1SccUint)(max - min); + if (!range) + return; + nRangeBits = GetNumberOfBitsForNonNegativeInteger(range); + nBits = GetNumberOfBitsForNonNegativeInteger(v - min); + BitStream_AppendNBitZero(pBitStrm, nRangeBits - nBits); + BitStream_EncodeNonNegativeInteger(pBitStrm, v - min); +} + + + + + + + + + + + +flag BitStream_DecodeConstraintPosWholeNumberUInt8(BitStream* pBitStrm, uint8_t* v, uint8_t min, uint8_t max) +{ + asn1SccUint bv; + flag ret; + ret = BitStream_DecodeConstraintPosWholeNumber(pBitStrm, &bv, min, max); + *v = (uint8_t)bv; + return ret; +} + +flag BitStream_DecodeConstraintPosWholeNumberUInt16(BitStream* pBitStrm, uint16_t* v, uint16_t min, uint16_t max) +{ + asn1SccUint bv; + flag ret; + ret = BitStream_DecodeConstraintPosWholeNumber(pBitStrm, &bv, min, max); + *v = (uint16_t)bv; + return ret; +} + + +flag BitStream_DecodeConstraintPosWholeNumberUInt32(BitStream* pBitStrm, uint32_t* v, uint32_t min, uint32_t max) +{ + asn1SccUint bv; + flag ret; + ret = BitStream_DecodeConstraintPosWholeNumber(pBitStrm, &bv, min, max); + *v = (uint32_t)bv; + return ret; +} + + + + +flag BitStream_DecodeConstraintPosWholeNumber(BitStream* pBitStrm, asn1SccUint* v, asn1SccUint min, asn1SccUint max) +{ + asn1SccUint uv; + int nRangeBits; + asn1SccUint range = max - min; + + ASSERT_OR_RETURN_FALSE(min <= max); + + + *v = 0; + if (!range) { + *v = min; + return TRUE; + } + + nRangeBits = GetNumberOfBitsForNonNegativeInteger(range); + + if (BitStream_DecodeNonNegativeInteger(pBitStrm, &uv, nRangeBits)) + { + *v = uv + min; + return TRUE; + } + return FALSE; +} + + + + + + + + + + + + + + + + + + +#ifndef INFINITY +#ifdef __GNUC__ +#define INFINITY (__builtin_inf()) +#endif +#endif + +/* +Bynary encoding will be used +REAL = M*B^E +where +M = S*N*2^F + +ENCODING is done within three parts +part 1 is 1 byte header +part 2 is 1 or more byte for exponent +part 3 is 3 or more byte for mantissa (N) + +First byte +S :0-->+, S:1-->-1 +Base will be always be 2 (implied by 6th and 5th bit which are zero) +ab: F (0..3) +cd:00 --> 1 byte for exponent as 2's complement +cd:01 --> 2 byte for exponent as 2's complement +cd:10 --> 3 byte for exponent as 2's complement +cd:11 --> 1 byte for encoding the length of the exponent, then the expoent + +8 7 6 5 4 3 2 1 ++-+-+-+-+-+-+-+-+ +|1|S|0|0|a|b|c|d| ++-+-+-+-+-+-+-+-+ +*/ + +#if FP_WORD_SIZE==8 + +#define ExpoBitMask 0x7FF0000000000000ULL +#define MantBitMask 0x000FFFFFFFFFFFFFULL +#define MantBitMask2 0xFFE0000000000000ULL +#define MantisaExtraBit 0x0010000000000000ULL +#else + +#define ExpoBitMask 0x7F800000U +#define MantBitMask 0x007FFFFFU +#define MantBitMask2 0xF0000000U +#define MantisaExtraBit 0x00800000U + +#endif + + + + + + + + + + + +flag DecodeRealAsBinaryEncoding(BitStream* pBitStrm, int length, byte header, asn1Real* v); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#ifdef ASN1SCC_STREAMING +void bitstream_fetch_data_if_required(BitStream* pStrm) { + if (pStrm->currentByte == pStrm->count && pStrm->fetchDataPrm != NULL) { + fetchData(pStrm, pStrm->fetchDataPrm); + pStrm->currentByte = 0; + } +} + + +void bitstream_push_data_if_required(BitStream* pStrm) { + if (pStrm->currentByte == pStrm->count && pStrm->pushDataPrm != NULL) { + pushData(pStrm, pStrm->pushDataPrm); + pStrm->currentByte = 0; + } +} +#endif + + + diff --git a/MIDDLEWARE/asn1/asn1crt_encoding.h b/MIDDLEWARE/asn1/asn1crt_encoding.h new file mode 100644 index 00000000..b394aca9 --- /dev/null +++ b/MIDDLEWARE/asn1/asn1crt_encoding.h @@ -0,0 +1,93 @@ +#ifndef ASN1SCC_ASN1CRT_ENCODING_H_ +#define ASN1SCC_ASN1CRT_ENCODING_H_ + +#include "asn1crt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +flag OctetString_equal(int len1, int len2, const byte arr1[], const byte arr2[]); + +/* Byte stream functions */ + +void BitStream_AttachBuffer2(BitStream* pBitStrm, unsigned char* buf, long count, void* pushDataPrm, void* fetchDataPrm); +asn1SccSint ByteStream_GetLength(ByteStream* pStrm); + +#ifdef ASN1SCC_STREAMING + +void fetchData(BitStream* pBitStrm, void* param); +void pushData(BitStream* pBitStrm, void* param); + +void bitstream_fetch_data_if_required(BitStream* pStrm); +void bitstream_push_data_if_required(BitStream* pStrm); + +#else + +#define bitstream_fetch_data_if_required(pStrm) ((void)pStrm) +#define bitstream_push_data_if_required(pStrm) ((void)pStrm) + +#endif + +/* Bit stream functions */ + +void BitStream_AppendNBitZero(BitStream* pBitStrm, int nbits); +void BitStream_EncodeNonNegativeInteger(BitStream* pBitStrm, asn1SccUint v); +flag BitStream_DecodeNonNegativeInteger(BitStream* pBitStrm, asn1SccUint* v, int nBits); +flag BitStream_ReadPartialByte(BitStream* pBitStrm, byte *v, byte nbits); +void BitStream_AppendPartialByte(BitStream* pBitStrm, byte v, byte nbits, flag negate); + +void BitStream_Init(BitStream* pBitStrm, unsigned char* buf, long count); +void BitStream_AttachBuffer(BitStream* pBitStrm, unsigned char* buf, long count); +void BitStream_AppendBit(BitStream* pBitStrm, flag v); +void BitStream_AppendByte(BitStream* pBitStrm, byte v, flag negate); + +asn1SccSint BitStream_GetLength(BitStream* pBitStrm); +flag BitStream_ReadBit(BitStream* pBitStrm, flag* v); +flag BitStream_ReadByte(BitStream* pBitStrm, byte* v); + +/* Integer functions */ +void BitStream_EncodeConstraintPosWholeNumber(BitStream* pBitStrm, asn1SccUint v, asn1SccUint min, asn1SccUint max); + + +flag BitStream_DecodeConstraintPosWholeNumber(BitStream* pBitStrm, asn1SccUint* v, asn1SccUint min, asn1SccUint max); + + + +flag BitStream_DecodeConstraintPosWholeNumberUInt8 (BitStream* pBitStrm, uint8_t* v, uint8_t min, uint8_t max); +flag BitStream_DecodeConstraintPosWholeNumberUInt16(BitStream* pBitStrm, uint16_t* v, uint16_t min, uint16_t max); +flag BitStream_DecodeConstraintPosWholeNumberUInt32(BitStream* pBitStrm, uint32_t* v, uint32_t min, uint32_t max); + + +int GetNumberOfBitsForNonNegativeInteger(asn1SccUint v); + + + + + + + +/* +Checks if the bit pattern is (immediatelly) present in the bit stream. + +bit_terminated_pattern: the bit pattern to check +bit_terminated_pattern_size_in_bits: the size of the bit pattern in bits + +example: the bit pattern 'FFF'H is passed as follows +bit_terminated_pattern (byte[]){0xFF, 0xF0} +bit_terminated_pattern_size_in_bits = 12 + +returns +0 = Error - end of bit stream. The bit stream does not contains at least bit_terminated_pattern_size_in_bits +1 = when bit pattern doesn't match. +2 = when bit pattern matches. +In this case the bit_pattern is consumed (i.e. the currentByte and currentBit are moved) + +*/ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MIDDLEWARE/asn1/asn1crt_encoding_uper.c b/MIDDLEWARE/asn1/asn1crt_encoding_uper.c new file mode 100644 index 00000000..c78cc17a --- /dev/null +++ b/MIDDLEWARE/asn1/asn1crt_encoding_uper.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "asn1crt_encoding_uper.h" + + + + + + + + + + + + + + + + + + diff --git a/MIDDLEWARE/asn1/asn1crt_encoding_uper.h b/MIDDLEWARE/asn1/asn1crt_encoding_uper.h new file mode 100644 index 00000000..25e7f3b5 --- /dev/null +++ b/MIDDLEWARE/asn1/asn1crt_encoding_uper.h @@ -0,0 +1,19 @@ +#ifndef ASN1SCC_ASN1CRT_ENCODING_UPER_H_ +#define ASN1SCC_ASN1CRT_ENCODING_UPER_H_ + +#include "asn1crt_encoding.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/MIDDLEWARE/asn1/bms.c b/MIDDLEWARE/asn1/bms.c new file mode 100644 index 00000000..326ee151 --- /dev/null +++ b/MIDDLEWARE/asn1/bms.c @@ -0,0 +1,963 @@ +/* +Code automatically generated by asn1scc tool +*/ +#include +#include +#include + +#include "asn1crt_encoding.h" +#include "asn1crt_encoding_uper.h" + +#include "bms.h" + +const asn1SccSint lfpIdBMSSystemStatusRequest = 0LL; +const asn1SccSint lfpIdBMSSystemStatusResponse = 1LL; +const asn1SccSint lfpIdBMSPowerStatusRequest = 2LL; +const asn1SccSint lfpIdBMSPowerStatusResponse = 3LL; +const asn1SccSint lfpIdBMSSetHeaterDutyRequest = 4LL; +const asn1SccSint lfpIdBMSSetHeaterDutyResponse = 5LL; +const asn1SccSint lfpIdBMSTemperatureStatusRequest = 6LL; +const asn1SccSint lfpIdBMSTemperatureStatusResponse = 7LL; + +flag BMSADCValue_IsConstraintValid(const BMSADCValue* pVal, int* pErrCode) +{ + flag ret = TRUE; + (void)pVal; + ret = TRUE; + *pErrCode = 0; + + return ret; +} + +void BMSADCValue_Initialize(BMSADCValue* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} + +flag BMSADCValue_Encode(const BMSADCValue* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSADCValue_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)((*(pVal))), 0, 65535); + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSADCValue_Decode(BMSADCValue* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + + ret = BitStream_DecodeConstraintPosWholeNumberUInt16(pBitStrm, pVal, 0, 65535); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSADCVALUE; + + return ret && BMSADCValue_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSCellStatus_IsConstraintValid(const BMSCellStatus* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSADCValue_IsConstraintValid((&(pVal->voltage)), pErrCode); + + return ret; +} + +void BMSCellStatus_Initialize(BMSCellStatus* pVal) +{ + (void)pVal; + + + /*set overvoltage */ + pVal->overvoltage = FALSE; + /*set undervoltage */ + pVal->undervoltage = FALSE; + /*set voltage */ + BMSADCValue_Initialize((&(pVal->voltage))); +} + +flag BMSCellStatus_Encode(const BMSCellStatus* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSCellStatus_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode overvoltage */ + BitStream_AppendBit(pBitStrm,pVal->overvoltage); + if (ret) { + /*Encode undervoltage */ + BitStream_AppendBit(pBitStrm,pVal->undervoltage); + if (ret) { + /*Encode voltage */ + ret = BMSADCValue_Encode((&(pVal->voltage)), pBitStrm, pErrCode, FALSE); + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSCellStatus_Decode(BMSCellStatus* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + + /*Decode overvoltage */ + ret = BitStream_ReadBit(pBitStrm, (&(pVal->overvoltage))); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSCELLSTATUS_OVERVOLTAGE; + if (ret) { + /*Decode undervoltage */ + ret = BitStream_ReadBit(pBitStrm, (&(pVal->undervoltage))); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSCELLSTATUS_UNDERVOLTAGE; + if (ret) { + /*Decode voltage */ + ret = BMSADCValue_Decode((&(pVal->voltage)), pBitStrm, pErrCode); + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + return ret && BMSCellStatus_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSBatteryPackStatus_IsConstraintValid(const BMSBatteryPackStatus* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSCellStatus_IsConstraintValid((&(pVal->cellA)), pErrCode); + if (ret) { + ret = BMSCellStatus_IsConstraintValid((&(pVal->cellB)), pErrCode); + if (ret) { + ret = BMSADCValue_IsConstraintValid((&(pVal->currentDraw)), pErrCode); + if (ret) { + ret = BMSADCValue_IsConstraintValid((&(pVal->currentCharge)), pErrCode); + if (ret) { + ret = BMSADCValue_IsConstraintValid((&(pVal->voltage)), pErrCode); + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + return ret; +} + +void BMSBatteryPackStatus_Initialize(BMSBatteryPackStatus* pVal) +{ + (void)pVal; + + + /*set cellA */ + BMSCellStatus_Initialize((&(pVal->cellA))); + /*set cellB */ + BMSCellStatus_Initialize((&(pVal->cellB))); + /*set currentDraw */ + BMSADCValue_Initialize((&(pVal->currentDraw))); + /*set currentCharge */ + BMSADCValue_Initialize((&(pVal->currentCharge))); + /*set voltage */ + BMSADCValue_Initialize((&(pVal->voltage))); + /*set overcurrent */ + pVal->overcurrent = FALSE; +} + +flag BMSBatteryPackStatus_Encode(const BMSBatteryPackStatus* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSBatteryPackStatus_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode cellA */ + ret = BMSCellStatus_Encode((&(pVal->cellA)), pBitStrm, pErrCode, FALSE); + if (ret) { + /*Encode cellB */ + ret = BMSCellStatus_Encode((&(pVal->cellB)), pBitStrm, pErrCode, FALSE); + if (ret) { + /*Encode currentDraw */ + ret = BMSADCValue_Encode((&(pVal->currentDraw)), pBitStrm, pErrCode, FALSE); + if (ret) { + /*Encode currentCharge */ + ret = BMSADCValue_Encode((&(pVal->currentCharge)), pBitStrm, pErrCode, FALSE); + if (ret) { + /*Encode voltage */ + ret = BMSADCValue_Encode((&(pVal->voltage)), pBitStrm, pErrCode, FALSE); + if (ret) { + /*Encode overcurrent */ + BitStream_AppendBit(pBitStrm,pVal->overcurrent); + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSBatteryPackStatus_Decode(BMSBatteryPackStatus* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + + /*Decode cellA */ + ret = BMSCellStatus_Decode((&(pVal->cellA)), pBitStrm, pErrCode); + if (ret) { + /*Decode cellB */ + ret = BMSCellStatus_Decode((&(pVal->cellB)), pBitStrm, pErrCode); + if (ret) { + /*Decode currentDraw */ + ret = BMSADCValue_Decode((&(pVal->currentDraw)), pBitStrm, pErrCode); + if (ret) { + /*Decode currentCharge */ + ret = BMSADCValue_Decode((&(pVal->currentCharge)), pBitStrm, pErrCode); + if (ret) { + /*Decode voltage */ + ret = BMSADCValue_Decode((&(pVal->voltage)), pBitStrm, pErrCode); + if (ret) { + /*Decode overcurrent */ + ret = BitStream_ReadBit(pBitStrm, (&(pVal->overcurrent))); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_OVERCURRENT; + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + return ret && BMSBatteryPackStatus_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSPowerStatusResponse_IsConstraintValid(const BMSPowerStatusResponse* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSBatteryPackStatus_IsConstraintValid((&(pVal->batteryPack1)), pErrCode); + if (ret) { + ret = BMSBatteryPackStatus_IsConstraintValid((&(pVal->batteryPack2)), pErrCode); + } /*COVERAGE_IGNORE*/ + + return ret; +} + +void BMSPowerStatusResponse_Initialize(BMSPowerStatusResponse* pVal) +{ + (void)pVal; + + + /*set batteryPack1 */ + BMSBatteryPackStatus_Initialize((&(pVal->batteryPack1))); + /*set batteryPack2 */ + BMSBatteryPackStatus_Initialize((&(pVal->batteryPack2))); +} + +flag BMSPowerStatusResponse_Encode(const BMSPowerStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSPowerStatusResponse_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode batteryPack1 */ + ret = BMSBatteryPackStatus_Encode((&(pVal->batteryPack1)), pBitStrm, pErrCode, FALSE); + if (ret) { + /*Encode batteryPack2 */ + ret = BMSBatteryPackStatus_Encode((&(pVal->batteryPack2)), pBitStrm, pErrCode, FALSE); + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSPowerStatusResponse_Decode(BMSPowerStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + + /*Decode batteryPack1 */ + ret = BMSBatteryPackStatus_Decode((&(pVal->batteryPack1)), pBitStrm, pErrCode); + if (ret) { + /*Decode batteryPack2 */ + ret = BMSBatteryPackStatus_Decode((&(pVal->batteryPack2)), pBitStrm, pErrCode); + } /*COVERAGE_IGNORE*/ + + return ret && BMSPowerStatusResponse_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSTemperatureStatusResponse_thermistors_IsConstraintValid(const BMSTemperatureStatusResponse_thermistors* pVal, int* pErrCode) +{ + flag ret = TRUE; + int i1; + for(i1 = 0; ret && i1 < 8; i1++) + { + ret = BMSADCValue_IsConstraintValid((&(pVal->arr[i1])), pErrCode); + } + + return ret; +} + +flag BMSTemperatureStatusResponse_IsConstraintValid(const BMSTemperatureStatusResponse* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSTemperatureStatusResponse_thermistors_IsConstraintValid((&(pVal->thermistors)), pErrCode); + + return ret; +} + +void BMSTemperatureStatusResponse_thermistors_Initialize(BMSTemperatureStatusResponse_thermistors* pVal) +{ + (void)pVal; + + int i1; + + i1 = 0; + while (i1< 8) { + pVal->arr[i1] = 0UL; + i1 = i1 + 1; + } + +} +void BMSTemperatureStatusResponse_Initialize(BMSTemperatureStatusResponse* pVal) +{ + (void)pVal; + + + /*set thermistors */ + BMSTemperatureStatusResponse_thermistors_Initialize((&(pVal->thermistors))); +} + +flag BMSTemperatureStatusResponse_Encode(const BMSTemperatureStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + int i1; + *pErrCode = 0; + ret = bCheckConstraints ? BMSTemperatureStatusResponse_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode thermistors */ + for(i1=0; (i1 < (int)8) && ret; i1++) + { + ret = BMSADCValue_Encode((&(pVal->thermistors.arr[i1])), pBitStrm, pErrCode, FALSE); + } + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSTemperatureStatusResponse_Decode(BMSTemperatureStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + int i1; + + /*Decode thermistors */ + for(i1=0; (i1 < (int)8) && ret; i1++) + { + ret = BMSADCValue_Decode((&(pVal->thermistors.arr[i1])), pBitStrm, pErrCode); + } + + return ret && BMSTemperatureStatusResponse_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSSystemStatusRequest_placeholder_IsConstraintValid(const BMSSystemStatusRequest_placeholder* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) == 0UL); + *pErrCode = ret ? 0 : ERR_BMSSYSTEMSTATUSREQUEST_PLACEHOLDER; + + return ret; +} + +flag BMSSystemStatusRequest_IsConstraintValid(const BMSSystemStatusRequest* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSSystemStatusRequest_placeholder_IsConstraintValid((&(pVal->placeholder)), pErrCode); + + return ret; +} + +void BMSSystemStatusRequest_placeholder_Initialize(BMSSystemStatusRequest_placeholder* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSystemStatusRequest_Initialize(BMSSystemStatusRequest* pVal) +{ + (void)pVal; + + + /*set placeholder */ + BMSSystemStatusRequest_placeholder_Initialize((&(pVal->placeholder))); +} + +flag BMSSystemStatusRequest_Encode(const BMSSystemStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + (void)pBitStrm; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSSystemStatusRequest_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode placeholder */ + /* No need to encode value since it will always be 0UL */ + (void)pBitStrm; + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSSystemStatusRequest_Decode(BMSSystemStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + (void)pBitStrm; + + + /*Decode placeholder */ + pVal->placeholder=0UL; + (void)pBitStrm; + ret = TRUE; + *pErrCode = 0; + + return ret && BMSSystemStatusRequest_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSSystemStatusResponse_version_IsConstraintValid(const BMSSystemStatusResponse_version* pVal, int* pErrCode) +{ + flag ret = TRUE; + (void)pVal; + ret = TRUE; + *pErrCode = 0; + + return ret; +} + +flag BMSSystemStatusResponse_uptime_IsConstraintValid(const BMSSystemStatusResponse_uptime* pVal, int* pErrCode) +{ + flag ret = TRUE; + (void)pVal; + ret = TRUE; + *pErrCode = 0; + + return ret; +} + +flag BMSSystemStatusResponse_IsConstraintValid(const BMSSystemStatusResponse* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSSystemStatusResponse_version_IsConstraintValid((&(pVal->version)), pErrCode); + if (ret) { + ret = BMSSystemStatusResponse_uptime_IsConstraintValid((&(pVal->uptime)), pErrCode); + } /*COVERAGE_IGNORE*/ + + return ret; +} + +void BMSSystemStatusResponse_version_Initialize(BMSSystemStatusResponse_version* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSystemStatusResponse_uptime_Initialize(BMSSystemStatusResponse_uptime* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSystemStatusResponse_Initialize(BMSSystemStatusResponse* pVal) +{ + (void)pVal; + + + /*set version */ + BMSSystemStatusResponse_version_Initialize((&(pVal->version))); + /*set uptime */ + BMSSystemStatusResponse_uptime_Initialize((&(pVal->uptime))); +} + +flag BMSSystemStatusResponse_Encode(const BMSSystemStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSSystemStatusResponse_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode version */ + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)(pVal->version), 0, 255); + if (ret) { + /*Encode uptime */ + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)(pVal->uptime), 0, 4294967295LL); + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSSystemStatusResponse_Decode(BMSSystemStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + + /*Decode version */ + ret = BitStream_DecodeConstraintPosWholeNumberUInt8(pBitStrm, (&(pVal->version)), 0, 255); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSYSTEMSTATUSRESPONSE_VERSION; + if (ret) { + /*Decode uptime */ + ret = BitStream_DecodeConstraintPosWholeNumberUInt32(pBitStrm, (&(pVal->uptime)), 0, 4294967295LL); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSYSTEMSTATUSRESPONSE_UPTIME; + } /*COVERAGE_IGNORE*/ + + return ret && BMSSystemStatusResponse_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSPowerStatusRequest_placeholder_IsConstraintValid(const BMSPowerStatusRequest_placeholder* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) == 0UL); + *pErrCode = ret ? 0 : ERR_BMSPOWERSTATUSREQUEST_PLACEHOLDER; + + return ret; +} + +flag BMSPowerStatusRequest_IsConstraintValid(const BMSPowerStatusRequest* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSPowerStatusRequest_placeholder_IsConstraintValid((&(pVal->placeholder)), pErrCode); + + return ret; +} + +void BMSPowerStatusRequest_placeholder_Initialize(BMSPowerStatusRequest_placeholder* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSPowerStatusRequest_Initialize(BMSPowerStatusRequest* pVal) +{ + (void)pVal; + + + /*set placeholder */ + BMSPowerStatusRequest_placeholder_Initialize((&(pVal->placeholder))); +} + +flag BMSPowerStatusRequest_Encode(const BMSPowerStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + (void)pBitStrm; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSPowerStatusRequest_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode placeholder */ + /* No need to encode value since it will always be 0UL */ + (void)pBitStrm; + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSPowerStatusRequest_Decode(BMSPowerStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + (void)pBitStrm; + + + /*Decode placeholder */ + pVal->placeholder=0UL; + (void)pBitStrm; + ret = TRUE; + *pErrCode = 0; + + return ret && BMSPowerStatusRequest_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSSetHeaterDutyRequest_heater1_IsConstraintValid(const BMSSetHeaterDutyRequest_heater1* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) <= 99UL); + *pErrCode = ret ? 0 : ERR_BMSSETHEATERDUTYREQUEST_HEATER1; + + return ret; +} + +flag BMSSetHeaterDutyRequest_heater2_IsConstraintValid(const BMSSetHeaterDutyRequest_heater2* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) <= 99UL); + *pErrCode = ret ? 0 : ERR_BMSSETHEATERDUTYREQUEST_HEATER2; + + return ret; +} + +flag BMSSetHeaterDutyRequest_heater3_IsConstraintValid(const BMSSetHeaterDutyRequest_heater3* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) <= 99UL); + *pErrCode = ret ? 0 : ERR_BMSSETHEATERDUTYREQUEST_HEATER3; + + return ret; +} + +flag BMSSetHeaterDutyRequest_heater4_IsConstraintValid(const BMSSetHeaterDutyRequest_heater4* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) <= 99UL); + *pErrCode = ret ? 0 : ERR_BMSSETHEATERDUTYREQUEST_HEATER4; + + return ret; +} + +flag BMSSetHeaterDutyRequest_IsConstraintValid(const BMSSetHeaterDutyRequest* pVal, int* pErrCode) +{ + flag ret = TRUE; + if (pVal->exist.heater1) { + ret = BMSSetHeaterDutyRequest_heater1_IsConstraintValid((&(pVal->heater1)), pErrCode); + } + if (ret) { + if (pVal->exist.heater2) { + ret = BMSSetHeaterDutyRequest_heater2_IsConstraintValid((&(pVal->heater2)), pErrCode); + } + if (ret) { + if (pVal->exist.heater3) { + ret = BMSSetHeaterDutyRequest_heater3_IsConstraintValid((&(pVal->heater3)), pErrCode); + } + if (ret) { + if (pVal->exist.heater4) { + ret = BMSSetHeaterDutyRequest_heater4_IsConstraintValid((&(pVal->heater4)), pErrCode); + } + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + return ret; +} + +void BMSSetHeaterDutyRequest_heater1_Initialize(BMSSetHeaterDutyRequest_heater1* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSetHeaterDutyRequest_heater2_Initialize(BMSSetHeaterDutyRequest_heater2* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSetHeaterDutyRequest_heater3_Initialize(BMSSetHeaterDutyRequest_heater3* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSetHeaterDutyRequest_heater4_Initialize(BMSSetHeaterDutyRequest_heater4* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSetHeaterDutyRequest_Initialize(BMSSetHeaterDutyRequest* pVal) +{ + (void)pVal; + + + /*set heater1 */ + pVal->exist.heater1 = 1; + BMSSetHeaterDutyRequest_heater1_Initialize((&(pVal->heater1))); + /*set heater2 */ + pVal->exist.heater2 = 1; + BMSSetHeaterDutyRequest_heater2_Initialize((&(pVal->heater2))); + /*set heater3 */ + pVal->exist.heater3 = 1; + BMSSetHeaterDutyRequest_heater3_Initialize((&(pVal->heater3))); + /*set heater4 */ + pVal->exist.heater4 = 1; + BMSSetHeaterDutyRequest_heater4_Initialize((&(pVal->heater4))); +} + +flag BMSSetHeaterDutyRequest_Encode(const BMSSetHeaterDutyRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSSetHeaterDutyRequest_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + BitStream_AppendBit(pBitStrm,pVal->exist.heater1); + if (ret) { + BitStream_AppendBit(pBitStrm,pVal->exist.heater2); + if (ret) { + BitStream_AppendBit(pBitStrm,pVal->exist.heater3); + if (ret) { + BitStream_AppendBit(pBitStrm,pVal->exist.heater4); + if (ret) { + /*Encode heater1 */ + if (pVal->exist.heater1) { + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)(pVal->heater1), 0, 99); + } + if (ret) { + /*Encode heater2 */ + if (pVal->exist.heater2) { + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)(pVal->heater2), 0, 99); + } + if (ret) { + /*Encode heater3 */ + if (pVal->exist.heater3) { + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)(pVal->heater3), 0, 99); + } + if (ret) { + /*Encode heater4 */ + if (pVal->exist.heater4) { + BitStream_EncodeConstraintPosWholeNumber(pBitStrm, (asn1SccUint)(pVal->heater4), 0, 99); + } + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSSetHeaterDutyRequest_Decode(BMSSetHeaterDutyRequest* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + + flag presenceBit; + + ret = BitStream_ReadBit(pBitStrm, &presenceBit); + pVal->exist.heater1 = presenceBit == 0 ? 0 : 1; + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST; + if (ret) { + ret = BitStream_ReadBit(pBitStrm, &presenceBit); + pVal->exist.heater2 = presenceBit == 0 ? 0 : 1; + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST; + if (ret) { + ret = BitStream_ReadBit(pBitStrm, &presenceBit); + pVal->exist.heater3 = presenceBit == 0 ? 0 : 1; + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST; + if (ret) { + ret = BitStream_ReadBit(pBitStrm, &presenceBit); + pVal->exist.heater4 = presenceBit == 0 ? 0 : 1; + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST; + if (ret) { + /*Decode heater1 */ + if (pVal->exist.heater1) { + ret = BitStream_DecodeConstraintPosWholeNumberUInt8(pBitStrm, (&(pVal->heater1)), 0, 99); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER1; + } + if (ret) { + /*Decode heater2 */ + if (pVal->exist.heater2) { + ret = BitStream_DecodeConstraintPosWholeNumberUInt8(pBitStrm, (&(pVal->heater2)), 0, 99); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER2; + } + if (ret) { + /*Decode heater3 */ + if (pVal->exist.heater3) { + ret = BitStream_DecodeConstraintPosWholeNumberUInt8(pBitStrm, (&(pVal->heater3)), 0, 99); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER3; + } + if (ret) { + /*Decode heater4 */ + if (pVal->exist.heater4) { + ret = BitStream_DecodeConstraintPosWholeNumberUInt8(pBitStrm, (&(pVal->heater4)), 0, 99); + *pErrCode = ret ? 0 : ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER4; + } + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + } /*COVERAGE_IGNORE*/ + + return ret && BMSSetHeaterDutyRequest_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSSetHeaterDutyResponse_placeholder_IsConstraintValid(const BMSSetHeaterDutyResponse_placeholder* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) == 0UL); + *pErrCode = ret ? 0 : ERR_BMSSETHEATERDUTYRESPONSE_PLACEHOLDER; + + return ret; +} + +flag BMSSetHeaterDutyResponse_IsConstraintValid(const BMSSetHeaterDutyResponse* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSSetHeaterDutyResponse_placeholder_IsConstraintValid((&(pVal->placeholder)), pErrCode); + + return ret; +} + +void BMSSetHeaterDutyResponse_placeholder_Initialize(BMSSetHeaterDutyResponse_placeholder* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSSetHeaterDutyResponse_Initialize(BMSSetHeaterDutyResponse* pVal) +{ + (void)pVal; + + + /*set placeholder */ + BMSSetHeaterDutyResponse_placeholder_Initialize((&(pVal->placeholder))); +} + +flag BMSSetHeaterDutyResponse_Encode(const BMSSetHeaterDutyResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + (void)pBitStrm; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSSetHeaterDutyResponse_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode placeholder */ + /* No need to encode value since it will always be 0UL */ + (void)pBitStrm; + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSSetHeaterDutyResponse_Decode(BMSSetHeaterDutyResponse* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + (void)pBitStrm; + + + /*Decode placeholder */ + pVal->placeholder=0UL; + (void)pBitStrm; + ret = TRUE; + *pErrCode = 0; + + return ret && BMSSetHeaterDutyResponse_IsConstraintValid(pVal, pErrCode); +} + + +flag BMSTemperatureStatusRequest_placeholder_IsConstraintValid(const BMSTemperatureStatusRequest_placeholder* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = ((*(pVal)) == 0UL); + *pErrCode = ret ? 0 : ERR_BMSTEMPERATURESTATUSREQUEST_PLACEHOLDER; + + return ret; +} + +flag BMSTemperatureStatusRequest_IsConstraintValid(const BMSTemperatureStatusRequest* pVal, int* pErrCode) +{ + flag ret = TRUE; + ret = BMSTemperatureStatusRequest_placeholder_IsConstraintValid((&(pVal->placeholder)), pErrCode); + + return ret; +} + +void BMSTemperatureStatusRequest_placeholder_Initialize(BMSTemperatureStatusRequest_placeholder* pVal) +{ + (void)pVal; + + + (*(pVal)) = 0UL; +} +void BMSTemperatureStatusRequest_Initialize(BMSTemperatureStatusRequest* pVal) +{ + (void)pVal; + + + /*set placeholder */ + BMSTemperatureStatusRequest_placeholder_Initialize((&(pVal->placeholder))); +} + +flag BMSTemperatureStatusRequest_Encode(const BMSTemperatureStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints) +{ + flag ret = TRUE; + (void)pBitStrm; + + + *pErrCode = 0; + ret = bCheckConstraints ? BMSTemperatureStatusRequest_IsConstraintValid(pVal, pErrCode) : TRUE ; + if (ret && *pErrCode == 0) { + /*Encode placeholder */ + /* No need to encode value since it will always be 0UL */ + (void)pBitStrm; + } /*COVERAGE_IGNORE*/ + + + return ret; +} + +flag BMSTemperatureStatusRequest_Decode(BMSTemperatureStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode) +{ + flag ret = TRUE; + *pErrCode = 0; + (void)pBitStrm; + + + /*Decode placeholder */ + pVal->placeholder=0UL; + (void)pBitStrm; + ret = TRUE; + *pErrCode = 0; + + return ret && BMSTemperatureStatusRequest_IsConstraintValid(pVal, pErrCode); +} + + diff --git a/MIDDLEWARE/asn1/bms.h b/MIDDLEWARE/asn1/bms.h new file mode 100644 index 00000000..b72cde32 --- /dev/null +++ b/MIDDLEWARE/asn1/bms.h @@ -0,0 +1,390 @@ +#ifndef GENERATED_ASN1SCC_bms_H +#define GENERATED_ASN1SCC_bms_H +/* +Code automatically generated by asn1scc tool +*/ +#include "asn1crt.h" +#include "asn1crt_encoding.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef uint16_t BMSADCValue; + + +#define ERR_BMSADCVALUE 1 /*(0..65535)*/ +flag BMSADCValue_IsConstraintValid(const BMSADCValue* pVal, int* pErrCode); + +void BMSADCValue_Initialize(BMSADCValue* pVal); + +#define ERR_UPER_ENCODE_BMSADCVALUE 2 /**/ +#define BMSADCValue_REQUIRED_BYTES_FOR_ENCODING 2 +#define BMSADCValue_REQUIRED_BITS_FOR_ENCODING 16 + +flag BMSADCValue_Encode(const BMSADCValue* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSADCVALUE 3 /**/ +flag BMSADCValue_Decode(BMSADCValue* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSCellStatus --------------------------------------------*/ +typedef struct { + flag overvoltage; + flag undervoltage; + BMSADCValue voltage; + +} BMSCellStatus; + +#define ERR_BMSCELLSTATUS 26 /**/ +#define ERR_BMSCELLSTATUS_OVERVOLTAGE 6 /**/ +#define ERR_BMSCELLSTATUS_UNDERVOLTAGE 11 /**/ +#define ERR_BMSCELLSTATUS_VOLTAGE_2 21 /**/ +flag BMSCellStatus_IsConstraintValid(const BMSCellStatus* pVal, int* pErrCode); + +void BMSCellStatus_Initialize(BMSCellStatus* pVal); + +#define ERR_UPER_ENCODE_BMSCELLSTATUS 27 /**/ +#define ERR_UPER_ENCODE_BMSCELLSTATUS_OVERVOLTAGE 7 /**/ +#define ERR_UPER_ENCODE_BMSCELLSTATUS_UNDERVOLTAGE 12 /**/ +#define ERR_UPER_ENCODE_BMSCELLSTATUS_VOLTAGE_2 22 /**/ +#define BMSCellStatus_REQUIRED_BYTES_FOR_ENCODING 3 +#define BMSCellStatus_REQUIRED_BITS_FOR_ENCODING 18 + +flag BMSCellStatus_Encode(const BMSCellStatus* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSCELLSTATUS 28 /**/ +#define ERR_UPER_DECODE_BMSCELLSTATUS_OVERVOLTAGE 8 /**/ +#define ERR_UPER_DECODE_BMSCELLSTATUS_UNDERVOLTAGE 13 /**/ +#define ERR_UPER_DECODE_BMSCELLSTATUS_VOLTAGE_2 23 /**/ +flag BMSCellStatus_Decode(BMSCellStatus* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSBatteryPackStatus --------------------------------------------*/ +typedef struct { + BMSCellStatus cellA; + BMSCellStatus cellB; + BMSADCValue currentDraw; + BMSADCValue currentCharge; + BMSADCValue voltage; + flag overcurrent; + +} BMSBatteryPackStatus; + +#define ERR_BMSBATTERYPACKSTATUS 76 /**/ +#define ERR_BMSBATTERYPACKSTATUS_CELLA 31 /**/ +#define ERR_BMSBATTERYPACKSTATUS_CELLB 36 /**/ +#define ERR_BMSBATTERYPACKSTATUS_CURRENTDRAW_2 46 /**/ +#define ERR_BMSBATTERYPACKSTATUS_CURRENTCHARGE_2 56 /**/ +#define ERR_BMSBATTERYPACKSTATUS_VOLTAGE_2 66 /**/ +#define ERR_BMSBATTERYPACKSTATUS_OVERCURRENT 71 /**/ +flag BMSBatteryPackStatus_IsConstraintValid(const BMSBatteryPackStatus* pVal, int* pErrCode); + +void BMSBatteryPackStatus_Initialize(BMSBatteryPackStatus* pVal); + +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS 77 /**/ +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS_CELLA 32 /**/ +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS_CELLB 37 /**/ +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS_CURRENTDRAW_2 47 /**/ +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS_CURRENTCHARGE_2 57 /**/ +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS_VOLTAGE_2 67 /**/ +#define ERR_UPER_ENCODE_BMSBATTERYPACKSTATUS_OVERCURRENT 72 /**/ +#define BMSBatteryPackStatus_REQUIRED_BYTES_FOR_ENCODING 11 +#define BMSBatteryPackStatus_REQUIRED_BITS_FOR_ENCODING 85 + +flag BMSBatteryPackStatus_Encode(const BMSBatteryPackStatus* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS 78 /**/ +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_CELLA 33 /**/ +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_CELLB 38 /**/ +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_CURRENTDRAW_2 48 /**/ +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_CURRENTCHARGE_2 58 /**/ +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_VOLTAGE_2 68 /**/ +#define ERR_UPER_DECODE_BMSBATTERYPACKSTATUS_OVERCURRENT 73 /**/ +flag BMSBatteryPackStatus_Decode(BMSBatteryPackStatus* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSPowerStatusResponse --------------------------------------------*/ +typedef struct { + BMSBatteryPackStatus batteryPack1; + BMSBatteryPackStatus batteryPack2; + +} BMSPowerStatusResponse; + +#define ERR_BMSPOWERSTATUSRESPONSE 91 /**/ +#define ERR_BMSPOWERSTATUSRESPONSE_BATTERYPACK1 81 /**/ +#define ERR_BMSPOWERSTATUSRESPONSE_BATTERYPACK2 86 /**/ +flag BMSPowerStatusResponse_IsConstraintValid(const BMSPowerStatusResponse* pVal, int* pErrCode); + +void BMSPowerStatusResponse_Initialize(BMSPowerStatusResponse* pVal); + +#define ERR_UPER_ENCODE_BMSPOWERSTATUSRESPONSE 92 /**/ +#define ERR_UPER_ENCODE_BMSPOWERSTATUSRESPONSE_BATTERYPACK1 82 /**/ +#define ERR_UPER_ENCODE_BMSPOWERSTATUSRESPONSE_BATTERYPACK2 87 /**/ +#define BMSPowerStatusResponse_REQUIRED_BYTES_FOR_ENCODING 22 +#define BMSPowerStatusResponse_REQUIRED_BITS_FOR_ENCODING 170 + +flag BMSPowerStatusResponse_Encode(const BMSPowerStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSPOWERSTATUSRESPONSE 93 /**/ +#define ERR_UPER_DECODE_BMSPOWERSTATUSRESPONSE_BATTERYPACK1 83 /**/ +#define ERR_UPER_DECODE_BMSPOWERSTATUSRESPONSE_BATTERYPACK2 88 /**/ +flag BMSPowerStatusResponse_Decode(BMSPowerStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSTemperatureStatusResponse --------------------------------------------*/ + + +typedef struct { + BMSADCValue arr[8]; +} BMSTemperatureStatusResponse_thermistors; +typedef struct { + BMSTemperatureStatusResponse_thermistors thermistors; + +} BMSTemperatureStatusResponse; + +#define ERR_BMSTEMPERATURESTATUSRESPONSE_THERMISTORS 106 /*SIZE(8)*/ +#define ERR_BMSTEMPERATURESTATUSRESPONSE_THERMISTORS_ELM_2 101 /**/ +flag BMSTemperatureStatusResponse_thermistors_IsConstraintValid(const BMSTemperatureStatusResponse_thermistors* pVal, int* pErrCode); + +#define ERR_BMSTEMPERATURESTATUSRESPONSE 111 /**/ +flag BMSTemperatureStatusResponse_IsConstraintValid(const BMSTemperatureStatusResponse* pVal, int* pErrCode); + +void BMSTemperatureStatusResponse_thermistors_Initialize(BMSTemperatureStatusResponse_thermistors* pVal); +void BMSTemperatureStatusResponse_Initialize(BMSTemperatureStatusResponse* pVal); + +#define ERR_UPER_ENCODE_BMSTEMPERATURESTATUSRESPONSE 112 /**/ +#define ERR_UPER_ENCODE_BMSTEMPERATURESTATUSRESPONSE_THERMISTORS 107 /**/ +#define ERR_UPER_ENCODE_BMSTEMPERATURESTATUSRESPONSE_THERMISTORS_ELM_2 102 /**/ +#define BMSTemperatureStatusResponse_REQUIRED_BYTES_FOR_ENCODING 16 +#define BMSTemperatureStatusResponse_REQUIRED_BITS_FOR_ENCODING 128 + +flag BMSTemperatureStatusResponse_Encode(const BMSTemperatureStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSTEMPERATURESTATUSRESPONSE 113 /**/ +#define ERR_UPER_DECODE_BMSTEMPERATURESTATUSRESPONSE_THERMISTORS 108 /**/ +#define ERR_UPER_DECODE_BMSTEMPERATURESTATUSRESPONSE_THERMISTORS_ELM_2 103 /**/ +flag BMSTemperatureStatusResponse_Decode(BMSTemperatureStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSSystemStatusRequest --------------------------------------------*/ +typedef uint8_t BMSSystemStatusRequest_placeholder; + +typedef struct { + BMSSystemStatusRequest_placeholder placeholder; + +} BMSSystemStatusRequest; + +#define ERR_BMSSYSTEMSTATUSREQUEST_PLACEHOLDER 116 /*(0)*/ +flag BMSSystemStatusRequest_placeholder_IsConstraintValid(const BMSSystemStatusRequest_placeholder* pVal, int* pErrCode); + +#define ERR_BMSSYSTEMSTATUSREQUEST 121 /**/ +flag BMSSystemStatusRequest_IsConstraintValid(const BMSSystemStatusRequest* pVal, int* pErrCode); + +void BMSSystemStatusRequest_placeholder_Initialize(BMSSystemStatusRequest_placeholder* pVal); +void BMSSystemStatusRequest_Initialize(BMSSystemStatusRequest* pVal); + +#define ERR_UPER_ENCODE_BMSSYSTEMSTATUSREQUEST 122 /**/ +#define ERR_UPER_ENCODE_BMSSYSTEMSTATUSREQUEST_PLACEHOLDER 117 /**/ +#define BMSSystemStatusRequest_REQUIRED_BYTES_FOR_ENCODING 0 +#define BMSSystemStatusRequest_REQUIRED_BITS_FOR_ENCODING 0 + +flag BMSSystemStatusRequest_Encode(const BMSSystemStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSSYSTEMSTATUSREQUEST 123 /**/ +#define ERR_UPER_DECODE_BMSSYSTEMSTATUSREQUEST_PLACEHOLDER 118 /**/ +flag BMSSystemStatusRequest_Decode(BMSSystemStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSSystemStatusResponse --------------------------------------------*/ +typedef uint8_t BMSSystemStatusResponse_version; + +typedef uint32_t BMSSystemStatusResponse_uptime; + +typedef struct { + BMSSystemStatusResponse_version version; + BMSSystemStatusResponse_uptime uptime; + +} BMSSystemStatusResponse; + +#define ERR_BMSSYSTEMSTATUSRESPONSE_VERSION 126 /*(0..255)*/ +flag BMSSystemStatusResponse_version_IsConstraintValid(const BMSSystemStatusResponse_version* pVal, int* pErrCode); + +#define ERR_BMSSYSTEMSTATUSRESPONSE_UPTIME 131 /*(0..4294967295)*/ +flag BMSSystemStatusResponse_uptime_IsConstraintValid(const BMSSystemStatusResponse_uptime* pVal, int* pErrCode); + +#define ERR_BMSSYSTEMSTATUSRESPONSE 136 /**/ +flag BMSSystemStatusResponse_IsConstraintValid(const BMSSystemStatusResponse* pVal, int* pErrCode); + +void BMSSystemStatusResponse_version_Initialize(BMSSystemStatusResponse_version* pVal); +void BMSSystemStatusResponse_uptime_Initialize(BMSSystemStatusResponse_uptime* pVal); +void BMSSystemStatusResponse_Initialize(BMSSystemStatusResponse* pVal); + +#define ERR_UPER_ENCODE_BMSSYSTEMSTATUSRESPONSE 137 /**/ +#define ERR_UPER_ENCODE_BMSSYSTEMSTATUSRESPONSE_VERSION 127 /**/ +#define ERR_UPER_ENCODE_BMSSYSTEMSTATUSRESPONSE_UPTIME 132 /**/ +#define BMSSystemStatusResponse_REQUIRED_BYTES_FOR_ENCODING 5 +#define BMSSystemStatusResponse_REQUIRED_BITS_FOR_ENCODING 40 + +flag BMSSystemStatusResponse_Encode(const BMSSystemStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSSYSTEMSTATUSRESPONSE 138 /**/ +#define ERR_UPER_DECODE_BMSSYSTEMSTATUSRESPONSE_VERSION 128 /**/ +#define ERR_UPER_DECODE_BMSSYSTEMSTATUSRESPONSE_UPTIME 133 /**/ +flag BMSSystemStatusResponse_Decode(BMSSystemStatusResponse* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSPowerStatusRequest --------------------------------------------*/ +typedef uint8_t BMSPowerStatusRequest_placeholder; + +typedef struct { + BMSPowerStatusRequest_placeholder placeholder; + +} BMSPowerStatusRequest; + +#define ERR_BMSPOWERSTATUSREQUEST_PLACEHOLDER 141 /*(0)*/ +flag BMSPowerStatusRequest_placeholder_IsConstraintValid(const BMSPowerStatusRequest_placeholder* pVal, int* pErrCode); + +#define ERR_BMSPOWERSTATUSREQUEST 146 /**/ +flag BMSPowerStatusRequest_IsConstraintValid(const BMSPowerStatusRequest* pVal, int* pErrCode); + +void BMSPowerStatusRequest_placeholder_Initialize(BMSPowerStatusRequest_placeholder* pVal); +void BMSPowerStatusRequest_Initialize(BMSPowerStatusRequest* pVal); + +#define ERR_UPER_ENCODE_BMSPOWERSTATUSREQUEST 147 /**/ +#define ERR_UPER_ENCODE_BMSPOWERSTATUSREQUEST_PLACEHOLDER 142 /**/ +#define BMSPowerStatusRequest_REQUIRED_BYTES_FOR_ENCODING 0 +#define BMSPowerStatusRequest_REQUIRED_BITS_FOR_ENCODING 0 + +flag BMSPowerStatusRequest_Encode(const BMSPowerStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSPOWERSTATUSREQUEST 148 /**/ +#define ERR_UPER_DECODE_BMSPOWERSTATUSREQUEST_PLACEHOLDER 143 /**/ +flag BMSPowerStatusRequest_Decode(BMSPowerStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSSetHeaterDutyRequest --------------------------------------------*/ +typedef uint8_t BMSSetHeaterDutyRequest_heater1; + +typedef uint8_t BMSSetHeaterDutyRequest_heater2; + +typedef uint8_t BMSSetHeaterDutyRequest_heater3; + +typedef uint8_t BMSSetHeaterDutyRequest_heater4; + +typedef struct { + unsigned long heater1:1; + unsigned long heater2:1; + unsigned long heater3:1; + unsigned long heater4:1; +} BMSSetHeaterDutyRequest_exist; +typedef struct { + BMSSetHeaterDutyRequest_heater1 heater1; + BMSSetHeaterDutyRequest_heater2 heater2; + BMSSetHeaterDutyRequest_heater3 heater3; + BMSSetHeaterDutyRequest_heater4 heater4; + + BMSSetHeaterDutyRequest_exist exist; + +} BMSSetHeaterDutyRequest; + +#define ERR_BMSSETHEATERDUTYREQUEST_HEATER1 151 /*(0..99)*/ +flag BMSSetHeaterDutyRequest_heater1_IsConstraintValid(const BMSSetHeaterDutyRequest_heater1* pVal, int* pErrCode); + +#define ERR_BMSSETHEATERDUTYREQUEST_HEATER2 156 /*(0..99)*/ +flag BMSSetHeaterDutyRequest_heater2_IsConstraintValid(const BMSSetHeaterDutyRequest_heater2* pVal, int* pErrCode); + +#define ERR_BMSSETHEATERDUTYREQUEST_HEATER3 161 /*(0..99)*/ +flag BMSSetHeaterDutyRequest_heater3_IsConstraintValid(const BMSSetHeaterDutyRequest_heater3* pVal, int* pErrCode); + +#define ERR_BMSSETHEATERDUTYREQUEST_HEATER4 166 /*(0..99)*/ +flag BMSSetHeaterDutyRequest_heater4_IsConstraintValid(const BMSSetHeaterDutyRequest_heater4* pVal, int* pErrCode); + +#define ERR_BMSSETHEATERDUTYREQUEST 171 /**/ +flag BMSSetHeaterDutyRequest_IsConstraintValid(const BMSSetHeaterDutyRequest* pVal, int* pErrCode); + +void BMSSetHeaterDutyRequest_heater1_Initialize(BMSSetHeaterDutyRequest_heater1* pVal); +void BMSSetHeaterDutyRequest_heater2_Initialize(BMSSetHeaterDutyRequest_heater2* pVal); +void BMSSetHeaterDutyRequest_heater3_Initialize(BMSSetHeaterDutyRequest_heater3* pVal); +void BMSSetHeaterDutyRequest_heater4_Initialize(BMSSetHeaterDutyRequest_heater4* pVal); +void BMSSetHeaterDutyRequest_Initialize(BMSSetHeaterDutyRequest* pVal); + +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYREQUEST 172 /**/ +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYREQUEST_HEATER1 152 /**/ +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYREQUEST_HEATER2 157 /**/ +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYREQUEST_HEATER3 162 /**/ +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYREQUEST_HEATER4 167 /**/ +#define BMSSetHeaterDutyRequest_REQUIRED_BYTES_FOR_ENCODING 4 +#define BMSSetHeaterDutyRequest_REQUIRED_BITS_FOR_ENCODING 32 + +flag BMSSetHeaterDutyRequest_Encode(const BMSSetHeaterDutyRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST 173 /**/ +#define ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER1 153 /**/ +#define ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER2 158 /**/ +#define ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER3 163 /**/ +#define ERR_UPER_DECODE_BMSSETHEATERDUTYREQUEST_HEATER4 168 /**/ +flag BMSSetHeaterDutyRequest_Decode(BMSSetHeaterDutyRequest* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSSetHeaterDutyResponse --------------------------------------------*/ +typedef uint8_t BMSSetHeaterDutyResponse_placeholder; + +typedef struct { + BMSSetHeaterDutyResponse_placeholder placeholder; + +} BMSSetHeaterDutyResponse; + +#define ERR_BMSSETHEATERDUTYRESPONSE_PLACEHOLDER 176 /*(0)*/ +flag BMSSetHeaterDutyResponse_placeholder_IsConstraintValid(const BMSSetHeaterDutyResponse_placeholder* pVal, int* pErrCode); + +#define ERR_BMSSETHEATERDUTYRESPONSE 181 /**/ +flag BMSSetHeaterDutyResponse_IsConstraintValid(const BMSSetHeaterDutyResponse* pVal, int* pErrCode); + +void BMSSetHeaterDutyResponse_placeholder_Initialize(BMSSetHeaterDutyResponse_placeholder* pVal); +void BMSSetHeaterDutyResponse_Initialize(BMSSetHeaterDutyResponse* pVal); + +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYRESPONSE 182 /**/ +#define ERR_UPER_ENCODE_BMSSETHEATERDUTYRESPONSE_PLACEHOLDER 177 /**/ +#define BMSSetHeaterDutyResponse_REQUIRED_BYTES_FOR_ENCODING 0 +#define BMSSetHeaterDutyResponse_REQUIRED_BITS_FOR_ENCODING 0 + +flag BMSSetHeaterDutyResponse_Encode(const BMSSetHeaterDutyResponse* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSSETHEATERDUTYRESPONSE 183 /**/ +#define ERR_UPER_DECODE_BMSSETHEATERDUTYRESPONSE_PLACEHOLDER 178 /**/ +flag BMSSetHeaterDutyResponse_Decode(BMSSetHeaterDutyResponse* pVal, BitStream* pBitStrm, int* pErrCode); +/*-- BMSTemperatureStatusRequest --------------------------------------------*/ +typedef uint8_t BMSTemperatureStatusRequest_placeholder; + +typedef struct { + BMSTemperatureStatusRequest_placeholder placeholder; + +} BMSTemperatureStatusRequest; + +#define ERR_BMSTEMPERATURESTATUSREQUEST_PLACEHOLDER 186 /*(0)*/ +flag BMSTemperatureStatusRequest_placeholder_IsConstraintValid(const BMSTemperatureStatusRequest_placeholder* pVal, int* pErrCode); + +#define ERR_BMSTEMPERATURESTATUSREQUEST 191 /**/ +flag BMSTemperatureStatusRequest_IsConstraintValid(const BMSTemperatureStatusRequest* pVal, int* pErrCode); + +void BMSTemperatureStatusRequest_placeholder_Initialize(BMSTemperatureStatusRequest_placeholder* pVal); +void BMSTemperatureStatusRequest_Initialize(BMSTemperatureStatusRequest* pVal); + +#define ERR_UPER_ENCODE_BMSTEMPERATURESTATUSREQUEST 192 /**/ +#define ERR_UPER_ENCODE_BMSTEMPERATURESTATUSREQUEST_PLACEHOLDER 187 /**/ +#define BMSTemperatureStatusRequest_REQUIRED_BYTES_FOR_ENCODING 0 +#define BMSTemperatureStatusRequest_REQUIRED_BITS_FOR_ENCODING 0 + +flag BMSTemperatureStatusRequest_Encode(const BMSTemperatureStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode, flag bCheckConstraints); + +#define ERR_UPER_DECODE_BMSTEMPERATURESTATUSREQUEST 193 /**/ +#define ERR_UPER_DECODE_BMSTEMPERATURESTATUSREQUEST_PLACEHOLDER 188 /**/ +flag BMSTemperatureStatusRequest_Decode(BMSTemperatureStatusRequest* pVal, BitStream* pBitStrm, int* pErrCode); + +extern const asn1SccSint lfpIdBMSSystemStatusRequest; +extern const asn1SccSint lfpIdBMSSystemStatusResponse; +extern const asn1SccSint lfpIdBMSPowerStatusRequest; +extern const asn1SccSint lfpIdBMSPowerStatusResponse; +extern const asn1SccSint lfpIdBMSSetHeaterDutyRequest; +extern const asn1SccSint lfpIdBMSSetHeaterDutyResponse; +extern const asn1SccSint lfpIdBMSTemperatureStatusRequest; +extern const asn1SccSint lfpIdBMSTemperatureStatusResponse; + +/* ================= Encoding/Decoding function prototypes ================= + * These functions are placed at the end of the file to make sure all types + * have been declared first, in case of parameterized ACN encodings + * ========================================================================= */ + + + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/MIDDLEWARE/tinyprotocol/CMakeLists.txt b/MIDDLEWARE/tinyprotocol/CMakeLists.txt index 5f776789..991be683 100644 --- a/MIDDLEWARE/tinyprotocol/CMakeLists.txt +++ b/MIDDLEWARE/tinyprotocol/CMakeLists.txt @@ -1,12 +1,5 @@ -add_library(TINYPROTOCOL) +zephyr_library_named(tinyprotocol) -target_sources( - TINYPROTOCOL - PRIVATE - tinyprotocol.c - PUBLIC - FILE_SET HEADERS - BASE_DIRS . - FILES - tinyprotocol.h -) \ No newline at end of file +zephyr_library_sources(src/tinyprotocol.c) + +zephyr_library_include_directories(include) diff --git a/ProjectFiles/BMS/.cproject b/ProjectFiles/BMS/.cproject index ea189c81..e340cd41 100644 --- a/ProjectFiles/BMS/.cproject +++ b/ProjectFiles/BMS/.cproject @@ -17,8 +17,8 @@ - - - + diff --git a/ProjectFiles/BMS/.project b/ProjectFiles/BMS/.project index 1a46a3da..de04eba2 100644 --- a/ProjectFiles/BMS/.project +++ b/ProjectFiles/BMS/.project @@ -65,6 +65,16 @@ 2 virtual:/virtual + + MIDDLEWARE/ASN1SCC + 2 + PARENT-2-PROJECT_LOC/MIDDLEWARE/ASN1SCC + + + MIDDLEWARE/LFP + 2 + PARENT-2-PROJECT_LOC/MIDDLEWARE/LFP + MIDDLEWARE/MRAM 2 @@ -80,6 +90,16 @@ 2 virtual:/virtual + + MIDDLEWARE/asn1 + 2 + PARENT-2-PROJECT_LOC/MIDDLEWARE/asn1 + + + MIDDLEWARE/shared_types + 2 + PARENT-2-PROJECT_LOC/MIDDLEWARE/shared_types + MIDDLEWARE/tinyprotocol 2 diff --git a/ProjectFiles/BMS/.settings/org.eclipse.core.resources.prefs b/ProjectFiles/BMS/.settings/org.eclipse.core.resources.prefs index 8b06942f..933edb80 100644 --- a/ProjectFiles/BMS/.settings/org.eclipse.core.resources.prefs +++ b/ProjectFiles/BMS/.settings/org.eclipse.core.resources.prefs @@ -23,6 +23,12 @@ encoding//Debug/DRIVERS/MSP430/UTILS/subdir_rules.mk=UTF-8 encoding//Debug/DRIVERS/MSP430/UTILS/subdir_vars.mk=UTF-8 encoding//Debug/MIDDLEWARE/ADS7138/subdir_rules.mk=UTF-8 encoding//Debug/MIDDLEWARE/ADS7138/subdir_vars.mk=UTF-8 +encoding//Debug/MIDDLEWARE/ASN1SCC/subdir_rules.mk=UTF-8 +encoding//Debug/MIDDLEWARE/ASN1SCC/subdir_vars.mk=UTF-8 +encoding//Debug/MIDDLEWARE/LFP/subdir_rules.mk=UTF-8 +encoding//Debug/MIDDLEWARE/LFP/subdir_vars.mk=UTF-8 +encoding//Debug/MIDDLEWARE/asn1/subdir_rules.mk=UTF-8 +encoding//Debug/MIDDLEWARE/asn1/subdir_vars.mk=UTF-8 encoding//Debug/MIDDLEWARE/tinyprotocol/subdir_rules.mk=UTF-8 encoding//Debug/MIDDLEWARE/tinyprotocol/subdir_vars.mk=UTF-8 encoding//Debug/makefile=UTF-8 diff --git a/ProjectFiles/BMS/.theia/launch.json b/ProjectFiles/BMS/.theia/launch.json index 3642da95..57abfade 100644 --- a/ProjectFiles/BMS/.theia/launch.json +++ b/ProjectFiles/BMS/.theia/launch.json @@ -35,12 +35,47 @@ { "name": "MSP430", "debuggerSettings": { - "data": "\n\n\n \n 1\n \n\n \n 1\n \n\n \n 1\n \n\n \n 1\n \n\n \n 1\n \n\n \n 1\n \n\n \n 0\n \n\n \n 0\n \n\n \n 0\n \n\n \n 1\n \n\n \n 0\n \n\n \n 0\n \n\n \n 4400\n \n\n \n 13fff\n \n\n\n" + "data": "\n\n" + } + } + ] + }, + { + "name": "TI MSP430 USB1", + "cores": [ + { + "name": "MSP430", + "debuggerSettings": { + "data": "\n\n" + } + } + ] + }, + { + "name": "TI MSP430 USB2_0", + "cores": [ + { + "name": "MSP430", + "debuggerSettings": { + "data": "\n\n" } } ] } - ] + ], + "debuggerSettings": { + "targetConfigs/MSP430FR5969.ccxml": { + "TI MSP430 USB1_0/MSP430": { + "data": "\n\n" + }, + "TI MSP430 USB2_0/MSP430": { + "data": "\n\n" + }, + "TI MSP430 USB3_0/MSP430": { + "data": "\n\n" + } + } + } } ] -} \ No newline at end of file +} diff --git a/ProjectFiles/BMS/targetConfigs/MSP430FR5969.ccxml b/ProjectFiles/BMS/targetConfigs/MSP430FR5969.ccxml index cdf13812..a20f1f7f 100644 --- a/ProjectFiles/BMS/targetConfigs/MSP430FR5969.ccxml +++ b/ProjectFiles/BMS/targetConfigs/MSP430FR5969.ccxml @@ -1,11 +1,12 @@ - - - + + + + - + diff --git a/Tools/BMSTinyProtocolPicoMaster/sketch_mar15a/sketch_mar15a.ino b/Tools/BMSTinyProtocolPicoMaster/sketch_mar15a/sketch_mar15a.ino index 35abac24..0132305c 100644 --- a/Tools/BMSTinyProtocolPicoMaster/sketch_mar15a/sketch_mar15a.ino +++ b/Tools/BMSTinyProtocolPicoMaster/sketch_mar15a/sketch_mar15a.ino @@ -10,6 +10,8 @@ const static uint8_t crc_init_value = 0xFF; // Value XORed to the final register before the CRC is returned const static uint8_t crc_xor_value = 0xFF; +#define BMS_SLAVE_ADDR 0x09 + // Pre-computed AUTOSAR CRC8 table const static uint8_t crc_lookup_table[256] = { 0x00, 0x2F, 0x5E, 0x71, 0xBC, 0x93, 0xE2, 0xCD, 0x57, 0x78, 0x09, 0x26, 0xEB, 0xC4, 0xB5, 0x9A, @@ -65,7 +67,7 @@ void sendTeleCommand(uint8_t cmd_id, const uint8_t* buff, uint8_t size) cpy[0] = cmd_id; memcpy(&cpy[1], buff, size); const uint8_t crc = TINYPROTOCOL_CalculateCRC(cpy, size + 1); - Wire.beginTransmission(0x08); + Wire.beginTransmission(BMS_SLAVE_ADDR); Wire.write(0x9b); // MAGIC Serial.print("Sending CMD: "); Serial.println(cmd_id, HEX); @@ -172,7 +174,7 @@ void requestADC() { void sendTeleChannelRequest(uint8_t channel_id, uint8_t* buff, size_t len) { // Begin transmission to slave at address 0x08 - Wire.beginTransmission(0x08); + Wire.beginTransmission(BMS_SLAVE_ADDR); Wire.write(0x9b); // MAGIC // FIXME: This is really stupid, this function should definitely expect unaltered channel_id/ @@ -193,7 +195,7 @@ void sendTeleChannelRequest(uint8_t channel_id, uint8_t* buff, size_t len) { // Serial.println("ACK!"); } - Wire.requestFrom(0x8, len, true); // read + Wire.requestFrom(BMS_SLAVE_ADDR, len, true); // read for (size_t i = 0; i < len; i++) { buff[i] = Wire.read(); } @@ -238,12 +240,12 @@ void setup() { void loop() { requestADC(); // Send command and read data - delay(10); - requestFlags(); - delay(10); - getExtADC(); - delay(10); - sendPWMData(); + // delay(10); + // requestFlags(); + // delay(10); + // getExtADC(); + // delay(10); + // sendPWMData(); delay(1000); // Wait 1 second before repeating } diff --git a/Tools/ads7138_emulator/ads7138_emulator.ino b/Tools/ads7138_emulator/ads7138_emulator.ino new file mode 100644 index 00000000..d3650f21 --- /dev/null +++ b/Tools/ads7138_emulator/ads7138_emulator.ino @@ -0,0 +1,224 @@ +#include +#include "pico/stdlib.h" +#include "hardware/timer.h" + +#define ADS7138_ADDR 0x10 +#define REG_SYSTEM_STATUS 0x00 +#define REG_CHANNEL_SEL 0x11 + +// Opcodes (subset) +#define OPCODE_WRITE_SINGLE 0x08 +#define OPCODE_READ_SINGLE 0x10 +#define OPCODE_GENERAL_CMD 0x00 // NOP in our stub + +// Simple register map (0x00–0x1F is enough for this stub) +uint8_t regs[0x20]; +uint16_t channels[8]; + +// --- Configuration --- +const uint8_t PWM_IN_PIN = 15; // GP15 +const uint8_t LED_PIN = 25; // Built-in LED +const int INTERVAL_MS = 50; // Run simulation every 50ms + +// --- Thermistor Simulation Constants --- +// Adjust these to match the hardware you will eventually install +const float THERMISTOR_NOMINAL = 10000; // Resistance at 25 degrees C (10k) +const float TEMPERATURE_NOMINAL = 25; // Temp. for nominal resistance (almost always 25 C) +const float BETA_COEFFICIENT = 3950; // The beta coefficient of the thermistor +const float SERIES_RESISTOR = 10000; // The value of the 'other' resistor in the divider (10k) + +// --- Global Simulation Variables --- +volatile float temperature = 20.0; + +// State for next I2C read +volatile bool nextIsRegRead = false; +volatile uint8_t currentReg = 0; +volatile uint8_t currentChan = 0; // 0–7, manual mode + +struct repeating_timer timer; + +// Dummy ADC values per channel (12-bit) +uint16_t dummyValueForChannel(uint8_t ch) { + ch &= 0x07; + // 0x000, 0x111, 0x222, ... 0x777 (all fit in 12 bits) + return (uint16_t)(ch * 0x111) & 0x0FFF; +} + +uint8_t readRegister(uint8_t reg) { + if (reg == REG_SYSTEM_STATUS) { + // Reset value from datasheet snippet: 0x81 + return 0x81; + } + if (reg < sizeof(regs)) { + return regs[reg]; + } + return 0x00; // undefined regs -> 0 +} + +void writeRegister(uint8_t reg, uint8_t value) { + if (reg == REG_SYSTEM_STATUS) { + // Read-only in this stub + return; + } + if (reg < sizeof(regs)) { + regs[reg] = value; + } + if (reg == REG_CHANNEL_SEL) { + currentChan = value & 0x07; // MANUAL_CHID low 3 bits + } +} + +// Called when master sends data to us +void onReceiveHandler(int len) { + if (len <= 0) return; + + uint8_t first = Wire.read(); + len--; + + // Default: assume next read is a conversion read + nextIsRegRead = false; + + if (first == OPCODE_GENERAL_CMD) { + // General command 0x00 -> just ACK & ignore + return; + } + + if (first == OPCODE_WRITE_SINGLE && len >= 2) { + uint8_t reg = Wire.read(); + uint8_t data = Wire.read(); + writeRegister(reg, data); + return; + } + + if (first == OPCODE_READ_SINGLE && len >= 1) { + currentReg = Wire.read(); + nextIsRegRead = true; + return; + } + + // Fallback: treat first byte as register address (no-opcode style) + currentReg = first; + nextIsRegRead = true; + + // If there's another byte, treat it as a plain write (reg, data) + if (len >= 1) { + uint8_t data = Wire.read(); + writeRegister(currentReg, data); + } +} + +// Called when master requests data from us +void onRequestHandler() { + if (nextIsRegRead) { + uint8_t val = readRegister(currentReg); + Wire.write(val); + } else { + uint16_t val = channels[currentChan]; + // uint16_t val = dummyValueForChannel(currentChan); + + // 12-bit value left-aligned into two bytes: D11..D4, D3..D0 xxxx + uint8_t msb = (val >> 4) & 0xFF; + uint8_t lsb = (val << 4) & 0xF0; + Wire.write(msb); + Wire.write(lsb); + } +} + +bool isHeatingActive() { + return digitalRead(PWM_IN_PIN) == HIGH; +} + +// --- Helper: Convert Temp to Simulated ADC Value --- +// This reverses the standard thermistor reading logic. +// Returns a value 0-4095 (12-bit ADC) +uint16_t temperatureToADC(float tempC) { + // 1. Convert Celsius to Kelvin + float tempK = tempC + 273.15; + float tempRefK = TEMPERATURE_NOMINAL + 273.15; + + // 2. Calculate Thermistor Resistance (Steinhart-Hart / Beta equation) + // R = R0 * exp(B * (1/T - 1/T0)) + float resistance = THERMISTOR_NOMINAL * exp(BETA_COEFFICIENT * (1.0/tempK - 1.0/tempRefK)); + + // 3. Simulate Voltage Divider (Vcc -> SeriesR -> [ADC] -> Thermistor -> GND) + // This is the most common config. + // Voltage Fraction = R_therm / (R_series + R_therm) + float voltageFraction = resistance / (SERIES_RESISTOR + resistance); + + // 4. Convert to 12-bit ADC value (0-4095) + float adcVal = voltageFraction * 4095.0; + + // Clamp values + if (adcVal > 4095) return 4095; + if (adcVal < 0) return 0; + return (uint16_t)adcVal; +} + +// --- Timer Interrupt Service Routine (ISR) --- +bool timer_callback(struct repeating_timer *t) { + // Determine heating vs cooling + // Simple simulation: HIGH = Heating, LOW = Cooling + if (digitalRead(PWM_IN_PIN) == HIGH) { + temperature += 0.1; + // Serial.println("Got pwm data"); + } else { + temperature -= 0.05; + } + + // Safety bounds for simulation physics + if (temperature < -200) temperature = -200; + if (temperature > 500) temperature = 500; + + return true; +} + +void setup() { + pinMode(PWM_IN_PIN, INPUT); + + add_repeating_timer_ms(-INTERVAL_MS, timer_callback, NULL, &timer); + + // Initialize minimal register defaults + for (uint8_t i = 0; i < sizeof(regs); ++i) { + regs[i] = 0x00; + } + regs[REG_SYSTEM_STATUS] = 0x81; + regs[REG_CHANNEL_SEL] = 0x00; + currentChan = 0; + + Wire.setSDA(4); + Wire.setSCL(5); + Wire.begin(ADS7138_ADDR); // I2C slave at 0x10 + Wire.onReceive(onReceiveHandler); + Wire.onRequest(onRequestHandler); + + // Enable general call ACK (address 0x00) on AVR-based boards +#if defined(TWAR) + TWAR |= 0x01; // Set TWGCE bit: respond to general call address 0x00 +#endif +} + +void loop() { + static unsigned long lastPrint = 0; + + // Update data output every 100ms + if (millis() - lastPrint > 100) { + lastPrint = millis(); + + // Grab a snapshot of the current physics state + float currentTemp = temperature; + + // Calculate the simulated ADC value + // (This is the value you would send to your master board) + uint16_t simulatedADC = temperatureToADC(currentTemp); + // For now we'll just assume the temperature of all the batteries is the same everywhere + for (int i = 0; i < 8; i++) { + channels[i] = simulatedADC; + } + + Serial.println(temperature); + + + // Visual heartbeat + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); + } +}