Ver código fonte

adc channel fix

namrota ghosh 9 meses atrás
pai
commit
4dde6b7ee7
9 arquivos alterados com 403 adições e 260 exclusões
  1. 257 210
      adc.c
  2. 12 2
      adc.h
  3. 6 1
      battery.h
  4. 32 12
      cc_cv_charging.c
  5. 48 1
      dac.c
  6. 2 0
      dac.h
  7. 14 0
      dynamic_i2c_addressing_mcu.c
  8. 26 34
      i2c_controller.c
  9. 6 0
      i2c_controller.syscfg

+ 257 - 210
adc.c

@@ -1,10 +1,10 @@
-#include <adc.h>
-#include <stdint.h>
-#include <stdio.h>
 #include "battery.h"
 #include "ti/driverlib/dl_i2c.h"
 #include "ti/driverlib/m0p/dl_core.h"
 #include "ti_msp_dl_config.h"
+#include <adc.h>
+#include <stdint.h>
+#include <stdio.h>
 
 volatile bool gRxComplete;
 volatile bool gTxComplete;
@@ -14,96 +14,142 @@ uint8_t gRxPacket[I2C_RX_MAX_PACKET_SIZE];
 uint32_t gTxADClen, gTxADCcount;
 uint32_t gRxADClen, gRxADCcount;
 
