i2c_controller.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. Main Source File
  3. */
  4. #include "adc.h"
  5. #include "battery.h"
  6. #include "cc_cv_charging.h"
  7. #include "dac.h"
  8. #include "i2c_target.h"
  9. #include "multiplexer.h"
  10. #include "ti/comm_modules/i2c/controller/i2c_comm_controller.h"
  11. #include "ti/devices/msp/peripherals/hw_dac12.h"
  12. #include "ti/driverlib/dl_adc12.h"
  13. #include "ti/driverlib/dl_gpio.h"
  14. #include "ti/driverlib/dl_i2c.h"
  15. #include "ti/driverlib/m0p/dl_core.h"
  16. #include "ti_msp_dl_config.h"
  17. #include <stdint.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <ti/drivers/GPIO.h>
  21. I2C_Instance gI2C;
  22. I2C_ResponseInfo gResponse;
  23. BatteryData battery_data;
  24. /*Interrupt for MCU -> ADC
  25. * CASE: DL_I2C_IIDX_CONTROLLER_RX_DONE: ADC Reception Complete
  26. - ADC has finished sending data and it's fully received.
  27. - gI2C.rxMsg.len = gI2C.rxMsg.ptr:
  28. - Stores the received data length in the response buffer.
  29. - I2C_decodeResponse():
  30. - Decodes the received response.
  31. - gI2C.status = I2C_STATUS_RX_COMPLETE:
  32. - Marks reception is complete.
  33. * CASE: DL_I2C_IIDX_CONTROLLER_TX_DONE: Data Transmit to ADC complete
  34. - DL_I2C_disableInterrupt(..): Disables the TXFIFO interrupt since data is
  35. now sent
  36. * CASE: DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER: Receive Data in FIFO
  37. - The I2C Receive FIFO has data ready to be read.
  38. - while (DL_I2C_isControllerRXFIFOEmpty(...) != true): Loops until the RX
  39. FIFOis empty (READ all available bytes)
  40. - Inside the while loop:
  41. - If buffer has SPACE, store the received byte
  42. - Prints each received byte in HEXADECIMAL format for debugging
  43. - IF BUFFER is FULL, avoids OVERFLOW by discarding extra byte.
  44. * CASE: DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER: Transmit Data in FIFO
  45. - If there is still data to send:
  46. gI2C.txMsg.ptr += DL_I2C_fillControllerTXFIFO(I2C_controller_INST,
  47. &gI2C.txMsg.buffer[gI2C.txMsg.ptr], gI2C.txMsg.len - gI2C.txMsg.ptr);
  48. */
  49. void I2C_controller_INST_IRQHandler(void) {
  50. // printf("I2C Interrupt Triggered to ADC!\n");
  51. switch (DL_I2C_getPendingInterrupt(I2C_controller_INST)) { /*START Condition*/
  52. case DL_I2C_IIDX_CONTROLLER_START:
  53. // gTxADCcount= 0;
  54. gRxADCcount = 0;
  55. DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
  56. break;
  57. case DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER:
  58. gI2C.status = I2C_STATUS_RX_INPROGRESS;
  59. /* Store bytes received from target in Rx Msg Buffer */
  60. while (DL_I2C_isControllerRXFIFOEmpty(I2C_controller_INST) != true) {
  61. if (gRxADCcount < gRxADClen) {
  62. gRxPacket[gRxADCcount] =
  63. DL_I2C_receiveControllerData(I2C_controller_INST);
  64. printf("Received Byte[%d]: 0x%02X\n", gRxADCcount,
  65. gRxPacket[gRxADCcount]); // Debug print
  66. gRxADCcount++;
  67. } else {
  68. // printf("ERROR: RX Buffer Overflow! ptr=%d MAX_BUFFER_SIZE=%d\n",
  69. // gI2C.rxMsg.ptr, MAX_BUFFER_SIZE);
  70. /* Ignore and remove from FIFO if the buffer is full */
  71. DL_I2C_receiveControllerData(I2C_controller_INST);
  72. }
  73. }
  74. if (gRxADCcount >= gRxADClen) {
  75. // printf("ADC Bytes Received!\n");
  76. gRxComplete = true;
  77. DL_I2C_enableInterrupt(I2C_controller_INST,
  78. DL_I2C_INTERRUPT_CONTROLLER_STOP);
  79. }
  80. break;
  81. /*TRANSMIT data to ADC*/
  82. case DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER:
  83. // printf("TX FIFO with data!\n");
  84. gI2C.status = I2C_STATUS_TX_INPROGRESS;
  85. if (gTxADCcount < gTxADClen) {
  86. gTxADCcount += DL_I2C_fillControllerTXFIFO(I2C_controller_INST,
  87. &gTxPacket[gTxADCcount],
  88. (gTxADClen - gTxADCcount));
  89. } else {
  90. /*Prevent overflow and just ignore data*/
  91. DL_I2C_fillTargetTXFIFO(I2C_controller_INST, (uint8_t[]){0x00}, 1);
  92. gTxComplete = true;
  93. }
  94. // DL_I2C_flushControllerTXFIFO(I2C_controller_INST);
  95. break;
  96. /*STOP condition*/
  97. case DL_I2C_IIDX_CONTROLLER_STOP:
  98. gTxComplete = true;
  99. gRxComplete = true;
  100. // printf("I2C Stop Detected- RX Complete");
  101. break;
  102. case DL_I2C_IIDX_CONTROLLER_ARBITRATION_LOST:
  103. // printf("Interrupt index for I2C controller Arbitration Lost!\n");
  104. break;
  105. case DL_I2C_IIDX_CONTROLLER_NACK:
  106. // printf("I2C NACK Received\n");
  107. if ((gI2C.status == I2C_STATUS_RX_STARTED) ||
  108. (gI2C.status = I2C_STATUS_TX_STARTED)) {
  109. gI2C.status = I2C_STATUS_ERROR;
  110. }
  111. break;
  112. default:
  113. break;
  114. }
  115. }
  116. /**** Interrupt for Pi to MCU ****/
  117. void I2C_target_INST_IRQHandler(void) {
  118. uint8_t receivedCommand = 0;
  119. uint8_t battery_state[8] = {0x00};
  120. uint32_t status = DL_I2C_getPendingInterrupt(I2C_target_INST);
  121. printf("status: %d\n", status);
  122. switch (status) {
  123. case DL_I2C_IIDX_TARGET_START:
  124. /*Initialize Tx or RX after Start condition is recieved*/
  125. piTxCount = 0;
  126. piRxCount = 0;
  127. piTxComplete = false;
  128. DL_I2C_flushTargetTXFIFO(I2C_target_INST);
  129. break;
  130. case DL_I2C_IIDX_TARGET_STOP:
  131. piTxComplete = true;
  132. piRxComplete = true;
  133. DL_I2C_flushTargetTXFIFO(I2C_target_INST);
  134. DL_I2C_flushTargetRXFIFO(I2C_target_INST);
  135. break;
  136. case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER:
  137. printf("Rx Interrupt Triggered \n");
  138. if (DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)) {
  139. return;
  140. }
  141. receivedCommand = DL_I2C_receiveTargetData(I2C_target_INST);
  142. if (receivedCommand == CMD_GET_BATTERY_STATUS) {
  143. printf("Received Command: 0x%02X\n", receivedCommand);
  144. for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
  145. battery_state[slot] = batteries[slot].state;
  146. }
  147. DL_I2C_fillTargetTXFIFO(I2C_target_INST, battery_state, 8);
  148. while (DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false)
  149. ;
  150. printf("Sent Data\n");
  151. }
  152. /*
  153. To receive the Battery Mesaurements from MCU, bit masking is applied
  154. where:
  155. - command type is upper 4 bits: 0010 (for CMD_GET_BATTERY_DATA)->
  156. consistent
  157. - slot_id is lower 3 bits, since NUM_SLOTS are 8 so it ranges from 000
  158. till 111
  159. - bit mask for command is 0xF0: 11110000
  160. - bit mask for requested slot is 0x07: 00000111
  161. receivedCommand now ranges from 0x20 till 0x27
  162. */
  163. else if ((receivedCommand & 0xF0) == 0x20) {
  164. //printf("Received Command: 0x%02X\n", receivedCommand);
  165. uint8_t requestedSlot = (receivedCommand & 0x07);
  166. //printf("Requested slot:%d\n", requestedSlot);
  167. // piTxCount = 0;
  168. piTxLen = sizeof(BatteryData);
  169. BatteryData battery_data;
  170. if (requestedSlot >= NUM_SLOTS) {
  171. //printf("Requested Slot is not valid.\n");
  172. DL_I2C_flushTargetTXFIFO(I2C_target_INST);
  173. return;
  174. }
  175. Battery *battery = &batteries[requestedSlot];
  176. battery_data.slot_id = battery->slot_id; // !TODO: recheck if necessary
  177. //printf("slot_id:%u\n", battery_data.slot_id);
  178. battery_data.voltage = battery->voltage;
  179. //printf("voltage:%u\n", battery_data.voltage);
  180. battery_data.current = battery->current;
  181. //printf("current:%u\n", battery_data.current);
  182. battery_data.temperature = battery->temperature;
  183. //printf("temperature:%u\n", battery_data.temperature);
  184. DL_I2C_fillTargetTXFIFO(I2C_target_INST, (uint8_t *)&battery_data,
  185. piTxLen);
  186. /*piTxComplete= true;
  187. if(piTxCount >= piTxLen){
  188. piTxComplete= true;
  189. piTxCount= 0;
  190. }*/
  191. printf("Battery Measurement Sent. \n");
  192. DL_I2C_flushTargetTXFIFO(I2C_target_INST);
  193. }
  194. else if (receivedCommand == CMD_SET_BATTERY_LIMIT) {
  195. uint8_t rx_buffer[sizeof(BatteryLimitMsg)];
  196. uint8_t index = 0;
  197. while (!DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)) {
  198. if (index < sizeof(BatteryLimitMsg)) {
  199. rx_buffer[index] = DL_I2C_receiveTargetData(I2C_target_INST);
  200. index++;
  201. } else {
  202. DL_I2C_receiveTargetData(I2C_target_INST);
  203. }
  204. }
  205. if (index == sizeof(BatteryLimitMsg)) {
  206. BatteryLimitMsg battery_limits;
  207. memcpy(&battery_limits, rx_buffer, sizeof(BatteryLimitMsg));
  208. if (battery_limits.slot_id < NUM_SLOTS) {
  209. Battery *battery = &batteries[battery_limits.slot_id];
  210. battery->min_voltage = battery_limits.min_voltage;
  211. battery->max_voltage = battery_limits.max_voltage;
  212. battery->cut_off_current = battery_limits.cut_off_current;
  213. battery->capacitance = battery_limits.capacitance;
  214. battery->charge_fraction = battery_limits.charge_fraction;
  215. }
  216. }
  217. }
  218. break;
  219. case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
  220. break;
  221. case DL_I2C_IIDX_TARGET_ARBITRATION_LOST:
  222. break;
  223. default:
  224. break;
  225. }
  226. }
  227. /********MAIN function*************/
  228. int main(void) {
  229. // Initialize System and I2C
  230. SYSCFG_DL_init();
  231. // Initialize battery array and default params
  232. Battery_Init();
  233. // Reset_I2C_Bus();
  234. NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
  235. NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
  236. printf("............System Configuration Enabled...............\n");
  237. // Multiplexer
  238. Multiplexer_SelectChannel(I2C_CHANNEL);
  239. // I2C_scanBus();
  240. I2C_init(&gI2C);
  241. // ADC_SetConfigurationBytes(adc_voltage_params);
  242. // delay_cycles(50000);
  243. // ADC_SetConfigurationBytes(adc_current_params);
  244. // delay_cycles(50000);
  245. // DAC_ReadCurrentAddress();
  246. while (1) {
  247. // Looping through the ADC Channels
  248. for (uint8_t slot_id = 0; slot_id < NUM_SLOTS; slot_id++) {
  249. for (uint8_t adc_channel = 0; adc_channel < ADC_CHANNEL_NUM;
  250. adc_channel++) {
  251. Battery_UpdateADCReading(slot_id, adc_channel);
  252. }
  253. Battery_ReadState(slot_id);
  254. }
  255. printf("Battery Details: Slot: %u, Voltage:%u, Current: %u \n, State:%u\n:",
  256. batteries[0].slot_id, batteries[0].voltage, batteries[0].current,
  257. batteries[0].state);
  258. // CC-CV Cycle: maximum cycles is not yet implemented
  259. // for(uint8_t slot_id= 0; slot_id < NUM_SLOTS; slot_id++){
  260. // CC_CV_ControlCharging(slot_id);
  261. // }
  262. // DAC_fastWrite(CHANNEL_A_VALUE);
  263. }
  264. }