controller.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #include "src/controller/controller.h"
  2. //#include "src/i2c_comm/i2c_hal.h"
  3. #include "ti/driverlib/dl_i2c.h"
  4. #include "ti/driverlib/m0p/dl_core.h"
  5. #include "ti_msp_dl_config.h"
  6. #include <stdio.h>
  7. //#include <string.h>
  8. /*
  9. * Generic Function to send data to the target controller using I2C:
  10. Format: command + ((slot_id) + data (optional))
  11. */
  12. //Send command to set charge and discharge current to the target
  13. void controller_SetCurrent(uint8_t const TARGET_ADDRESS, uint8_t slot_id, int16_t current_mA){
  14. //Bitmasked: Slot id + Command
  15. txPacket.txBuffer[0]= (slot_id<<4) | (CMD_SET_CURRENT & 0x0F);
  16. //Filling the buffer with current value
  17. *((int16_t*)(&txPacket.txBuffer[1])) = current_mA;
  18. /*I2C Communication for transmitting Charging/Discharging current for the slots*/
  19. //Length is calculated as 1 byte for the bitmasked slot and command+ 2 bytes of current + 1 byte of padding
  20. txPacket.txLen= 4;
  21. DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
  22. DL_I2C_startControllerTransfer(I2C_1_INST, TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX, txPacket.txLen);
  23. printf("Packet Sent:: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X \n", TARGET_ADDRESS, txPacket.txBuffer[0], txPacket.txBuffer[1],txPacket.txBuffer[2], txPacket.txBuffer[3]);
  24. DL_I2C_fillControllerTXFIFO(I2C_1_INST, txPacket.txBuffer, txPacket.txLen);
  25. // Wait for the bus to become not busy WITH a timeout
  26. uint32_t timeout = 10000;
  27. while ((DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) && timeout > 0) {
  28. timeout--;
  29. }
  30. printf("STATUS ***SetCurrent successful for slot %d with current %d mA***\n", slot_id, current_mA);
  31. // Clean up and exit
  32. DL_I2C_flushControllerTXFIFO(I2C_1_INST);
  33. }
  34. //Get battery measurement: Voltage, Current, Temperature including slot state:
  35. bool controller_GetBatteryMeasurement(uint8_t slot_id){
  36. //I2cControllerStatus= I2C_STATUS_IDLE;
  37. uint8_t target_address= TARGET_BASE_ADDRESS + ((slot_id & 0b00000100) >> 2);
  38. printf("Target Address 0x%02X \n", target_address);
  39. //Initializing BatteryMeasurement structure from battery.h of size 8
  40. BatteryMeasurement measurement;
  41. //Flush the TX FIFO and make the buffer ready to transmit data:
  42. //DL_I2C_flushControllerTXFIFO(I2C_1_INST);
  43. //DL_I2C_flushControllerRXFIFO(I2C_1_INST);
  44. //Write Command to the target
  45. //Set the command in the tx buffer in bit masked format to the target: Upper Nibble-> Slot and Lower Nibble -> Command
  46. //txPacket.txBuffer[0]= (slot_id << 4)|(CMD_GET_MEASUREMENT & 0x0F); //shift slot_id to the left by 4 bits
  47. txPacket.txLen= 1;
  48. //Number of bytes to be written to TX FIFO:
  49. txPacket.txCount= DL_I2C_fillControllerTXFIFO(I2C_1_INST, &txPacket.txBuffer[0] , txPacket.txLen);
  50. txPacket.txComplete= false;
  51. //DL_I2C_fillControllerTXFIFO(I2C_1_INST, &txPacket.txBuffer[0], txPacket.txLen);
  52. //Enable the interrupt:
  53. DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
  54. // Wait for the bus to be idle
  55. uint32_t timeout = 32000;
  56. while (!(DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_IDLE) && timeout--);
  57. if(timeout == 0){
  58. printf("Error in reading from I2C Bus: Bus is not getting ready before transmit start\n");
  59. DL_I2C_resetControllerTransfer(I2C_1_INST);
  60. return false;
  61. }
  62. //Send command bytes to the target
  63. //delay_cycles(10000000);
  64. DL_I2C_startControllerTransferAdvanced(I2C_1_INST, target_address, DL_I2C_CONTROLLER_DIRECTION_TX, txPacket.txLen, DL_I2C_CONTROLLER_START_ENABLE, DL_I2C_CONTROLLER_STOP_DISABLE, DL_I2C_CONTROLLER_ACK_ENABLE);
  65. printf("[I2C] TX Packet Sent:: 0x%02X\n", txPacket.txBuffer[0]);
  66. //If I2C Bus is stuck then reset the controller:
  67. if(DL_I2C_getControllerStatus(I2C_1_INST)&(DL_I2C_CONTROLLER_STATUS_ERROR)){
  68. printf("ERROR ***I2C Write Error: Bus is stuck***\n");
  69. DL_I2C_resetControllerTransfer(I2C_1_INST);
  70. return false;
  71. }
  72. // Wait until TX FIFO is empty (TX complete)
  73. timeout = 32000;
  74. while ((DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY) && timeout--);
  75. if (timeout == 0) {
  76. printf("Bus stuck during TX.\n");
  77. DL_I2C_resetControllerTransfer(I2C_1_INST);
  78. return false;
  79. }
  80. //Re-initializing te timeout value for Rx:
  81. timeout= 32000;
  82. rxPacket.rxLen= sizeof(BatteryMeasurement);
  83. rxPacket.rxComplete= false;
  84. rxPacket.rxCount= 0;
  85. //BatteryMeasurement size is 8 similar to the target side
  86. //DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
  87. //DL_I2C_startControllerTransferAdvanced(I2C_1_INST, TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_RX, rxPacket.rxLen, DL_I2C_CONTROLLER_START_ENABLE, DL_I2C_CONTROLLER_STOP_ENABLE, DL_I2C_CONTROLLER_ACK_DISABLE);
  88. //DL_I2C_startControllerTransfer(I2C_1_INST, target_address, DL_I2C_CONTROLLER_DIRECTION_RX, rxPacket.rxLen);
  89. while((DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY) && timeout--);
  90. if(timeout == 0 || (DL_I2C_getSCLStatus(I2C_1_INST)== DL_I2C_CONTROLLER_SCL_LOW)){
  91. printf("Bus stuck during Rx transmit or SCL held LOW.\n");
  92. DL_I2C_resetControllerTransfer(I2C_1_INST);
  93. return false;
  94. }
  95. //while(DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  96. //DEBUG
  97. printf("Rx Count: %d\n", rxPacket.rxCount);
  98. printf("Rx Complete: %d\n", rxPacket.rxComplete);
  99. //Check if all the data is received then store the battery limits in BatteryInfo struct:
  100. if(rxPacket.rxCount== (sizeof(BatteryMeasurement))){
  101. measurement.voltage= rxPacket.rxBuffer[0] | (rxPacket.rxBuffer[1] << 8);
  102. measurement.current= rxPacket.rxBuffer[2]|(rxPacket.rxBuffer[3] << 8);
  103. measurement.temperature = rxPacket.rxBuffer[4] | (rxPacket.rxBuffer[5] << 8);
  104. measurement.slot_state = (SlotState)(rxPacket.rxBuffer[6]);
  105. battery_data[slot_id].battery_measurement= measurement;
  106. //DEBUG
  107. printf("[I2C] Successfully read %d bytes from target 0x%02X\n", rxPacket.rxCount, target_address);
  108. printf("Voltage: %u\n", battery_data[slot_id].battery_measurement.voltage);
  109. printf("Current: %d\n", battery_data[slot_id].battery_measurement.current);
  110. printf("Temp: %u\n", battery_data[slot_id].battery_measurement.temperature);
  111. printf("Slot state: %u\n", battery_data[slot_id].battery_measurement.slot_state);
  112. return true;
  113. }
  114. return false;
  115. }
  116. //Clear error flag to the target to change it back to SLOT_STATE_OK
  117. //Format: command + ((slot_id) + data (optional))
  118. void controller_ClearError(uint8_t const TARGET_ADDRESS, uint8_t slot_id){
  119. uint8_t command= CMD_CLEAR_ERR| (slot_id<<4); //shift slot_id to the left by 4 bits
  120. printf("[MCU] Clear Error Bitmasked Command:: 0x%02X\n", command);
  121. txPacket.txBuffer[0]= command;
  122. txPacket.txBuffer[1]= slot_id;
  123. txPacket.txLen= sizeof(txPacket.txBuffer);
  124. while (DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  125. DL_I2C_startControllerTransfer(I2C_1_INST, TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX, txPacket.txLen);
  126. DL_I2C_fillControllerTXFIFO(I2C_1_INST, txPacket.txBuffer, txPacket.txLen);
  127. while (DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  128. DL_I2C_flushControllerTXFIFO(I2C_1_INST);
  129. }
  130. //Logic to handle Power Burning PWM on the controller side: Problem of power flow back to the device which was breaking the board has been resolved
  131. void controller_EvaluateBatterySlotState(uint8_t slot_id, BatteryMeasurement *measurement){
  132. static bool slot_sov_hov_state= false;
  133. if((measurement->slot_state== SLOT_ERR_HOV) || (measurement->slot_state == SLOT_STATE_SOV)){
  134. slot_sov_hov_state= true;
  135. if(battery_data[slot_id].pwm_value < (PWM_MAX_VALUE - PWM_INCREMENT_VALUE)){
  136. battery_data[slot_id].pwm_value+= PWM_INCREMENT_VALUE;
  137. printf("[Power Burning PWM] SOV/HOV state: Increased power burn PWM to %d\n", battery_data[slot_id].pwm_value);
  138. DL_TimerG_setCaptureCompareValue(PWM_0_INST, battery_data[slot_id].pwm_value, DL_TIMER_CC_0_INDEX);
  139. }
  140. }else if(measurement->slot_state== SLOT_STATE_OK && slot_sov_hov_state== true){
  141. if(battery_data[slot_id].pwm_value >= (INITIAL_PWM_VALUE + PWM_DECREMENT_VALUE)){
  142. battery_data[slot_id].pwm_value-= PWM_DECREMENT_VALUE;
  143. printf("[Power Burning PWM] OK state: Decreased power burn PWM to %d\n", battery_data[slot_id].pwm_value);
  144. DL_TimerG_setCaptureCompareValue(PWM_0_INST, battery_data[slot_id].pwm_value, DL_TIMER_CC_0_INDEX);
  145. }
  146. }else{
  147. printf("[Power Burning PWM] initial state: %d\n", battery_data[slot_id].pwm_value);
  148. DL_TimerG_setCaptureCompareValue(PWM_0_INST, battery_data[slot_id].pwm_value, DL_TIMER_CC_0_INDEX);
  149. }
  150. }
  151. /*bool getBatteryMeasurement_test(){
  152. //DL_I2C_flushControllerTXFIFO(I2C_1_INST);
  153. //Enable the interrupt:
  154. DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
  155. //Wait for I2C to be Idle
  156. uint32_t timeout = 10000;
  157. while (!(DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_IDLE) && timeout--);
  158. if(timeout == 0){
  159. printf("Error in reading from I2C Bus: Bus is not getting ready before transmit start\n");
  160. DL_I2C_resetControllerTransfer(I2C_1_INST);
  161. return false;
  162. }
  163. //Send the packet to the controller.
  164. //This function will send Start + Stop automatically.
  165. DL_I2C_startControllerTransferAdvanced(I2C_1_INST,
  166. 0x49,
  167. DL_I2C_CONTROLLER_DIRECTION_TX,
  168. 1,
  169. DL_I2C_CONTROLLER_START_ENABLE,
  170. DL_I2C_CONTROLLER_STOP_ENABLE,
  171. DL_I2C_CONTROLLER_ACK_ENABLE);
  172. printf("[I2C] TX Packet Sent:: 0x%02X\n", txPacket.txBuffer[0]);
  173. while (DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY)
  174. ;
  175. // Add delay between transfers
  176. //delay_cycles(320000);
  177. rxPacket.rxCount= 0;
  178. rxPacket.rxLen= 8;
  179. DL_I2C_flushControllerRXFIFO(I2C_1_INST);
  180. DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
  181. // Send a read request to Targe
  182. DL_I2C_startControllerTransferAdvanced(I2C_1_INST, 0x49, DL_I2C_CONTROLLER_DIRECTION_RX, 8, DL_I2C_CONTROLLER_START_ENABLE,
  183. DL_I2C_CONTROLLER_STOP_ENABLE,
  184. DL_I2C_CONTROLLER_ACK_ENABLE);
  185. while (DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY);
  186. printf("Received Bytes[%d]: 0x%02X\n", rxPacket.rxCount, rxPacket.rxBuffer[rxPacket.rxCount]);
  187. return true;
  188. }*/
  189. // Following code worked with ADC as the target with now clocking issues:
  190. bool getBatteryMeasurement_test(uint8_t slot_id){
  191. BatteryMeasurement measurement;
  192. //Enable the interrupt:
  193. DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
  194. txPacket.txComplete= false;
  195. txPacket.txLen= 1;
  196. txPacket.txBuffer[0] = (0<<4) | (CMD_GET_MEASUREMENT & 0x0F);
  197. /* Wait for I2C to be Idle */
  198. uint32_t timeout = 10000;
  199. while (!(DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_IDLE) && timeout--);
  200. if(timeout == 0){
  201. printf("Error in reading from I2C Bus: Bus is not getting ready before transmit start\n");
  202. DL_I2C_resetControllerTransfer(I2C_1_INST);
  203. return false;
  204. }
  205. /* Send the packet to the controller.
  206. * This function will send Start + Stop automatically.
  207. */
  208. DL_I2C_startControllerTransferAdvanced(I2C_1_INST,
  209. TARGET_BASE_ADDRESS,
  210. DL_I2C_CONTROLLER_DIRECTION_TX,
  211. txPacket.txLen,
  212. DL_I2C_CONTROLLER_START_ENABLE,
  213. DL_I2C_CONTROLLER_STOP_ENABLE,
  214. DL_I2C_CONTROLLER_ACK_ENABLE);
  215. printf("[I2C] TX Packet Sent:: 0x%02X\n", txPacket.txBuffer[0]);
  216. /* Poll until the Controller writes all bytes */
  217. timeout= 32000;
  218. while(!(txPacket.txComplete) && timeout--);
  219. if(timeout == 0){
  220. printf("Tx Transmit not completed.\n");
  221. DL_I2C_resetControllerTransfer(I2C_1_INST);
  222. return false;
  223. }
  224. /* Add delay between transfers */
  225. //delay_cycles(32000);
  226. rxPacket.rxCount= 0;
  227. rxPacket.rxLen= 8;
  228. rxPacket.rxComplete= false;
  229. timeout= 32000;
  230. DL_I2C_flushControllerRXFIFO(I2C_1_INST);
  231. DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
  232. while(!(rxPacket.rxComplete) && timeout--);
  233. if(timeout==0){
  234. printf("Rx transmit not completed");
  235. }
  236. //while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  237. /* Send a read request to Target */
  238. DL_I2C_startControllerTransferAdvanced(I2C_1_INST, TARGET_BASE_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_RX, rxPacket.rxLen, DL_I2C_CONTROLLER_START_ENABLE,
  239. DL_I2C_CONTROLLER_STOP_ENABLE,
  240. DL_I2C_CONTROLLER_ACK_ENABLE);
  241. while (DL_I2C_getControllerStatus(I2C_1_INST) & DL_I2C_CONTROLLER_STATUS_BUSY)
  242. ;
  243. measurement.voltage= rxPacket.rxBuffer[0] | (rxPacket.rxBuffer[1] << 8);
  244. measurement.current= rxPacket.rxBuffer[2]|(rxPacket.rxBuffer[3] << 8);
  245. measurement.temperature = rxPacket.rxBuffer[4] | (rxPacket.rxBuffer[5] << 8);
  246. measurement.slot_state = (SlotState)(rxPacket.rxBuffer[6]);
  247. battery_data[slot_id].battery_measurement= measurement;
  248. //DEBUG
  249. printf("[I2C] Successfully read %d bytes from target 0x%02X\n", rxPacket.rxCount, TARGET_BASE_ADDRESS);
  250. printf("Voltage: %u\n", battery_data[slot_id].battery_measurement.voltage);
  251. printf("Current: %d\n", battery_data[slot_id].battery_measurement.current);
  252. printf("Temp: %u\n", battery_data[slot_id].battery_measurement.temperature);
  253. printf("Slot state: %u\n", battery_data[slot_id].battery_measurement.slot_state);
  254. return true;
  255. }