|
|
@@ -0,0 +1,118 @@
|
|
|
+/*
|
|
|
+References: https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c
|
|
|
+
|
|
|
+*/
|
|
|
+
|
|
|
+#include "src/battery_data/battery.h"
|
|
|
+#include "src/peripherals/dac/dac.h"
|
|
|
+#include "src/interfaces/mcu_slave_interface.h"
|
|
|
+#include "ti/driverlib/dl_i2c.h"
|
|
|
+#include "ti_msp_dl_config.h"
|
|
|
+#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+/*Function to Rx and Tx data from Target to Controller*/
|
|
|
+// The code has multiple i2c instances (multiple MCUs connected) from which we
|
|
|
+// need to select the right one, passing a pointer as an argument
|
|
|
+
|
|
|
+void mcu_i2c_handle(I2C_Regs *i2c) {
|
|
|
+ printf("MCU interrupt triggered\n");
|
|
|
+ uint8_t receivedCommand = DL_I2C_receiveTargetData(i2c);
|
|
|
+ printf("[SLAVE] Received Command: 0x%02X\n", receivedCommand);
|
|
|
+ uint8_t tx_buffer[10] = {0};
|
|
|
+ //changed to volatile variable, so that the compiler cannot optimize the variable out and is forced to do as told by the code
|
|
|
+ volatile uint8_t rx_buffer[10] = {0};
|
|
|
+ /*Handling GET commands with bitmasking*/
|
|
|
+ // GET command for ADC(Battery Measurement): Voltage, Current, Temperature
|
|
|
+ if ((receivedCommand & 0xF0) == 0x60) {
|
|
|
+ uint8_t slot = receivedCommand & 0x0F;
|
|
|
+ if (slot > NUM_SLOTS) {
|
|
|
+ DL_I2C_flushTargetTXFIFO(i2c);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Struct for voltage, current and temperature
|
|
|
+ BatteryMeasurementData battery_measure;
|
|
|
+ // Pointer pointing to the address of the requested battery slot:
|
|
|
+ Battery *battery = &batteries[slot];
|
|
|
+ // take the updated battery measurement from the battery struct and store it
|
|
|
+ // in the battery_measure struct
|
|
|
+ battery_measure.voltage = battery->voltage;
|
|
|
+ battery_measure.current = battery->current;
|
|
|
+ battery_measure.temperature = battery->temperature;
|
|
|
+ // Copying the memory block from battery_measure struct to tx_buffer:
|
|
|
+ memcpy(tx_buffer, &battery_measure, sizeof(battery_measure));
|
|
|
+ DL_I2C_fillTargetTXFIFO(i2c, tx_buffer, sizeof(BatteryMeasurementData));
|
|
|
+ printf("Battery Measurement Sent to MCU. \n");
|
|
|
+ DL_I2C_flushTargetTXFIFO(i2c);
|
|
|
+ }
|
|
|
+ // GET command for Battery Discharge State: 0x00, 0x01, 0x02, 0x03
|
|
|
+ else if ((receivedCommand & 0xF0) == 0x70) {
|
|
|
+ uint8_t slot = receivedCommand & 0x0F;
|
|
|
+ if (slot > NUM_SLOTS) {
|
|
|
+ DL_I2C_flushTargetTXFIFO(i2c);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Battery *battery = &batteries[slot];
|
|
|
+ uint8_t discharge_state = battery->condition;
|
|
|
+ DL_I2C_fillTargetTXFIFO(i2c, &discharge_state, 1);
|
|
|
+ while (DL_I2C_transmitTargetDataCheck(i2c, 0x00) != false)
|
|
|
+ ;
|
|
|
+
|
|
|
+ } else{
|
|
|
+ switch(receivedCommand){
|
|
|
+ case CMD_SET_CURRENT:{
|
|
|
+ SetChargeDischargeCurrent set_current;
|
|
|
+ uint8_t rx_index= 0;
|
|
|
+ while(rx_index < sizeof(SetChargeDischargeCurrent)){
|
|
|
+ if(!DL_I2C_isTargetRXFIFOEmpty(i2c)){
|
|
|
+ rx_buffer[rx_index]= DL_I2C_receiveTargetData(i2c);
|
|
|
+ rx_index++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(rx_index != sizeof(SetChargeDischargeCurrent)){
|
|
|
+ printf("[MCU target]: Set Charging Current: Incomplete Data.\n");
|
|
|
+ DL_I2C_flushTargetRXFIFO(i2c);
|
|
|
+ rx_index= 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ memcpy(&set_current, (const uint8_t *)rx_buffer, sizeof(SetChargeDischargeCurrent));
|
|
|
+ if (set_current.slot_id < NUM_SLOTS) {
|
|
|
+ Battery *battery = &batteries[set_current.slot_id];
|
|
|
+ battery->charge_discharge_current = set_current.current;
|
|
|
+ // printf("Charge Current:%u\n", battery->charge_discharge_current);
|
|
|
+ }
|
|
|
+ uint8_t slot = set_current.slot_id;
|
|
|
+ int16_t current = set_current.current;
|
|
|
+ printf("Slot id: %d, Current: %d\n", slot, current);
|
|
|
+ if (current > 0) {
|
|
|
+ // Calibrate charge current for DAC, different slots will have different
|
|
|
+ // channels, how to handle that?-> ans: with slot_id, since each slots
|
|
|
+ // will be connected to each channels of the same DAC, address is same
|
|
|
+ // channels change
|
|
|
+ DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
|
|
|
+ DAC_SingleWrite(current);
|
|
|
+ } else if (current < 0) {
|
|
|
+ // Calibrate discharge current for PWM
|
|
|
+ // TODO: PWM function develop
|
|
|
+ printf("PWM Discharge");
|
|
|
+ } else {
|
|
|
+ // do nothing, charge or discharge
|
|
|
+ printf("state is idle");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CMD_SET_HOV_CLEAR:{
|
|
|
+ uint8_t slot = DL_I2C_receiveTargetDataBlocking(i2c);
|
|
|
+ /*if (slot >= NUM_SLOTS) {
|
|
|
+ }*/
|
|
|
+ Battery *battery = &batteries[slot];
|
|
|
+ // clear hov state flag to false:
|
|
|
+ battery->pwm_hov_state = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|