/*include configuration libraries*/ #include "src/interfaces/mcu_slave_interface.h" #include "ti/driverlib/m0p/dl_core.h" #include "ti_msp_dl_config.h" #include #include #include #include //adc peripheral #include "src/peripherals/adc/adc.h" #include "src/peripherals/adc/adc_interface.h" #define DELAY_CYCLE (1000000) //i2c: #include "ti/comm_modules/i2c/controller/i2c_comm_controller.h" //battery: #include "src/battery_data/battery.h" #include "src/interfaces/i2c_peripherals_scan.h" I2C_Instance gI2C; I2C_ResponseInfo gResponse; volatile bool mcuCommandPending= false; /*Interrupt for MCU -> ADC * CASE: DL_I2C_IIDX_CONTROLLER_RX_DONE: ADC Reception Complete - ADC has finished sending data and it's fully received. - gI2C.rxMsg.len = gI2C.rxMsg.ptr: - Stores the received data length in the response buffer. - I2C_decodeResponse(): - Decodes the received response. - 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 * 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) - 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); */ 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 Main MCU to Target MCU ****/ void I2C_target_INST_IRQHandler(void) { uint32_t status = DL_I2C_getPendingInterrupt(I2C_target_INST); //printf("status: %d\n", status); switch (status) { case DL_I2C_IIDX_TARGET_START: DL_I2C_flushTargetTXFIFO(I2C_target_INST); break; case DL_I2C_IIDX_TARGET_STOP: mcuCommandPending= true; DL_I2C_flushTargetTXFIFO(I2C_target_INST); DL_I2C_flushTargetRXFIFO(I2C_target_INST); break; case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER: //printf("Rx Interrupt Triggered \n"); if (DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)) { return; } mcuCommandPending= true; break; case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER: mcuCommandPending= true; //printf("Tx interrupt triggered.\n"); break; case DL_I2C_IIDX_TARGET_ARBITRATION_LOST: break; default: break; } } /***Main Function***/ int main(void){ SYSCFG_DL_init(); Battery_Init(); // Reset_I2C_Bus(); NVIC_EnableIRQ(I2C_target_INST_INT_IRQN); NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN); printf("*******Scanning the peripherals********\n"); //I2C Scanning I2C_scanBus(I2C_controller_INST); I2C_init(&gI2C); while(1){ if(mcuCommandPending){ mcu_i2c_handle(I2C_target_INST); mcuCommandPending= false; continue; } // 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++) { updateADCReading_multichannel(slot_id, adc_channel); } } delay_cycles(DELAY_CYCLE); } }