Jelajahi Sumber

dac and pwm working; adc channel 2 is not yet working

namrota ghosh 8 bulan lalu
induk
melakukan
69fb32fa12

+ 7 - 16
main_target.c

@@ -7,13 +7,8 @@
 #include "src/peripherals/adc/adc_interface.h"
 #include "src/i2c_comm/mcu_slave_interface.h"
 
-/*
-DL_TimerG_startCounter(PWM_0_INST);
-DL_TimerA_setCaptureCompareValue(PWM_1_INST, pwm_count,
-                                     DL_TIMER_CC_0_INDEX); // update ccr0 value
-*/
 
-#define DELAY_CYCLE  (10000000)
+#define DELAY_CYCLE  (100000000)
 
 volatile bool mcu_CommandPending= false;
 
@@ -73,6 +68,7 @@ void I2C_controller_INST_IRQHandler(void) {
     
     case DL_I2C_IIDX_CONTROLLER_START:
         gRxADCcount = 0;
+        
         DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
         break;
 
@@ -82,6 +78,7 @@ void I2C_controller_INST_IRQHandler(void) {
             if (gRxADCcount < gRxADClen) {
                 gRxPacket[gRxADCcount] =
                     DL_I2C_receiveControllerData(I2C_controller_INST);
+                    ;
                 gRxADCcount++;
 
             } else {
@@ -159,32 +156,26 @@ int main(void)
 {   
     SYSCFG_DL_init();
     Battery_Init();
+    //I2C_scanBus(I2C_controller_INST);
     NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
     NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
-
-
-    /*printf("&gRxPacket:     %p\n", (void*)gRxPacket);
-    printf("&batteries[0]:  %p\n", (void*)&batteries[0]);
-    printf("&gRxADClen:     %p\n", (void*)&gRxADClen);
-    printf("&gTxPacket:     %p\n", (void*)gTxPacket);
-    printf("&gTxADClen:     %p\n", (void*)&gTxADClen);
-    */
     
-    //printf("Memory address of batteries: %p\n", &batteries[0]);
     while (1) {
 
         if(mcu_CommandPending){
+            printf("Step 1: Calling MCU target interrupt\n");
             mcu_i2c_handle(I2C_target_INST);
             mcu_CommandPending= false;
             continue;
         }
         
-        for(uint8_t slot= 0; slot< NUM_SLOTS; slot++){
+        /*for(uint8_t slot= 0; slot< NUM_SLOTS; slot++){
             for(uint8_t channel= 0; channel< 2; channel++){
                 updateADCReading_multichannel(slot, channel);
             }
         }
         
         delay_cycles(DELAY_CYCLE);
+        */
     }
 }

+ 1 - 1
main_target.syscfg

@@ -63,7 +63,7 @@ I2C2.sclPinConfig.enableConfig         = true;
 
 PWM1.$name                      = "PWM_0";
 PWM1.ccIndex                    = [0];
-PWM1.timerCount                 = 400;
+PWM1.timerCount                 = 320;
 PWM1.peripheral.ccp0Pin.$assign = "PA26";
 PWM1.PWM_CHANNEL_0.$name        = "ti_driverlib_pwm_PWMTimerCC0";
 PWM1.PWM_CHANNEL_0.dutyCycle    = 10;

+ 53 - 9
src/i2c_comm/mcu_slave_interface.c

@@ -1,23 +1,27 @@
 /*
-References: https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c
+References:
+https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c
 
 */
 
-#include "src/battery_data/battery.h"
 #include "mcu_slave_interface.h"
+#include "src/battery_data/battery.h"
 #include "ti/driverlib/dl_i2c.h"
 #include <stdio.h>
 #include <string.h>
+#include "src/peripherals/dac/dac.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");
+  printf("MCU interrupt triggered\n");
   uint8_t receivedCommand = DL_I2C_receiveTargetData(i2c);
-  //printf("[SLAVE] Received Command: 0x%02X\n", receivedCommand);
+  printf("[SLAVE] Received Command: 0x%02X\n", receivedCommand);
   uint8_t tx_buffer[8] = {0};
-  //changed to volatile variable, so that the compiler cannot optimize the variable out and is forced to do as told by the code
+  // 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[8] = {0};
   /*Handling GET commands with bitmasking*/
   // GET command for ADC(Battery Measurement): Voltage, Current, Temperature
@@ -29,9 +33,9 @@ void mcu_i2c_handle(I2C_Regs *i2c) {
     }
     // Struct for voltage, current and temperature
     BatteryMeasurementData battery_measure;
-    //Battery *battery= &batteries[slot];
-    // take the updated battery measurement from the battery struct and store it
-    // in the battery_measure struct
+    // Battery *battery= &batteries[slot];
+    //  take the updated battery measurement from the battery struct and store
+    //  it in the battery_measure struct
     battery_measure.voltage = batteries[slot].voltage;
     battery_measure.current = batteries[slot].current;
     battery_measure.temperature = batteries[slot].temperature;
@@ -40,6 +44,46 @@ void mcu_i2c_handle(I2C_Regs *i2c) {
     DL_I2C_fillTargetTXFIFO(i2c, tx_buffer, sizeof(BatteryMeasurementData));
     printf("Battery Measurement Sent to MCU. \n");
     DL_I2C_flushTargetTXFIFO(i2c);
+  } 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);
+        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));
+    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) {
+      DAC_SingleWrite(current);
+    } else if (current < 0) {
+        
+        DL_TimerG_startCounter(PWM_0_INST);
+        DL_TimerG_setCaptureCompareValue(PWM_0_INST, -1*current, DL_TIMER_CC_0_INDEX); // update ccr0 value
+        //DL_TimerG_setCaptureCompareValue(PWM_0_INST, 1000, DL_TIMER_CC_1_INDEX); 
+
+    } else {
+      // do nothing, charge or discharge
+      printf("state is idle");
+    }
+
   }
