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));
+ }
+}