|
|
@@ -23,7 +23,6 @@
|
|
|
DAC function to write to Channel A in Fast Mode and return the Analog output
|
|
|
*/
|
|
|
|
|
|
-
|
|
|
#include "i2c_target.h"
|
|
|
#include "ti/devices/msp/peripherals/hw_dac12.h"
|
|
|
#include "ti/driverlib/dl_adc12.h"
|
|
|
@@ -34,11 +33,13 @@
|
|
|
#include "ti/comm_modules/i2c/controller/i2c_comm_controller.h"
|
|
|
#include <stdint.h>
|
|
|
#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
#include "multiplexer.h"
|
|
|
#include "adc.h"
|
|
|
#include "dac.h"
|
|
|
#include "battery.h"
|
|
|
#include "i2c_target.h"
|
|
|
+#include "cc_cv_charging.h"
|
|
|
|
|
|
I2C_Instance gI2C;
|
|
|
I2C_ResponseInfo gResponse;
|
|
|
@@ -201,11 +202,12 @@ void I2C_controller_INST_IRQHandler(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**** Interrupt for Pi to MCU ****/
|
|
|
+
|
|
|
void I2C_target_INST_IRQHandler(void) {
|
|
|
|
|
|
//printf("I2C Interrupt Triggered to MCU (TARGET)!\n");
|
|
|
- static uint8_t receivedCommand= 0;
|
|
|
- static uint8_t requestedSlot= 0;
|
|
|
+ uint8_t receivedCommand= 0;
|
|
|
uint32_t status = DL_I2C_getPendingInterrupt(I2C_target_INST);
|
|
|
//ADC_PARAMS params;
|
|
|
switch (status) {
|
|
|
@@ -222,66 +224,147 @@ void I2C_target_INST_IRQHandler(void) {
|
|
|
case DL_I2C_IIDX_TARGET_STOP:
|
|
|
piTxComplete= true;
|
|
|
piRxComplete = true;
|
|
|
- printf("I2C Stop Detected- Rx/Tx Complete");
|
|
|
break;
|
|
|
|
|
|
/* TX FIFO trigger (Pi is reading data from MCU) */
|
|
|
+ /*TXFIFO to GET battery status is triggered when command is 0x01
|
|
|
+ - Pi on request of 0x01 will get a response of the battery status for all the slots
|
|
|
+ - Battery_StateUpdate function is called, which in turn calls the Battery_ReadState funtion to set the state of the batteries
|
|
|
+ -Pi on command of [0x02, slot_id] will GET the 'Battery Data' which is voltage, current and temperature for a given slot.
|
|
|
+ - MCU reads the slot_id from Pi using DL_I2C_receiveTargetData()
|
|
|
+ - piTxCount is set to 0
|
|
|
+ - piTxLen is the sizeof BatteryData struct which is 7 bytes
|
|
|
+ - If the requested slot is correct then:
|
|
|
+ - battery pointer variable points to the memory of the requested slot
|
|
|
+ - the values of voltage, current and temperature are then stored in battery_data struct
|
|
|
+ - Once the values are in BatteryData struct we wait for the bus to be free
|
|
|
+ - Next we send the BatteryData to Pi using DL_I2C_fillTargetTXFIFO()
|
|
|
+ - Reset the TX counter for the next data.
|
|
|
+ */
|
|
|
case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
|
|
|
- printf("Tx PI triggered!\n");
|
|
|
- if (receivedCommand == CMD_GET_BATTERY_STATUS){
|
|
|
- printf("Battery Status\n");
|
|
|
- Battery_StateUpdate();
|
|
|
- uint8_t battery_slots_status[NUM_SLOTS];
|
|
|
- for(uint8_t slot= 0; slot< NUM_SLOTS; slot++){
|
|
|
- battery_slots_status[slot]= batteries[slot].state;
|
|
|
+ printf("TX to PI triggered!\n");
|
|
|
+ if(!DL_I2C_isTargetTXFIFOEmpty(I2C_target_INST)){
|
|
|
+ receivedCommand= DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ printf("Received Command: 0x%02X\n", receivedCommand);
|
|
|
+
|
|
|
+ if (receivedCommand == CMD_GET_BATTERY_STATUS){
|
|
|
+ printf("Battery status received.\n");
|
|
|
+ Battery_StateUpdate();
|
|
|
+ if(piTxCount < piTxLen){
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
|
|
|
+ DL_I2C_fillTargetTXFIFO(I2C_target_INST, &piTxPacket[piTxCount], 1);
|
|
|
+ piTxCount++;
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ /*
|
|
|
+ * Fill FIFO with 0x00 if more data is requested than expected piTxLen
|
|
|
+ */
|
|
|
+ while (
|
|
|
+ DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false);
|
|
|
+ }
|
|
|
}
|
|
|
- DL_I2C_fillTargetTXFIFO(I2C_target_INST, battery_slots_status, NUM_SLOTS);
|
|
|
- while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
|
|
|
+ else if (receivedCommand == CMD_GET_BATTERY_DATA){
|
|
|
|
|
|
- }
|
|
|
- else if (receivedCommand == CMD_GET_BATTERY_DATA){
|
|
|
- printf("Battery Data!\n");
|
|
|
- piTxCount= 0;
|
|
|
- piTxComplete= false;
|
|
|
- if(requestedSlot < NUM_SLOTS){
|
|
|
- BatteryData battery_data;
|
|
|
- battery_data.slot_id= requestedSlot;
|
|
|
- battery_data.voltage= batteries[requestedSlot].voltage;
|
|
|
- // as of now set to 0 for testing
|
|
|
- battery_data.current= 0;
|
|
|
- battery_data.temperature=0;
|
|
|
- }
|
|
|
+ uint8_t requestedSlot= DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
|
|
|
- //Casting the struct pointer to byte array: (uint8_t*)
|
|
|
- DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t*)&battery_data, sizeof(BatteryData));
|
|
|
- while(!piTxComplete);
|
|
|
- while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
|
|
|
- // Check if full data has been sent
|
|
|
- if (piTxCount >= sizeof(BatteryData)) {
|
|
|
- piTxComplete = true;
|
|
|
- piTxCount = 0; // Reset counter for next request
|
|
|
- printf("Sent Full Battery Data\n");
|
|
|
- }
|
|
|
- }
|
|
|
+ printf("Battery Data!\n");
|
|
|
+ piTxCount= 0;
|
|
|
+ piTxLen= sizeof(BatteryData);
|
|
|
+ BatteryData battery_data;
|
|
|
+ if(requestedSlot < NUM_SLOTS){
|
|
|
+ Battery *battery= &batteries[requestedSlot];
|
|
|
+ battery_data.slot_id = battery-> slot_id;
|
|
|
+ battery_data.voltage= battery-> voltage;
|
|
|
+ battery_data.current= battery-> current;
|
|
|
+ battery_data.temperature= battery-> temperature;
|
|
|
+
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
|
|
|
+
|
|
|
+ piTxCount += DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t*)&battery_data, piTxLen);
|
|
|
+
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
|
|
|
+
|
|
|
+ if(piTxCount >= piTxLen){
|
|
|
+ piTxComplete= true;
|
|
|
+ piTxCount=0;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else{
|
|
|
+ printf("Invalid Slot ID: %d\n.", requestedSlot);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
|
|
|
/* TARGET_Rx FIFO trigger (Pi is writing data to MCU) */
|
|
|
+ /*Pi SET battery data limits for each slot, where:
|
|
|
+ - RXFIFO buffer is filled if the command from Pi is 0x03
|
|
|
+ - Creating a temporary buffer named ´rxbuffer´
|
|
|
+ - sizeof(BatteryLimitMsg): 11 bytes (1 byte: slot_id, 2 bytes: min_voltage; max_voltage; cut_off_current; capacitance; charge_fraction)
|
|
|
+ - rx_buffer stores the data from Pi.
|
|
|
+ - if all the expected bytes are received from Pi then,
|
|
|
+ - memcpy() to copy the block of address from the temporary buffer to the BatteryLimitMsg structure
|
|
|
+ - Why?, A: It copies the specified number of bytes from one memory location to another regardless of the type of the data stored.
|
|
|
+ - verify if the received slot_id is less than NUM_SLOTS, where slot_id count starts from 0 then:
|
|
|
+ - create a pointer variable for 'Battery'
|
|
|
+ - battery_limits.slot_id: index of the battery slot to be updated
|
|
|
+ - &batteries[battery_limits.slot_id]: gets the memory address of the battery in that slot
|
|
|
+ - Accessing the structure members of Battery using -> operator. This allows efficient access to the structure's members
|
|
|
+ without directly using the structure variable.
|
|
|
+
|
|
|
+ */
|
|
|
case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER:
|
|
|
- if (!DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)) {
|
|
|
+ printf("RX FIFO triggered from PI.\n");
|
|
|
+ if(!DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)){
|
|
|
+ receivedCommand= DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ printf("Received Command: 0x%02X\n", receivedCommand);
|
|
|
if(receivedCommand == CMD_SET_BATTERY_LIMIT){
|
|
|
- BatteryLimitMsg battery_limits;
|
|
|
- requestedSlot= DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
- if(requestedSlot < NUM_SLOTS){
|
|
|
- batteries[requestedSlot].min_voltage= (DL_I2C_receiveTargetData(I2C_target_INST)<< 8)|DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
- batteries[requestedSlot].max_voltage= (DL_I2C_receiveTargetData(I2C_target_INST)<< 8)|DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
- batteries[requestedSlot].cut_off_current= (DL_I2C_receiveTargetData(I2C_target_INST)<< 8)|DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
- batteries[requestedSlot].capacitance= (DL_I2C_receiveTargetData(I2C_target_INST)<< 8)|DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ uint8_t rx_buffer[sizeof(BatteryLimitMsg)];
|
|
|
+ uint8_t index= 0;
|
|
|
+
|
|
|
+ while (!DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)){
|
|
|
+ if(index < sizeof(BatteryLimitMsg)){
|
|
|
+ rx_buffer[index]= DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ printf("Received Byte[%d]: 0x%02X\n", index, rx_buffer[index]);
|
|
|
+ index++;
|
|
|
+
|
|
|
}
|
|
|
+ else{
|
|
|
+ DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Total Bytes Received: %d (Expected: %d)\n", index, sizeof(BatteryLimitMsg));
|
|
|
|
|
|
+ if(index == sizeof(BatteryLimitMsg)){
|
|
|
+ printf("Received Battery Limits.\n");
|
|
|
+ BatteryLimitMsg battery_limits;
|
|
|
+ memcpy(&battery_limits, rx_buffer, sizeof(BatteryLimitMsg));
|
|
|
+ if(battery_limits.slot_id < NUM_SLOTS){
|
|
|
+ Battery *battery = &batteries[battery_limits.slot_id];
|
|
|
+ battery -> min_voltage = battery_limits.min_voltage;
|
|
|
+ battery -> max_voltage = battery_limits.max_voltage;
|
|
|
+ battery -> cut_off_current = battery_limits.cut_off_current;
|
|
|
+ battery -> capacitance = battery_limits.capacitance;
|
|
|
+ battery -> charge_fraction = battery_limits.charge_fraction;
|
|
|
+ printf("\n Received Battery Limits for slot %d: \n", battery_limits.slot_id);
|
|
|
+ printf(" Min Voltage: %d mV (0x%04X)\n", battery_limits.min_voltage, battery_limits.min_voltage);
|
|
|
+ printf(" Max Voltage: %d mV (0x%04X)\n", battery_limits.max_voltage, battery_limits.max_voltage);
|
|
|
+ printf(" Cutoff Current: %d mA (0x%04X)\n", battery_limits.cut_off_current, battery_limits.cut_off_current);
|
|
|
+ printf(" Capacitance: %d µF (0x%04X)\n", battery_limits.capacitance, battery_limits.capacitance);
|
|
|
+ printf(" Charge Fraction: %d%% (0x%02X)\n", battery_limits.charge_fraction, battery_limits.charge_fraction);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
/* Arbitration lost or NACK */
|
|
|
case DL_I2C_IIDX_TARGET_ARBITRATION_LOST:
|
|
|
printf("Arbitration Lost.\n");
|
|
|
@@ -323,7 +406,7 @@ int main(void)
|
|
|
|
|
|
//Reset_I2C_Bus();
|
|
|
NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
|
|
|
- NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
|
|
|
+ //NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
|
|
|
|
|
|
printf("............System Configuration Enabled...............\n");
|
|
|
|
|
|
@@ -340,19 +423,19 @@ int main(void)
|
|
|
.gain= 1
|
|
|
|
|
|
};
|
|
|
- printf("Configuring ADC....\n");
|
|
|
+ //printf("Configuring ADC....\n");
|
|
|
//**Set Configuration Register for ADC**
|
|
|
- ADC_SetConfigurationBytes(adc_params);
|
|
|
- uint16_t channel_a_value= 3300; // in mVolts
|
|
|
+ //ADC_SetConfigurationBytes(adc_params);
|
|
|
+ //uint16_t channel_a_value= 3300; // in mVolts
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
{
|
|
|
|
|
|
- Battery_UpdateCurrentVoltage(adc_params);
|
|
|
- for(uint8_t slot_id= 0; slot_id < NUM_SLOTS; slot++){
|
|
|
- CC_CV_ControlCharging(slot_id);
|
|
|
- }
|
|
|
+ //Battery_UpdateCurrentVoltage(adc_params);
|
|
|
+ //for(uint8_t slot_id= 0; slot_id < NUM_SLOTS; slot_id++){
|
|
|
+ // CC_CV_ControlCharging(slot_id);
|
|
|
+ //}
|
|
|
//delay_cycles(5000);
|
|
|
//DAC_fastWrite(channel_a_value);
|
|
|
delay_cycles(100000);
|