-  
 }

+ 1 - 0
src/i2c_comm/mcu_slave_interface.h

@@ -18,6 +18,7 @@ typedef enum{
 typedef struct{
     uint8_t slot_id;
     int16_t current;
+    
 }SetChargeDischargeCurrent;
 
 typedef struct __attribute__((packed)){

+ 6 - 0
src/interfaces/i2c_hal.c

@@ -14,6 +14,7 @@ is restricted to the file where they are declared const keyword for
 'TARGET_ADDRESS' and 'Data_length' makes the variable immutable. const uint8_t *
 const Data: means the pointer to the variable and the value of Data is immutable
 */
+
 static bool msp_i2c_write(uint8_t const TARGET_ADDRESS,
                           const uint8_t *const Data,
                           uint8_t const Data_length) {
@@ -70,6 +71,11 @@ static bool msp_i2c_read(uint8_t const TARGET_ADDRESS,
                          uint8_t const Data_length) {
 
   
+ // Flush any stale data in TX FIFO:
+  DL_I2C_flushControllerRXFIFO(I2C_controller_INST);
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
   DL_I2C_startControllerTransfer(I2C_controller_INST, TARGET_ADDRESS,
                                  DL_I2C_CONTROLLER_DIRECTION_RX, Data_length);
 

+ 4 - 2
src/peripherals/adc/adc.c

@@ -18,11 +18,13 @@ void updateADCReading_multichannel(uint8_t slot, uint8_t channel) {
         case ADC_STATE_CONFIGURE:
             adc_params.channel = channel;
             adc_params.resolution = 12;
-            adc_params.continuous = 0;
+            //adc_params.continuous = 1;
             adc_params.gain = 1;
             //printf("Config: Memory address of batteries: %p\n", &batteries[0]);
             adc_hal.configure(slot, &adc_params);
-            adc_state = ADC_STATE_WAIT;
+            delay_cycles(500000);
+            //adc_state = ADC_STATE_WAIT;
+            adc_state = ADC_STATE_READ;
             break;
 
         case ADC_STATE_WAIT:

+ 20 - 6
src/peripherals/adc/adc_hal.c

@@ -73,7 +73,8 @@ static uint8_t construct_config_byte(ADC_Params *params) {
   config |= ((params->channel) << 5); // Channel Selection (Bits 6-5)
   
 
-  config |= (1 << 4); // One-Shot Mode
+  config |= (1 << 4); // Continous mode
+  //config |= (1 << 7); // One-Shot Mode: enable measurement (set read/not ready byte)
   
   
   switch (params->resolution) {
@@ -159,13 +160,19 @@ static bool adc_is_ready(uint8_t slot_id, ADC_Params *params) {
   gRxADClen = 3;
   gRxADCcount = 0;
   gRxComplete = false;
+
+  gRxPacket[0] = 0;
+  gRxPacket[1] = 0;
+  gRxPacket[2] = 0;
+
   i2c_hal.read(adc_address, gRxADClen);
   //i2c_hal.read(ADC_TARGET_BASE_ADDRESS + slot_id, 3);
   // Ready bit is bit 7
   while(!gRxComplete);
-  printf("ADC Ready:: gRxADClen: %d, gRxADCcount: %d\n", gRxADClen, gRxADCcount);
   uint8_t config_adc_byte = gRxPacket[2];
-  bool ready = (config_adc_byte & 0x80) == 0;
+  bool ready = (config_adc_byte & 0x80) == 1;
+  printf("Bytes: 0x%02X 0x%02X 0x%02X (%d %d %d)\n", gRxPacket[0], gRxPacket[1],  gRxPacket[2], gRxPacket[0], gRxPacket[1],  gRxPacket[2]);
+  printf("ADC Ready:: gRxADClen: %d, gRxADCcount: %d ready? %d\n", gRxADClen, gRxADCcount, ready);
   return ready;
 }
 
@@ -178,20 +185,27 @@ static int16_t read_adc_raw_data(uint8_t slot_id, ADC_Params *params) {
   gRxADClen = 3;
   gRxADCcount = 0;
   gRxComplete = false;
+
+  gRxPacket[0] = 0;
+  gRxPacket[1] = 0;
+  gRxPacket[2] = 0;
+  
   i2c_hal.read(ADC_TARGET_BASE_ADDRESS + slot_id, gRxADClen);
   while(!gRxComplete);
   printf("ADC Read:: gRxADClen: %d, gRxADCcount: %d\n", gRxADClen, gRxADCcount);
+  printf("Bytes: 0x%02X 0x%02X 0x%02X (%d %d %d)\n", gRxPacket[0], gRxPacket[1],  gRxPacket[2], gRxPacket[0], gRxPacket[1],  gRxPacket[2]);
   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 == 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);
+  printf("MSB: 0x%02X (%d)\n", msb, msb);
+  printf("LSB: 0x%02X (%d)\n", lsb, lsb);
+  printf("Config Byte response: 0x%02X \n", config_adc_byte);
   return raw_adc;
 }
 

+ 1 - 1
src/peripherals/adc/adc_interface.h

@@ -25,7 +25,7 @@ extern uint8_t gRxADClen, gRxADCcount;
 typedef struct {
     uint8_t channel;
     uint8_t resolution;
-    bool continuous;
+    //bool continuous;
     uint8_t gain;
 } ADC_Params;
 

+ 62 - 0
src/peripherals/dac/dac.c

@@ -0,0 +1,62 @@
+#include "dac.h"
+#include "src/interfaces/i2c_controller_interface.h"
+#include "ti/driverlib/dl_i2c.h"
+#include "ti_msp_dl_config.h"
+#include <stdint.h>
+#include <stdio.h>
+
+
+// The device updates all DAC analog output(vout) at the same time
+
+void DAC_UpdateOutput() {
+  uint8_t general_call_command = 0x08; // General Call Update Command
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
+
+  // Start I2C transaction
+  DL_I2C_startControllerTransfer(I2C_controller_INST, 0x00,
+                                 DL_I2C_CONTROLLER_DIRECTION_TX, 1);
+
+  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
+         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
+    ;
+
+  DL_I2C_fillControllerTXFIFO(I2C_controller_INST, &general_call_command, 1);
+
+  //printf("DAC Outputs Updated via General Call Software Update!\n");
+}
+
+
+bool DAC_SingleWrite(uint16_t channel_value) {
+  if(channel_value > 4095){
+    printf("DAC Error: channel_value out of range. Must be between 0 and 4095\n");
+    return false;
+  }
+  uint8_t data_length = 3;
+  uint8_t output_buffer_SingleWrite[data_length];
+  output_buffer_SingleWrite[0] = 0x58; //0x58 for Channel 0; 0x5A for Channel 1
+  printf("((channel_value >> 8) & 0x0F): 0x%02X", ((channel_value >> 8) & 0x0F));
+  output_buffer_SingleWrite[1] = (0x10) | ((channel_value >> 8) & 0x0F);
+  output_buffer_SingleWrite[2] = (channel_value & 0xFF);
+
+
+  // Log data being sent
+  printf("Sending to DAC: 0x%02X 0x%02X 0x%02X\n",
+           output_buffer_SingleWrite[0],
+           output_buffer_SingleWrite[1],
+           output_buffer_SingleWrite[2]);
+
+  // Write data to DAC
+  if (!i2c_hal.write(DAC_TARGET_BASE_ADDRESS, output_buffer_SingleWrite, data_length)) {
+        printf("I2C DAC Write Error: Failed to write to DAC.\n");
+        return false;
+    }
+
+  DAC_UpdateOutput();
+
+  printf("Output_Buffer_1: 0x%02X, Output_Buffer_2: 0x%02X\n", output_buffer_SingleWrite[1], output_buffer_SingleWrite[2]);
+
+  return true;
+
+}

+ 11 - 0
src/peripherals/dac/dac.h

@@ -0,0 +1,11 @@
+#ifndef DAC_H_
+#include "ti/driverlib/dl_i2c.h"
+#include "ti_msp_dl_config.h"
+#include <stdbool.h>
+
+#define DAC_TARGET_BASE_ADDRESS (0x60)
+#define DAC_VREF_MV 2048
+
+bool DAC_SingleWrite(uint16_t channel_value);
+
+#endif