Explorar el Código

Code for MCU acting as a target for the MCU controller- tested with Pi for ADC and DAC

namrota ghosh hace 8 meses
padre
commit
af1638e7ef
Se han modificado 2 ficheros con 126 adiciones y 2 borrados
  1. 5 2
      src/interfaces/mcu_slave_interface.h
  2. 121 0
      src/mcu_slave.c

+ 5 - 2
src/interfaces/mcu_slave_interface.h

@@ -2,13 +2,15 @@
 
 #ifndef MCU_SLAVE_INTERACE_H_
 #include <stdint.h>
+#include "ti/driverlib/dl_i2c.h"
+#include "ti_msp_dl_config.h"
 
 // Handles I2C command coming into Target MCU:
 
 typedef enum{
     CMD_SET_CURRENT= 0x05,
-    CMD_GET_MEASUREMENT= 0x06,
-    CMD_GET_BATTERY_STATE= 0x07,
+    CMD_GET_MEASUREMENT= 0x06, 
+    CMD_GET_BATTERY_STATE= 0x07, 
     CMD_SET_HOV_CLEAR= 0x08
 }mcu_I2C_command;
 
@@ -24,4 +26,5 @@ typedef struct{
     uint16_t temperature;
 }BatteryMeasurementData;
 
+void mcu_i2c_handle(I2C_Regs *i2c);
 #endif

+ 121 - 0
src/mcu_slave.c

@@ -0,0 +1,121 @@
+/*
+References: https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c
+
+*/
+
+
+#include "battery.h"
+#include "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 if (receivedCommand == CMD_SET_CURRENT) {
+    SetChargeDischargeCurrent set_current;
+    // Read incoming bytes from the Controller:
+    uint8_t rx_index = 0;
+    while (rx_index < sizeof(SetChargeDischargeCurrent)) {
+    //TODO: Need to have a workaround, currently the code is getting stuck on the first trigger and provides result on the second trigger    
+    if (!DL_I2C_isTargetRXFIFOEmpty(i2c)) {
+        rx_buffer[rx_index] = DL_I2C_receiveTargetData(i2c);
+        //printf("Received Bytes[%d]: 0x%02X\n", rx_index, rx_buffer[rx_index]);
+        rx_index++;
+    }
+    }
+    // printf("index:%d\n", rx_index);
+    // Byte array received from the Controller will be typecasted to (const
+    // uint8_t *), treats the rx_buffer as an array of READ ONLY bytes because
+    // of the const
+    if (rx_index != sizeof(SetChargeDischargeCurrent)) {
+      printf("ERROR: Incomplete I2C Rx: received %d%zu bytes\n", rx_index,
+             sizeof(SetChargeDischargeCurrent));
+      DL_I2C_flushTargetRXFIFO(i2c);
+      rx_index = 0;
+      return;
+    }
+
+    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");
+    }
+
+  } else if (receivedCommand == 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;
+  }
+}