|
|
@@ -1,31 +1,28 @@
|
|
|
/*
|
|
|
Main Source File
|
|
|
*/
|
|
|
+#include "adc.h"
|
|
|
+#include "battery.h"
|
|
|
+#include "cc_cv_charging.h"
|
|
|
+#include "dac.h"
|
|
|
#include "i2c_target.h"
|
|
|
+#include "multiplexer.h"
|
|
|
+#include "ti/comm_modules/i2c/controller/i2c_comm_controller.h"
|
|
|
#include "ti/devices/msp/peripherals/hw_dac12.h"
|
|
|
#include "ti/driverlib/dl_adc12.h"
|
|
|
#include "ti/driverlib/dl_gpio.h"
|
|
|
#include "ti/driverlib/dl_i2c.h"
|
|
|
#include "ti/driverlib/m0p/dl_core.h"
|
|
|
#include "ti_msp_dl_config.h"
|
|
|
-#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"
|
|
|
#include <ti/drivers/GPIO.h>
|
|
|
|
|
|
-
|
|
|
I2C_Instance gI2C;
|
|
|
I2C_ResponseInfo gResponse;
|
|
|
BatteryData battery_data;
|
|
|
|
|
|
-
|
|
|
/*Interrupt for MCU -> ADC
|
|
|
* CASE: DL_I2C_IIDX_CONTROLLER_RX_DONE: ADC Reception Complete
|
|
|
- ADC has finished sending data and it's fully received.
|
|
|
@@ -36,330 +33,398 @@ BatteryData battery_data;
|
|
|
- gI2C.status = I2C_STATUS_RX_COMPLETE:
|
|
|
- Marks reception is complete.
|
|
|
* CASE: DL_I2C_IIDX_CONTROLLER_TX_DONE: Data Transmit to ADC complete
|
|
|
- - DL_I2C_disableInterrupt(..): Disables the TXFIFO interrupt since data is now sent
|
|
|
+ - DL_I2C_disableInterrupt(..): Disables the TXFIFO interrupt since data is
|
|
|
+now sent
|
|
|
* CASE: DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER: Receive Data in FIFO
|
|
|
- The I2C Receive FIFO has data ready to be read.
|
|
|
- - while (DL_I2C_isControllerRXFIFOEmpty(...) != true): Loops until the RX FIFOis empty (READ all available bytes)
|
|
|
+ - while (DL_I2C_isControllerRXFIFOEmpty(...) != true): Loops until the RX
|
|
|
+FIFOis empty (READ all available bytes)
|
|
|
- Inside the while loop:
|
|
|
- If buffer has SPACE, store the received byte
|
|
|
- Prints each received byte in HEXADECIMAL format for debugging
|
|
|
- IF BUFFER is FULL, avoids OVERFLOW by discarding extra byte.
|
|
|
* CASE: DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER: Transmit Data in FIFO
|
|
|
- If there is still data to send:
|
|
|
- gI2C.txMsg.ptr += DL_I2C_fillControllerTXFIFO(I2C_controller_INST, &gI2C.txMsg.buffer[gI2C.txMsg.ptr], gI2C.txMsg.len - gI2C.txMsg.ptr);
|
|
|
+ gI2C.txMsg.ptr += DL_I2C_fillControllerTXFIFO(I2C_controller_INST,
|
|
|
+&gI2C.txMsg.buffer[gI2C.txMsg.ptr], gI2C.txMsg.len - gI2C.txMsg.ptr);
|
|
|
|
|
|
*/
|
|
|
-void I2C_controller_INST_IRQHandler(void)
|
|
|
-{
|
|
|
- //printf("I2C Interrupt Triggered to ADC!\n");
|
|
|
- switch (DL_I2C_getPendingInterrupt(I2C_controller_INST))
|
|
|
- { /*START Condition*/
|
|
|
- case DL_I2C_IIDX_CONTROLLER_START:
|
|
|
- //gTxADCcount= 0;
|
|
|
- gRxADCcount= 0;
|
|
|
- DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
|
|
|
- break;
|
|
|
-
|
|
|
- case DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER:
|
|
|
- gI2C.status= I2C_STATUS_RX_INPROGRESS;
|
|
|
- /* Store bytes received from target in Rx Msg Buffer */
|
|
|
- while (DL_I2C_isControllerRXFIFOEmpty(I2C_controller_INST) != true) {
|
|
|
- if (gRxADCcount< gRxADClen) {
|
|
|
- gRxPacket[gRxADCcount] = DL_I2C_receiveControllerData(I2C_controller_INST);
|
|
|
- printf("Received Byte[%d]: 0x%02X\n", gRxADCcount, gRxPacket[gRxADCcount]); // Debug print
|
|
|
- gRxADCcount++;
|
|
|
-
|
|
|
- } else {
|
|
|
- //printf("ERROR: RX Buffer Overflow! ptr=%d MAX_BUFFER_SIZE=%d\n", gI2C.rxMsg.ptr, MAX_BUFFER_SIZE);
|
|
|
- /* Ignore and remove from FIFO if the buffer is full */
|
|
|
- DL_I2C_receiveControllerData(I2C_controller_INST);
|
|
|
- }
|
|
|
- }
|
|
|
- if (gRxADCcount >= gRxADClen){
|
|
|
- //printf("ADC Bytes Received!\n");
|
|
|
- gRxComplete = true;
|
|
|
- DL_I2C_enableInterrupt(I2C_controller_INST, DL_I2C_INTERRUPT_CONTROLLER_STOP);
|
|
|
-
|
|
|
- }
|
|
|
- break;
|
|
|
- /*TRANSMIT data to ADC*/
|
|
|
- case DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER:
|
|
|
- //printf("TX FIFO with data!\n");
|
|
|
- gI2C.status= I2C_STATUS_TX_INPROGRESS;
|
|
|
- if(gTxADCcount<gTxADClen){
|
|
|
- gTxADCcount+= DL_I2C_fillControllerTXFIFO(I2C_controller_INST, &gTxPacket[gTxADCcount], (gTxADClen-gTxADCcount));
|
|
|
- } else{
|
|
|
- /*Prevent overflow and just ignore data*/
|
|
|
- DL_I2C_fillTargetTXFIFO(I2C_controller_INST, (uint8_t[]){0x00}, 1);
|
|
|
- gTxComplete= true;
|
|
|
- }
|
|
|
- //DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
|
|
|
- break;
|
|
|
- /*STOP condition*/
|
|
|
- case DL_I2C_IIDX_CONTROLLER_STOP:
|
|
|
- gTxComplete= true;
|
|
|
- gRxComplete = true;
|
|
|
- //printf("I2C Stop Detected- RX Complete");
|
|
|
- break;
|
|
|
- case DL_I2C_IIDX_CONTROLLER_ARBITRATION_LOST:
|
|
|
- //printf("Interrupt index for I2C controller Arbitration Lost!\n");
|
|
|
- break;
|
|
|
- case DL_I2C_IIDX_CONTROLLER_NACK:
|
|
|
- //printf("I2C NACK Received\n");
|
|
|
- if((gI2C.status== I2C_STATUS_RX_STARTED)|| (gI2C.status= I2C_STATUS_TX_STARTED)){
|
|
|
- gI2C.status= I2C_STATUS_ERROR;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
+void I2C_controller_INST_IRQHandler(void) {
|
|
|
+ // printf("I2C Interrupt Triggered to ADC!\n");
|
|
|
+ switch (DL_I2C_getPendingInterrupt(I2C_controller_INST)) { /*START Condition*/
|
|
|
+ case DL_I2C_IIDX_CONTROLLER_START:
|
|
|
+ // gTxADCcount= 0;
|
|
|
+ gRxADCcount = 0;
|
|
|
+ DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER:
|
|
|
+ gI2C.status = I2C_STATUS_RX_INPROGRESS;
|
|
|
+ /* Store bytes received from target in Rx Msg Buffer */
|
|
|
+ while (DL_I2C_isControllerRXFIFOEmpty(I2C_controller_INST) != true) {
|
|
|
+ if (gRxADCcount < gRxADClen) {
|
|
|
+ gRxPacket[gRxADCcount] =
|
|
|
+ DL_I2C_receiveControllerData(I2C_controller_INST);
|
|
|
+ printf("Received Byte[%d]: 0x%02X\n", gRxADCcount,
|
|
|
+ gRxPacket[gRxADCcount]); // Debug print
|
|
|
+ gRxADCcount++;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // printf("ERROR: RX Buffer Overflow! ptr=%d MAX_BUFFER_SIZE=%d\n",
|
|
|
+ // gI2C.rxMsg.ptr, MAX_BUFFER_SIZE);
|
|
|
+ /* Ignore and remove from FIFO if the buffer is full */
|
|
|
+ DL_I2C_receiveControllerData(I2C_controller_INST);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (gRxADCcount >= gRxADClen) {
|
|
|
+ // printf("ADC Bytes Received!\n");
|
|
|
+ gRxComplete = true;
|
|
|
+ DL_I2C_enableInterrupt(I2C_controller_INST,
|
|
|
+ DL_I2C_INTERRUPT_CONTROLLER_STOP);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ /*TRANSMIT data to ADC*/
|
|
|
+ case DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER:
|
|
|
+ // printf("TX FIFO with data!\n");
|
|
|
+ gI2C.status = I2C_STATUS_TX_INPROGRESS;
|
|
|
+ if (gTxADCcount < gTxADClen) {
|
|
|
+ gTxADCcount += DL_I2C_fillControllerTXFIFO(I2C_controller_INST,
|
|
|
+ &gTxPacket[gTxADCcount],
|
|
|
+ (gTxADClen - gTxADCcount));
|
|
|
+ } else {
|
|
|
+ /*Prevent overflow and just ignore data*/
|
|
|
+ DL_I2C_fillTargetTXFIFO(I2C_controller_INST, (uint8_t[]){0x00}, 1);
|
|
|
+ gTxComplete = true;
|
|
|
}
|
|
|
+ // DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
|
|
|
+ break;
|
|
|
+ /*STOP condition*/
|
|
|
+ case DL_I2C_IIDX_CONTROLLER_STOP:
|
|
|
+ gTxComplete = true;
|
|
|
+ gRxComplete = true;
|
|
|
+ // printf("I2C Stop Detected- RX Complete");
|
|
|
+ break;
|
|
|
+ case DL_I2C_IIDX_CONTROLLER_ARBITRATION_LOST:
|
|
|
+ // printf("Interrupt index for I2C controller Arbitration Lost!\n");
|
|
|
+ break;
|
|
|
+ case DL_I2C_IIDX_CONTROLLER_NACK:
|
|
|
+ // printf("I2C NACK Received\n");
|
|
|
+ if ((gI2C.status == I2C_STATUS_RX_STARTED) ||
|
|
|
+ (gI2C.status = I2C_STATUS_TX_STARTED)) {
|
|
|
+ gI2C.status = I2C_STATUS_ERROR;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**** Interrupt for Pi to MCU ****/
|
|
|
|
|
|
void I2C_target_INST_IRQHandler(void) {
|
|
|
|
|
|
- //printf("I2C Interrupt Triggered to MCU (TARGET)!\n");
|
|
|
- uint8_t receivedCommand= 0;
|
|
|
- uint32_t status = DL_I2C_getPendingInterrupt(I2C_target_INST);
|
|
|
- //ADC_PARAMS params;
|
|
|
- switch (status) {
|
|
|
-
|
|
|
- /* START condition detected */
|
|
|
- case DL_I2C_IIDX_TARGET_START:
|
|
|
- piTxCount= 0;
|
|
|
- piRxCount= 0;
|
|
|
- piTxComplete= false;
|
|
|
- DL_I2C_flushTargetTXFIFO(I2C_target_INST);
|
|
|
- break;
|
|
|
-
|
|
|
- /* STOP condition detected */
|
|
|
- case DL_I2C_IIDX_TARGET_STOP:
|
|
|
- piTxComplete= true;
|
|
|
- piRxComplete = true;
|
|
|
- DL_I2C_flushTargetTXFIFO(I2C_target_INST);
|
|
|
- break;
|
|
|
-
|
|
|
- /* TX FIFO trigger (Pi is reading data from MCU) */
|
|
|
- /* 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_fillTargetRXFIFO()
|
|
|
- - Reset the RX counter for the next data.
|
|
|
- */
|
|
|
-
|
|
|
- case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
|
|
|
- printf("Pi GET data from MCU!\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_GET_BATTERY_STATUS){
|
|
|
- printf("Battery status received.\n");
|
|
|
- //Battery_StateUpdate();
|
|
|
- piTxCount= 0;
|
|
|
- piTxLen= NUM_SLOTS;
|
|
|
- piTxComplete = false;
|
|
|
- // Prepare data to be sent to Pi:
|
|
|
- for(uint8_t slot= 0; slot < NUM_SLOTS; slot++){
|
|
|
- // Read the battery status for each slot
|
|
|
- Battery_ReadState(slot);
|
|
|
- piTxPacket[slot]= batteries[slot].state;
|
|
|
- }
|
|
|
- //Filling up the FIFO
|
|
|
- if(piTxCount < piTxLen){
|
|
|
- while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY)
|
|
|
- ;
|
|
|
- piTxCount += DL_I2C_fillTargetTXFIFO(I2C_target_INST, &piTxPacket[piTxCount], (piTxLen-piTxCount));
|
|
|
- }
|
|
|
- else {
|
|
|
- /*
|
|
|
- * Fill FIFO with 0x00 if more data is requested than expected piTxLen
|
|
|
- */
|
|
|
- while (
|
|
|
- DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false);
|
|
|
- }
|
|
|
- piTxComplete= true;
|
|
|
- }
|
|
|
- else if (receivedCommand == CMD_GET_BATTERY_DATA){
|
|
|
-
|
|
|
- uint8_t requestedSlot= DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
- while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY)
|
|
|
- ;
|
|
|
- //printf("Battery Data Requested for Slot %d!\n", requestedSlot);
|
|
|
- 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);
|
|
|
-
|
|
|
- DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t *)&battery_data, sizeof(BatteryData));
|
|
|
-
|
|
|
- //piTxCount += DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t*)&battery_data, piTxLen);
|
|
|
-
|
|
|
- piTxComplete= true;
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
+ // printf("I2C Interrupt Triggered to MCU (TARGET)!\n");
|
|
|
+ uint8_t receivedCommand = 0;
|
|
|
+ uint32_t status = DL_I2C_getPendingInterrupt(I2C_target_INST);
|
|
|
+ // ADC_PARAMS params;
|
|
|
+ switch (status) {
|
|
|
+
|
|
|
+ /* START condition detected */
|
|
|
+ case DL_I2C_IIDX_TARGET_START:
|
|
|
+ piTxCount = 0;
|
|
|
+ piRxCount = 0;
|
|
|
+ piTxComplete = false;
|
|
|
+ DL_I2C_flushTargetTXFIFO(I2C_target_INST);
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* STOP condition detected */
|
|
|
+ case DL_I2C_IIDX_TARGET_STOP:
|
|
|
+ piTxComplete = true;
|
|
|
+ piRxComplete = true;
|
|
|
+ DL_I2C_flushTargetTXFIFO(I2C_target_INST);
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* TX FIFO trigger (Pi is reading data from MCU) */
|
|
|
+ /* 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_fillTargetRXFIFO()
|
|
|
+ - Reset the RX counter for the next data.
|
|
|
+ */
|
|
|
+
|
|
|
+ case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
|
|
|
+ break;
|
|
|
+ if (!DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)) {
|
|
|
+ receivedCommand = DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ // printf("Received Command: 0x%02X\n", receivedCommand);
|
|
|
+
|
|
|
+ else {
|
|
|
+ /*
|
|
|
+ * Fill FIFO with 0x00 if more data is requested than expected piTxLen
|
|
|
+ */
|
|
|
+ while (DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false)
|
|
|
+ ;
|
|
|
+ }
|
|
|
+ piTxComplete = true;
|
|
|
+ } else if (receivedCommand == CMD_GET_BATTERY_DATA) {
|
|
|
+
|
|
|
+ uint8_t requestedSlot = DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) &
|
|
|
+ DL_I2C_TARGET_STATUS_BUS_BUSY)
|
|
|
+ ;
|
|
|
+ // printf("Battery Data Requested for Slot %d!\n", requestedSlot);
|
|
|
+ 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)
|
|
|
+ ;
|
|
|
+
|
|
|
+ DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t *)&battery_data,
|
|
|
+ sizeof(BatteryData));
|
|
|
+
|
|
|
+ // piTxCount += DL_I2C_fillTargetTXFIFO(I2C_target_INST,
|
|
|
+ // (uint8_t*)&battery_data, piTxLen);
|
|
|
+
|
|
|
+ piTxComplete = true;
|
|
|
+
|
|
|
+ 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:
|
|
|
- printf("Pi SET Battery limit to MCU.....\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){
|
|
|
- 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");
|
|
|
- break;
|
|
|
- default:
|
|
|
- printf("Unknown Interrupt.\n");
|
|
|
- break;
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-/********MAIN function*************/
|
|
|
+ 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)) {
|
|
|
+
|
|
|
+ receivedCommand = DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+
|
|
|
+ if (receivedCommand == CMD_SET_BATTERY_LIMIT) {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-int main(void)
|
|
|
-{
|
|
|
- // Initialize System and I2C
|
|
|
- SYSCFG_DL_init();
|
|
|
-
|
|
|
- // Initialize battery array and default params
|
|
|
- Battery_Init();
|
|
|
-
|
|
|
- //Reset_I2C_Bus();
|
|
|
- NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
|
|
|
- NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
|
|
|
-
|
|
|
- printf("............System Configuration Enabled...............\n");
|
|
|
-
|
|
|
- //Multiplexer
|
|
|
- Multiplexer_SelectChannel(I2C_CHANNEL);
|
|
|
- //I2C_scanBus();
|
|
|
- I2C_init(&gI2C);
|
|
|
-
|
|
|
- //ADC_SetConfigurationBytes(adc_voltage_params);
|
|
|
- //delay_cycles(50000);
|
|
|
- //ADC_SetConfigurationBytes(adc_current_params);
|
|
|
- //delay_cycles(50000);
|
|
|
- //DAC_ReadCurrentAddress();
|
|
|
-
|
|
|
- while (1)
|
|
|
- { //Looping through the ADC Channels
|
|
|
- /*for(uint8_t slot_id=0; slot_id< NUM_SLOTS; slot_id++){
|
|
|
- for(uint8_t adc_channel=0; adc_channel< ADC_CHANNEL_NUM; adc_channel++){
|
|
|
- batteries[slot_id].channel= adc_channel;
|
|
|
- Battery_UpdateADCReading(slot_id, batteries[slot_id].channel);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
+ // 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);*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (receivedCommand == CMD_GET_BATTERY_STATUS) {
|
|
|
+ uint8_t test[8] = {0x00};
|
|
|
+ // for testing:
|
|
|
+ Battery batteries[NUM_SLOTS] = {
|
|
|
+ {0, STATE_BATTERY_DETECTED, 3700, 500, 25, 3000, 4200, 2000, 10000, 80}
|
|
|
+ };
|
|
|
+ //Battery_StateUpdate();
|
|
|
+
|
|
|
+ // Prepare data to be sent to Pi:
|
|
|
+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
|
|
|
+ // Read the battery status for each slot
|
|
|
+ //Battery_ReadState(slot);
|
|
|
+ test[slot] = batteries[slot].state;
|
|
|
+ }
|
|
|
+ // Filling up the FIFO
|
|
|
+ DL_I2C_fillTargetTXFIFO(I2C_target_INST, &test, 8);
|
|
|
+ while (DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false)
|
|
|
+ ;
|
|
|
+ printf("Sent Data\n");
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /*if (piTxCount < piTxLen) {
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) &
|
|
|
+ DL_I2C_TARGET_STATUS_BUS_BUSY)
|
|
|
+ ;
|
|
|
+ piTxCount += DL_I2C_fillTargetTXFIFO(
|
|
|
+ I2C_target_INST, &piTxPacket[piTxCount], (piTxLen - piTxCount));
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Fill FIFO with 0x00 if more data is requested than expected piTxLen
|
|
|
+ */
|
|
|
+ /*while (DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false)
|
|
|
+ ;
|
|
|
}*/
|
|
|
+ } else if (receivedCommand == CMD_GET_BATTERY_DATA) {
|
|
|
+
|
|
|
+ uint8_t requestedSlot = DL_I2C_receiveTargetData(I2C_target_INST);
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) &
|
|
|
+ DL_I2C_TARGET_STATUS_BUS_BUSY)
|
|
|
+ ;
|
|
|
+ // printf("Battery Data Requested for Slot %d!\n", requestedSlot);
|
|
|
+ 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)
|
|
|
+ ;
|
|
|
+
|
|
|
+ DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t *)&battery_data,
|
|
|
+ sizeof(BatteryData));
|
|
|
+
|
|
|
+ // piTxCount += DL_I2C_fillTargetTXFIFO(I2C_target_INST,
|
|
|
+ // (uint8_t*)&battery_data, piTxLen);
|
|
|
+
|
|
|
+ piTxComplete = true;
|
|
|
+
|
|
|
+ while (DL_I2C_getTargetStatus(I2C_target_INST) &
|
|
|
+ DL_I2C_TARGET_STATUS_BUS_BUSY)
|
|
|
+ ;
|
|
|
+
|
|
|
+ if (piTxCount >= piTxLen) {
|
|
|
+ piTxComplete = true;
|
|
|
+ piTxCount = 0;
|
|
|
+ }
|
|
|
|
|
|
- //CC-CV Cycle: maximum cycles is not yet implemented
|
|
|
- //for(uint8_t slot_id= 0; slot_id < NUM_SLOTS; slot_id++){
|
|
|
- // CC_CV_ControlCharging(slot_id);
|
|
|
- //}
|
|
|
-
|
|
|
- //DAC_fastWrite(CHANNEL_A_VALUE);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ break;
|
|
|
|
|
|
+ /* Arbitration lost or NACK */
|
|
|
+ case DL_I2C_IIDX_TARGET_ARBITRATION_LOST:
|
|
|
+ printf("Arbitration Lost.\n");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ printf("Unknown Interrupt.\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
|
|
|
+/********MAIN function*************/
|
|
|
+
|
|
|
+int main(void) {
|
|
|
+ // Initialize System and I2C
|
|
|
+ SYSCFG_DL_init();
|
|
|
+
|
|
|
+ // Initialize battery array and default params
|
|
|
+ Battery_Init();
|
|
|
|
|
|
+ // Reset_I2C_Bus();
|
|
|
+ NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
|
|
|
+ NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
|
|
|
|
|
|
+ printf("............System Configuration Enabled...............\n");
|
|
|
|
|
|
+ // Multiplexer
|
|
|
+ Multiplexer_SelectChannel(I2C_CHANNEL);
|
|
|
+ // I2C_scanBus();
|
|
|
+ I2C_init(&gI2C);
|
|
|
|
|
|
+ // ADC_SetConfigurationBytes(adc_voltage_params);
|
|
|
+ // delay_cycles(50000);
|
|
|
+ // ADC_SetConfigurationBytes(adc_current_params);
|
|
|
+ // delay_cycles(50000);
|
|
|
+ // DAC_ReadCurrentAddress();
|
|
|
|
|
|
+ while (1) { // Looping through the ADC Channels
|
|
|
+ /*for(uint8_t slot_id=0; slot_id< NUM_SLOTS; slot_id++){
|
|
|
+ for(uint8_t adc_channel=0; adc_channel< ADC_CHANNEL_NUM; adc_channel++){
|
|
|
+ batteries[slot_id].channel= adc_channel;
|
|
|
+ Battery_UpdateADCReading(slot_id, batteries[slot_id].channel);
|
|
|
|
|
|
+ }
|
|
|
+
|
|
|
+ }*/
|
|
|
|
|
|
+ // CC-CV Cycle: maximum cycles is not yet implemented
|
|
|
+ // for(uint8_t slot_id= 0; slot_id < NUM_SLOTS; slot_id++){
|
|
|
+ // CC_CV_ControlCharging(slot_id);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // DAC_fastWrite(CHANNEL_A_VALUE);
|
|
|
+ }
|
|
|
+}
|