-uint8_t ADC_ConstructConfigBytes(ADC_PARAMS params) {
-
-    uint8_t config = 0;
-
-    config |= ((params.channel - 1) << 5);  // Channel Selection (Bits 6-5)
-
-    config |= (1 << 4);  // One-Shot Mode
+static ADC_PARAMS adc_params;
+static ADC_MeasurementState adc_state = ADC_STATE_CONFIGURE;
 
-    switch (params.resolution) {
-        case 12: config |= (0b00 << 2); break;
-        case 14: config |= (0b01 << 2); break;       
-        case 16: config |= (0b10 << 2); break;
-        default: printf("ERROR: Invalid Resolution!\n"); return 0;
-    }
-
-    switch (params.gain) {
-        case 1: config |= (0b00); break;
-        case 2: config |= (0b01); break;
-        case 4: config |= (0b10); break;
-        default: printf("ERROR: Invalid Gain!\n"); return 0;
-    }
+uint8_t ADC_ConstructConfigBytes(ADC_PARAMS params) {
 
-    return config;
+  uint8_t config = 0;
+
+  config |= ((params.channel) << 5); // Channel Selection (Bits 6-5)
+
+  config |= (1 << 4); // One-Shot Mode
+
+  switch (params.resolution) {
+  case 12:
+    config |= (0b00 << 2);
+    break;
+  case 14:
+    config |= (0b01 << 2);
+    break;
+  case 16:
+    config |= (0b10 << 2);
+    break;
+  default:
+    printf("ERROR: Invalid Resolution!\n");
+    return 0;
+  }
+
+  switch (params.gain) {
+  case 1:
+    config |= (0b00);
+    break;
+  case 2:
+    config |= (0b01);
+    break;
+  case 4:
+    config |= (0b10);
+    break;
+  default:
+    printf("ERROR: Invalid Gain!\n");
+    return 0;
+  }
+
+  return config;
 }
 
-/* Tansmit Data from MCU to ADC:  Function to SET configuration to ADC over I2C*/
+/* Tansmit Data from MCU to ADC:  Function to SET configuration to ADC over
+ * I2C*/
+
 
 void ADC_SetConfigurationBytes(ADC_PARAMS params) {
-    // **Construct Configuration Byte**
-    uint8_t config_byte = ADC_ConstructConfigBytes(params);
-
-    // Wait for I2C Bus to be Free**
-    while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
-
-    // **Start I2C Write Transaction**
-    // Prepare TX Buffer:
-    gTxPacket[0]= config_byte;
-    gTxADClen= 1;
-    gTxADCcount= 0;
-    gTxComplete= false;
-
-    DL_I2C_startControllerTransfer(I2C_controller_INST, ADC_TARGET_BASE_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX, gTxADClen);
-    DL_I2C_enableInterrupt(I2C_controller_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
-    //while(!gTxComplete);
-    // **Ensure STOP Condition is Sent**
-    while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
-    printf("Configuration Sent Successfully for 0x%X!\n", config_byte);
+  // **Construct Configuration Byte**
+  uint8_t config_byte = ADC_ConstructConfigBytes(params);
+
+  // Wait for I2C Bus to be Free**
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
+
+  // **Start I2C Write Transaction**
+  // Prepare TX Buffer:
+  gTxPacket[0] = config_byte;
+  gTxADClen = 1;
+  gTxADCcount = 0;
+  gTxComplete = false;
+
+  DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
+  DL_I2C_fillControllerTXFIFO(I2C_controller_INST, (uint8_t*) &gTxPacket, 1);
+  DL_I2C_startControllerTransfer(I2C_controller_INST, ADC_TARGET_BASE_ADDRESS,
+                                 DL_I2C_CONTROLLER_DIRECTION_TX, gTxADClen);
+  //DL_I2C_enableInterrupt(I2C_controller_INST,
+  //                       DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
+  // while(!gTxComplete);
+  //  **Ensure STOP Condition is Sent**
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
+  // printf("Configuration Sent Successfully for 0x%X!\n", config_byte);
 }
 
-// **Interrupt handler for configuration completion**
-void I2C_ConfigInterruptHandler(void) {
-    if (DL_I2C_getPendingInterrupt(I2C_controller_INST) == DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER) {
-        gTxComplete = true;
-    }
-}
 /*
 READY BIT:
-    This bit is the data ready flag. In read mode, this bit indicates if the output register has been updated
-    with a latest conversion result. In One-Shot Conversion mode, writing this bit to “1” initiates a new
-    conversion.
+    This bit is the data ready flag. In read mode, this bit indicates if the
+output register has been updated with a latest conversion result. In One-Shot
+Conversion mode, writing this bit to “1” initiates a new conversion.
 
     1= Output Register has not been updated
     0= Output Register has been updated
 
 */
 
-bool ADC_CheckReadyBit(uint8_t slot_id, ADC_PARAMS params){
-    uint8_t config_byte = ADC_ConstructConfigBytes(params);
-    DL_I2C_startControllerTransfer(I2C_controller_INST, ADC_TARGET_BASE_ADDRESS+slot_id, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
-    config_byte= DL_I2C_receiveControllerData(I2C_controller_INST);
-    bool ready= (config_byte & 0x80)==0; //Ready bit is bit 7
-    printf("Slot: %d | Config Byte: 0x%02X | READY Bit: %d\n", slot_id, config_byte, ready);
-    return ready;
+bool ADC_CheckReadyBit(uint8_t slot_id, ADC_PARAMS params) {
+  // Buffer for ADC data (MSB, LSB, Config Byte)
+  uint8_t adc_data[3];
+  uint8_t adc_address = ADC_TARGET_BASE_ADDRESS + slot_id;
+  printf("Reading ADC Data from MCP3428 for channel: %u\n", params.channel);
+  gRxADClen = 3;
+  gRxADCcount = 0;
+  gRxComplete = false;
+
+  DL_I2C_startControllerTransfer(I2C_controller_INST, adc_address,
+                                 DL_I2C_CONTROLLER_DIRECTION_RX, gRxADClen);
+  DL_I2C_enableInterrupt(I2C_controller_INST,
+                         DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
+  while (!gRxComplete)
+    ;
+
+  uint8_t config_adc_byte = gRxPacket[2];
+
+  // Ready bit is bit 7
+  bool ready = (config_adc_byte & 0x80) == 0;
+  printf("Slot: %d | Config Byte: 0x%02X | READY Bit: %d\n", slot_id,
+         config_adc_byte, ready);
+  return ready;
 }
 
-
 /*
-Function to read ADC DATA: This function simply retrieves the ADC raw digital output as 16-bit signed integer. 
+Function to read ADC DATA: This function simply retrieves the ADC raw digital
+output as 16-bit signed integer.
 * The value returned is not yet converted to VOLTAGE.
-* adc_data[2]: Buffer with an array of size 2, to store two bytes of ADC data. 
+* adc_data[2]: Buffer with an array of size 2, to store two bytes of ADC data.
 *             Since, the ADC output consists of two 8-bit bytes:
 *             - adc_data[0] (MSB)
 *             - adc_data[1] (LSB)
-* Next, we verify if the the I2C bus is busy using the function in the driverlib: DL_I2C_get ControllerStatus
-*       - Prevents collisions by ensuring no two I2C device is using the same bus before initializing.
-* BEGIN I2C READ operation to request 2 bytes from the ADC-> DL_I2C_startControllerTransfer()
+* Next, we verify if the the I2C bus is busy using the function in the
+driverlib: DL_I2C_get ControllerStatus
+*       - Prevents collisions by ensuring no two I2C device is using the same
+bus before initializing.
+* BEGIN I2C READ operation to request 2 bytes from the ADC->
+DL_I2C_startControllerTransfer()
 * Parameters:
     - I2C_controller_INST: Refererence to the I2C instance bring used.
     - DEF_TARGET_ADDR_ADC: Address of the ADC
-    - DL_I2C_CONTROLLER_DIRECTION_RX: Indicates that we want to receive the data from ADC
+    - DL_I2C_CONTROLLER_DIRECTION_RX: Indicates that we want to receive the data
+from ADC
     - 2: Specifies that we expect 2 bytes from the ADC
 * WAIT for the data to be received: (DL_I2C_getControllerStatus())
     - Waits until the ADC sends the data over I2C.
@@ -115,167 +161,168 @@ Function to read ADC DATA: This function simply retrieves the ADC raw digital ou
     ADC sends its 16-bit value in two parts over 8-bit I2C data frames.
 * COMBINE the two bytes into 16-bit Integer:
     - Shifts the MSB(first byte) left by 8 bits to make space for LSB.
-    - Performs a bitwise OR operation to combine MSB and LSB into a single 16-bit number.
+    - Performs a bitwise OR operation to combine MSB and LSB into a single
+16-bit number.
 * PRINT HEXADEC and DECIMAL format for DEBUGGING.
-* Output code is in binary and is proportional to the Input Voltage and PGA settings.
-* From the datasheet: https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/22226a.pdf
+* Output code is in binary and is proportional to the Input Voltage and PGA
+settings.
+* From the datasheet:
+https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/22226a.pdf
     - Equation 4.4 is being used to convert the output codes to input voltage
 
-* The ACK bits after conversion is issued by the Master, when the device receives a READ command, it outputs two data bytes
-    followed by a configuration register in 16 bit conversion mode the MSB(=sign bit) of the first data type is D15.
-    
-*/
+* The ACK bits after conversion is issued by the Master, when the device
+receives a READ command, it outputs two data bytes followed by a configuration
+register in 16 bit conversion mode the MSB(=sign bit) of the first data type is
+D15.
 
-int16_t ADC_ReadData(uint8_t slot_id, ADC_PARAMS params)
-{
-    //Request ADC Conversion
-    //ADC_SetConfigurationBytes(params);
-
-    //Wait until data is ready
-    while(!ADC_CheckReadyBit(slot_id, params)){
-        delay_cycles(50000);
-    }
-    // Buffer for ADC data (MSB, LSB, Config Byte)
-    uint8_t adc_data[3] = {0};  
-    int16_t raw_adc = 0;
-    uint8_t bytes_to_read= 3;
-    uint8_t adc_address= ADC_TARGET_BASE_ADDRESS + slot_id;
-    printf("Reading ADC Data from MCP3428 for channel: %u\n", params.channel);
-    
-    if(DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS){
-        printf("Error: I2C bus stuck! Resetting..\n");
-        DL_I2C_resetControllerTransfer(I2C_controller_INST);
-    }
-
-    gRxADClen= bytes_to_read;
-    gRxADCcount= 0;
-    gRxComplete= false;
-   
-    DL_I2C_startControllerTransfer(I2C_controller_INST, adc_address, DL_I2C_CONTROLLER_DIRECTION_RX, gRxADClen);
-    DL_I2C_enableInterrupt(I2C_controller_INST, DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
-    while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
-    while(!gRxComplete);
-    
-    uint8_t msb= gRxPacket[0];
-    uint8_t lsb= gRxPacket[1];
-    uint8_t config_adc_byte= gRxPacket[2];
-
-    uint8_t gain_setting = (config_adc_byte & 0x03);
-    uint8_t gain_multiplier = (1 << gain_setting); // Gain values: 1, 2, 4, 8
-
-    if (params.resolution==16){
-        raw_adc= (msb << 8)| lsb;
-        if(raw_adc > 32767) raw_adc-= 65536;
-    }
-    else if (params.resolution == 14) {
-        raw_adc= ((msb & 0b00111111) << 8)| lsb;
-        if(raw_adc > 8191) raw_adc-= 16384;
-    }
-    else if(params.resolution == 12){
-        raw_adc = ((msb & 0b00001111) << 8) | lsb; 
-        if (raw_adc > 2047) raw_adc -= 4096; 
-
-    }
+*/
 
-    //printf("Gain %d: \n", gain_multiplier);
-    printf("Raw ADC Value: 0x%0X (%d)\n", raw_adc, raw_adc);
-    return raw_adc;
-   
+int16_t ADC_ReadData(uint8_t slot_id, ADC_PARAMS params) {
+
+  // Buffer for ADC data (MSB, LSB, Config Byte)
+  uint8_t adc_data[3] = {0};
+  int16_t raw_adc = 0;
+  uint8_t bytes_to_read = 3;
+  uint8_t adc_address = ADC_TARGET_BASE_ADDRESS + slot_id;
+  // printf("Reading ADC Data from MCP3428 for channel: %u\n", params.channel);
+
+  if (DL_I2C_getControllerStatus(I2C_controller_INST) &
+      DL_I2C_CONTROLLER_STATUS_BUSY_BUS) {
+    printf("Error: I2C bus stuck! Resetting..\n");
+    // DL_I2C_resetControllerTransfer(I2C_controller_INST);
+  }
+
+  gRxADClen = bytes_to_read;
+  gRxADCcount = 0;
+  gRxComplete = false;
+
+  DL_I2C_startControllerTransfer(I2C_controller_INST, adc_address,
+                                 DL_I2C_CONTROLLER_DIRECTION_RX, gRxADClen);
+  DL_I2C_enableInterrupt(I2C_controller_INST,
+                         DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
+  while (!gRxComplete)
+    ;
+
+  uint8_t msb = gRxPacket[0];
+  uint8_t lsb = gRxPacket[1];
+  uint8_t config_adc_byte = gRxPacket[2];
+
+  uint8_t gain_setting = (config_adc_byte & 0x03);
+  uint8_t gain_multiplier = (1 << gain_setting); // Gain values: 1, 2, 4, 8
+
+  if (params.resolution == 16) {
+    raw_adc = (msb << 8) | lsb;
+    if (raw_adc > 32767)
+      raw_adc -= 65536;
+  } else if (params.resolution == 14) {
+    raw_adc = ((msb & 0b00111111) << 8) | lsb;
+    if (raw_adc > 8191)
+      raw_adc -= 16384;
+  } else if (params.resolution == 12) {
+    raw_adc = ((msb & 0b00001111) << 8) | lsb;
+    if (raw_adc > 2047)
+      raw_adc -= 4096;
+  }
+  printf("Raw ADC Value: 0x%0X (%d)\n", raw_adc, raw_adc);
+  return raw_adc;
 }
 
 // **Interrupt handler for ADC Read Completion**
 void I2C_ADC_IRQHandler(void) {
-    if (DL_I2C_getPendingInterrupt(I2C_controller_INST) == DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER) {
-        gRxComplete = true;
-    }
+  if (DL_I2C_getPendingInterrupt(I2C_controller_INST) ==
+      DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER) {
+    gRxComplete = true;
+  }
 }
 
-
 /* Function to Convert ADC Reading to Voltage */
 uint16_t ADC_ConvertToVoltage(int16_t adc_value, ADC_PARAMS params) {
-    uint16_t measured_voltage= 0;
-    uint16_t LSB= 0;
-    uint32_t max_adc_value= 1;
-
-     switch (params.resolution) {
-        case 12:  // 12-bit
-            max_adc_value = 4095;
-            break;
-        case 14:  // 14-bit
-            max_adc_value = 16383;
-            break;
-        case 16:  // 16-bit
-            max_adc_value = 65535;
-            break;
-        default:
-            printf("Error: Unknown ADC Resolution!\n");
-            return 0;
-        }
-    measured_voltage= (((uint32_t)adc_value * ADC_VREF_MV) * 3)/max_adc_value;
-    return (uint16_t)measured_voltage;
+  uint16_t measured_voltage = 0;
+  uint16_t LSB = 0;
+  uint32_t max_adc_value = 1;
+
+  switch (params.resolution) {
+  case 12: // 12-bit
+    max_adc_value = 4095;
+    break;
+  case 14: // 14-bit
+    max_adc_value = 16383;
+    break;
+  case 16: // 16-bit
+    max_adc_value = 65535;
+    break;
+  default:
+    printf("Error: Unknown ADC Resolution!\n");
+    return 0;
+  }
+  measured_voltage = (((uint32_t)adc_value * ADC_VREF_MV) * 3) / max_adc_value;
+  return (uint16_t)measured_voltage;
 }
 
 /* Function to Convert ADC Reading to Voltage */
 uint16_t ADC_ConvertToCurrent(int16_t adc_value, ADC_PARAMS params) {
-    int16_t current_mA= 0;
-    //uint8_t r_shunt= 0.1;
-    //Convert ADC value to voltage across shunt resistor:
-    uint16_t voltage_mV= ADC_ConvertToVoltage(adc_value, params);
-    uint8_t gain_multiplier= (1 <<(params.gain - 1));
-    //Convert voltage drop across shunt resistor to current
-    current_mA= (voltage_mV)/ (0.1 * gain_multiplier);
-    //printf("Converted Current: %d mA.\n", current_mA);
-    return (int16_t)current_mA;
-}
-
-void Battery_UpdateVoltage(ADC_PARAMS params){
-    for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
-        //CH1: Voltage Setup
-        params.channel= 1;
-        int16_t raw_adc_voltage= ADC_ReadData(slot, params);
-        batteries[slot].voltage= ADC_ConvertToVoltage(raw_adc_voltage, params);   
-        printf("Battery Voltage for slot %d is %u mV.\n", slot, batteries[slot].voltage);
-        }
-
+  int16_t current_mA = 0;
+  // uint8_t r_shunt= 0.1;
+  // Convert ADC value to voltage across shunt resistor:
+  uint16_t voltage_mV = ADC_ConvertToVoltage(adc_value, params);
+  uint8_t gain_multiplier = (1 << (params.gain - 1));
+  // Convert voltage drop across shunt resistor to current
+  current_mA = (voltage_mV) / (0.1 * gain_multiplier);
+  // printf("Converted Current: %d mA.\n", current_mA);
+  return (int16_t)current_mA;
 }
 
-void Battery_UpdateCurrent(ADC_PARAMS params){
-    for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
-        //CH2: Charge Current
-        params.channel= 2;
-        int16_t raw_adc_current= ADC_ReadData(slot, params);
-        batteries[slot].current= ADC_ConvertToCurrent(raw_adc_current, params);
-        printf("Battery current for slot %d is %u mA.\n", slot, batteries[slot].current);
-        }
-
-}
-
-void Battery_UpdateADCReading(){
-    ADC_PARAMS adc_params;
-
-    // For Channel 1: Voltage
-    adc_params.channel= 1;
-    adc_params.resolution= 12;
-    adc_params.continuous= 0;
-    adc_params.gain= 1;
-    ADC_SetConfigurationBytes(adc_params);
-    delay_cycles(50000);
-    for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
-        int16_t raw_adc_voltage= ADC_ReadData(slot, adc_params);
-        batteries[slot].voltage= ADC_ConvertToVoltage(raw_adc_voltage, adc_params);   
-        printf("Battery Voltage for slot %d is %u mV.\n", slot, batteries[slot].voltage);
-        }
-
-    //For Channel 2: Current
-    adc_params.channel= 2;
-    ADC_SetConfigurationBytes(adc_params);
-    delay_cycles(50000);
-
-    for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
-        int16_t raw_adc_current= ADC_ReadData(slot, adc_params);
-        batteries[slot].current= ADC_ConvertToCurrent(raw_adc_current, adc_params);
-        printf("Battery current for slot %d is %u mA.\n", slot, batteries[slot].current);
-        }
+void Battery_UpdateADCReading(uint8_t slot, uint8_t channel) {
+  while (adc_state != ADC_STATE_DONE) {
+    switch (adc_state) {
+
+    case ADC_STATE_CONFIGURE:
+      adc_params.channel = channel;
+      // printf("Channel: %d\n", adc_params.channel);
+      adc_params.resolution = 12;
+      adc_params.continuous = 1;
+      adc_params.gain = 1;
+      ADC_SetConfigurationBytes(adc_params);
+      adc_state = ADC_STATE_WAIT;
+      break;
+
+    case ADC_STATE_WAIT:
+      if (ADC_CheckReadyBit(slot, adc_params)) {
+        adc_state = ADC_STATE_READ;
+      }
+      break;
+
+    case ADC_STATE_READ:
+      if (channel == 0) {
+
+        int16_t raw_adc_voltage = ADC_ReadData(slot, adc_params);
+        batteries[slot].voltage =
+            ADC_ConvertToVoltage(raw_adc_voltage, adc_params);
+        printf("Battery voltage for slot %d is %u mV.\n", slot,
+               batteries[slot].voltage);
+        adc_state = ADC_STATE_DONE;
+
+      } else if (channel == 1) {
+
+        int16_t raw_adc_current = ADC_ReadData(slot, adc_params);
+        batteries[slot].current =
+            ADC_ConvertToCurrent(raw_adc_current, adc_params);
+        printf("Battery current for slot %d is %u mA.\n", slot,
+               batteries[slot].current);
+
+        adc_state = ADC_STATE_DONE;
+
+      }
+      break;
+    default:
+      channel = 0;
+      adc_state = ADC_STATE_CONFIGURE;
+      break;
+    }
+  }
 
+  adc_state = ADC_STATE_CONFIGURE;
 }
-    

+ 12 - 2
adc.h

@@ -2,11 +2,13 @@
 #ifndef ADC_H_
 #include "ti/driverlib/dl_i2c.h"
 #include "ti_msp_dl_config.h"
-
+#include "battery.h"
 #define ADC_TARGET_BASE_ADDRESS (0x68)
 #define ADC_VREF_MV (2048)
 #define DELAY (100000) //define timeout limit
 
+//defining the configurations
+
 //Maximum packet sizes
 #define I2C_TX_MAX_PACKET_SIZE (16)
 #define I2C_RX_MAX_PACKET_SIZE (16)
@@ -21,6 +23,14 @@ extern uint8_t gRxPacket[I2C_RX_MAX_PACKET_SIZE];
 extern uint32_t gTxADClen, gTxADCcount;
 extern uint32_t gRxADClen, gRxADCcount;
 
+//ADC states
+typedef enum{
+    ADC_STATE_CONFIGURE,
+    ADC_STATE_WAIT,
+    ADC_STATE_READ,
+    ADC_STATE_DONE
+}ADC_MeasurementState;
+
 typedef struct{
     uint8_t channel;
     uint8_t resolution;
@@ -34,6 +44,6 @@ bool ADC_CheckReadyBit(uint8_t slot_id, ADC_PARAMS params);
 int16_t ADC_ReadData(uint8_t slot_id, ADC_PARAMS params);
 void Battery_UpdateVoltage(ADC_PARAMS params);
 void Battery_UpdateCurrent(ADC_PARAMS params);
-void Battery_UpdateADCReading();
+void Battery_UpdateADCReading(uint8_t slot, uint8_t channel);
 
 #endif

+ 6 - 1
battery.h

@@ -1,12 +1,14 @@
 #ifndef BATTERY_H
 #define BATTERY_H
-#include <stdint.h>
 
+#include <stdint.h>
 //define macro to be used by multiple files in the program witout the variable being overwritten
 //for testing
 #define NUM_SLOTS (1)
 #define BATTERY_THRESHOLD (50)
+#define ADC_CHANNEL_NUM (2)
 
+//Battery states
 typedef enum{
     STATE_EMPTY= 0x01,
     STATE_BATTERY_DETECTED= 0x02,
@@ -15,11 +17,14 @@ typedef enum{
     STATE_OVERCHARGING= 0x05
 } BatteryState;
 
+
+
 //Battery Structure
 
 typedef struct{
     uint8_t slot_id;
     BatteryState state;
+    uint8_t channel;
     uint16_t voltage;
     int16_t current;
     uint16_t temperature;

+ 32 - 12
cc_cv_charging.c

@@ -1,3 +1,10 @@
+/*
+* MIN_VOLTAGE_MV, MAXIMUM_VOLTAGE will be replaced by the value a slot gets from Pi
+* Article referred: 
+* https://www.monolithicpower.com/learning/resources/battery-charger-fundamentals
+* https://www.instructables.com/Programming-a-Lithium-ion-Battery-Charger-Using-a-/
+*/
+
 #include "cc_cv_charging.h"
 #include "battery.h"
 #include "dac.h"
@@ -6,13 +13,14 @@
 #include "ti/driverlib/dl_gpio.h"
 #include <stdio.h>
 
-
+//#define BATTERY_CAPACITY_MAH (2000)
 #define MAX_VOLTAGE_MV (4200)
 #define MIN_VOLTAGE_MV (3000)
 #define CC_CURRENT_LIMIT_MA (500)
 #define CUTOFF_CURRENT_MA (50)
 #define MAX_CYCLES (2)
-
+#define CONSTANT_VALUE (1)
+#define SHUNT_RESISTOR (0.1)
 
 //********** Not used **************************
 // if the battery is deeply discharged then 50mA of trickle charge is given for a set timer
@@ -20,20 +28,19 @@
 //#define TRICKLE_CHARGE_VOLTAGE_MV (2100)
 //#define TRICKLE_CHARGE_TIMEOUT_MS (5000) //5 mseconds
 
+
 //Pre Charge
-#define BATTERY_CAPACITY_MAH (2000)
-#define PRE_CHARGE_CURRENT_MA (BATTERY_CAPACITY_MAH/ 10)
 
+//#define PRE_CHARGE_CURRENT_MA (BATTERY_CAPACITY_MAH/ 10)
 static ChargingState charging_state= STATE_PRE_CHARGE;
 static uint16_t cycle_count= 0;
 static uint32_t pre_charge_start_time= 0;
-//batt_voltage and current as stored from ADC
 
+//Functions for Charging and Discharging
 
 void CC_CV_UpdateChargingState(uint8_t slot_id){
     uint16_t batt_voltage= batteries[slot_id].voltage;
     int16_t batt_current= batteries[slot_id].current;
-
     if(batt_voltage < MIN_VOLTAGE_MV){
         charging_state= STATE_PRE_CHARGE;
     }
@@ -81,31 +88,44 @@ void CC_CV_ControlCharging(uint8_t slot_id){
     CC_CV_UpdateChargingState(slot_id);
     uint16_t batt_voltage= batteries[slot_id].voltage;
     int16_t batt_current= batteries[slot_id].current;
-    
+    uint16_t batt_cutoff_current= batteries[slot_id].cut_off_current;
+    uint16_t charge_current_mA= (batteries[slot_id].capacitance * batteries[slot_id].charge_fraction)/100;
+    int16_t dac_channel_VoutA;
+
     switch(charging_state){
         
         case STATE_PRE_CHARGE:
             DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
-            DAC_fastWrite(CHANNEL_A_VALUE);
-            printf("[CC-CV] Pre Charging: Slot %d at %d mA.\n", slot_id, PRE_CHARGE_CURRENT_MA);
+            uint16_t pre_charge_current_limit_ma = charge_current_mA/10;
+            DAC_fastWrite(pre_charge_current_limit_ma);
+            printf("[CC-CV] Pre Charging: Slot %d at %d mA.\n", slot_id, pre_charge_current_limit_ma);
             break;
         
         case STATE_CC_CHARGING:
             DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
-            DAC_fastWrite(CHANNEL_A_VALUE);
+            DAC_fastWrite(charge_current_mA);
             printf("[CC-CV] CC Charging: Slot %d at %d mA.\n", slot_id, CC_CURRENT_LIMIT_MA);
             break;
         
         case STATE_CV_CHARGING:
             DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
-            DAC_fastWrite(CHANNEL_A_VALUE);
+            if(batt_current >= batt_cutoff_current+BATTERY_THRESHOLD){
+                //Reducing by 5%
+                dac_channel_VoutA= (batt_current - (batt_current-0.05));
+            }
+            else{
+                dac_channel_VoutA= 0;
+                charging_state= STATE_FINAL_DISCHARGE;
+            }
+            DAC_fastWrite(dac_channel_VoutA);
             printf("[CC-CV] CV Charging: Slot %d at %d mA.\n", slot_id, CUTOFF_CURRENT_MA);
             break;
         
         case STATE_DISCHARGING:
             DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
             DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
-            DAC_fastWrite(CHANNEL_A_VALUE);
+            //still unsure about the value for channel VoutA:
+            DAC_fastWrite(batt_voltage);
             printf("[CC-CV] Discharging: Slot %d at %d mA.\n", slot_id, batt_voltage);
             break;
 

+ 48 - 1
dac.c

@@ -26,7 +26,7 @@ bool DAC_fastWrite(uint16_t channel_a_value){
     /*DAC has a 12 bit resolution that ranges from 0 to 4095.
     0x00: sets the Power Mode to NORMAL for Channel A
     (channel_a_value >> 8): shifts the value to 8 places right and gives upper 4 bits
-    VoutA channel, rest channels are ll powered down
+    VoutA channel, rest channels are powered down
     */
 
     uint8_t output_buffer[8];
@@ -66,3 +66,50 @@ bool DAC_fastWrite(uint16_t channel_a_value){
     return true;
 
 }
+
+/*
+LDAC pin is set to HIGH or LOW
+LDAC "HIGH": until the end of the positive pulse of the 8th clock of the 2nd byte
+LDAC "LOW": negative pulse of the 8th clock of the 2nd byte and stays low until the rising edge of the 9th clock of the 3rd byte
+LDAC pin resumes normal function after STOP bit
+Device address of 0x60 till 0x67, default is 0x60
+*/
+
+void ldac_pin_init(){
+    //Default set to HIGH
+    DL_GPIO_setPins(LDAC_PIN_PORT, LDAC_PIN_PIN_PA8_PIN);
+}
+
+void set_ldac(bool level){
+    if(level){
+        // Set LDAC Pins HIGH
+        DL_GPIO_setPins(LDAC_PIN_PORT, LDAC_PIN_PIN_PA8_PIN);
+    }
+    else{
+        // Set LDAC Pins LOW
+        DL_GPIO_clearPins(LDAC_PIN_PORT, LDAC_PIN_PIN_PA8_PIN);
+    }
+}
+/*General Call Read Address: Command to read I2C address bits of the device*/
+uint8_t DAC_ReadCurrentAddress(){
+    uint8_t current_address= 0;
+    //General call address bits
+    uint8_t command= 0xC3;
+    while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
+
+    //Send General Call Read Address Command
+    DL_I2C_startControllerTransfer(I2C_controller_INST, I2C_GENERAL_CALL_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, 1);
+    DL_I2C_fillControllerTXFIFO(I2C_controller_INST, &command, 1);
+
+    while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
+
+    //Read the response (Current DAC I2C address)
+    DL_I2C_startControllerTransfer(I2C_controller_INST, I2C_GENERAL_CALL_ADDR, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
+    current_address= DL_I2C_receiveControllerData(I2C_controller_INST);
+
+    //Debug
+    printf("Current DAC I2C Address: 0x%02X\n", current_address);
+    return current_address;
+}
+
+

+ 2 - 0
dac.h

@@ -5,8 +5,10 @@
 
 #define DAC_TARGET_BASE_ADDRESS (0x60)
 #define CHANNEL_A_VALUE (800) // in mAmps
+#define I2C_GENERAL_CALL_ADDR  0x00
 
 bool DAC_fastWrite(uint16_t channel_a_value);
 void DAC_UpdateOutput();
+uint8_t DAC_ReadCurrentAddress();
 
 #endif

+ 14 - 0
dynamic_i2c_addressing_mcu.c

@@ -0,0 +1,14 @@
+#include <stdint.h>
+#include <stdio.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"
+
+/*
+LDAC pin is set to HIGH or LOW
+LDAC "HIGH": until the end of the positive pulse of the 8th clock of the 2nd byte
+LDAC "LOW": negative pulse of the 8th clock of the 2nd byte and stays low until the rising edge of the 9th clock of the 3rd byte
+LDAC pin resumes normal function after STOP bit
+*/
+

+ 26 - 34
i2c_controller.c

@@ -93,6 +93,7 @@ void I2C_controller_INST_IRQHandler(void)
                 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:
@@ -154,11 +155,12 @@ void I2C_target_INST_IRQHandler(void) {
             - 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);
+                //printf("Received Command: 0x%02X\n", receivedCommand);
 
                 if (receivedCommand == CMD_GET_BATTERY_STATUS){
                     printf("Battery status received.\n");
@@ -174,7 +176,8 @@ void I2C_target_INST_IRQHandler(void) {
                     }
                     //Filling up the FIFO
                     if(piTxCount < piTxLen){
-                        while (DL_I2C_getTargetStatus(I2C_target_INST) & DL_I2C_TARGET_STATUS_BUS_BUSY);
+                        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 {
@@ -189,8 +192,9 @@ void I2C_target_INST_IRQHandler(void) {
                 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);
+                    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;
@@ -217,7 +221,7 @@ void I2C_target_INST_IRQHandler(void) {
                             }
 
                         } else{
-                            printf("Invalid Slot ID: %d\n.", requestedSlot);
+                            //printf("Invalid Slot ID: %d\n.", requestedSlot);
                         }
                     
                 }
@@ -246,7 +250,7 @@ void I2C_target_INST_IRQHandler(void) {
             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);
+                //printf("Received Command: 0x%02X\n", receivedCommand);
                 if(receivedCommand == CMD_SET_BATTERY_LIMIT){
                 uint8_t rx_buffer[sizeof(BatteryLimitMsg)];
                 uint8_t index= 0;
@@ -254,7 +258,7 @@ void I2C_target_INST_IRQHandler(void) {
                 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]); 
+                        //printf("Received Byte[%d]: 0x%02X\n", index, rx_buffer[index]); 
                         index++;
                         
                     }
@@ -263,10 +267,10 @@ void I2C_target_INST_IRQHandler(void) {
                     }
                 }
 
-                printf("Total Bytes Received: %d (Expected: %d)\n", index, sizeof(BatteryLimitMsg));
+                //printf("Total Bytes Received: %d (Expected: %d)\n", index, sizeof(BatteryLimitMsg));
 
                 if(index == sizeof(BatteryLimitMsg)){
-                    printf("Received Battery Limits.\n");
+                    //printf("Received Battery Limits.\n");
                     BatteryLimitMsg battery_limits;
                     memcpy(&battery_limits, rx_buffer, sizeof(BatteryLimitMsg));
                     if(battery_limits.slot_id < NUM_SLOTS){
@@ -276,12 +280,12 @@ void I2C_target_INST_IRQHandler(void) {
                         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("\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);
+                        printf("  Charge Fraction:  %d%% (0x%02X)\n", battery_limits.charge_fraction, battery_limits.charge_fraction);*/
                     }
                 }
 
@@ -312,44 +316,32 @@ int main(void)
     Battery_Init();
     
     //Reset_I2C_Bus();
-    //NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
+    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_scanBus();
     I2C_init(&gI2C);
-
-    // *Configure ADC for voltage: Channel 1 and Channel 2*
-    /*ADC_PARAMS adc_voltage_params={
-        .channel= 1,
-        .resolution= 12,
-        .continuous= 1,
-        .gain= 1
-    };
-    
-    ADC_PARAMS adc_current_params={
-        .channel= 2,
-        .resolution= 12,
-        .continuous= 1,
-        .gain= 1
-    };*/
-    
     
     //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
-        Battery_UpdateADCReading();
-        delay_cycles(100000);
-          
-        //Battery_UpdateCurrent(adc_current_params);
-        //delay_cycles(50000);
+        /*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++){

+ 6 - 0
i2c_controller.syscfg

@@ -14,6 +14,7 @@ const CRC   = scripting.addModule("/ti/driverlib/CRC");
 const GPIO  = scripting.addModule("/ti/driverlib/GPIO", {}, false);
 const GPIO1 = GPIO.addInstance();
 const GPIO2 = GPIO.addInstance();
+const GPIO3 = GPIO.addInstance();
 const I2C   = scripting.addModule("/ti/driverlib/I2C", {}, false);
 const I2C1  = I2C.addInstance();
 const I2C2  = I2C.addInstance();
@@ -41,6 +42,11 @@ GPIO2.associatedPins[0].pin.$assign = "PB8";
 GPIO2.associatedPins[1].$name       = "PIN_PB12";
 GPIO2.associatedPins[1].pin.$assign = "PB12";
 
+GPIO3.$name                         = "LDAC_PIN";
+GPIO3.port                          = "PORTA";
+GPIO3.associatedPins[0].$name       = "PIN_PA8";
+GPIO3.associatedPins[0].pin.$assign = "PA8";
+
 I2C1.basicEnableController             = true;
 I2C1.advControllerTXFIFOTRIG           = "BYTES_1";
 I2C1.advAnalogGlitchFilter             = "DISABLED";