//***************************************************************************** // // Write a register in the TLV320AIC23B DAC. // // \param ucRegister is the offset to the register to write. // \param ulData is the data to be written to the DAC register. // // This function will write the register passed in /e ucAddr with the value // passed in to /e ulData. The data in \e ulData is actually 9 bits and the // value in /e ucAddr is interpreted as 7 bits. // // \return Returns \b true on success or \b false on error. // //***************************************************************************** static tBoolean TLV320AIC23BWriteRegister(unsigned char ucRegister, unsigned long ulData) { // // Set the slave address. // I2CMasterSlaveAddrSet(DAC_I2C_MASTER_BASE, TI_TLV320AIC23B_ADDR_0, false); // // Write the next byte to the controller. // I2CMasterDataPut(DAC_I2C_MASTER_BASE, ucRegister | ((ulData >> 8) & 1)); // // Continue the transfer. // I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START); // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false) == 0) { } if(I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); return(false); } // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false)) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); } // // Write the next byte to the controller. // I2CMasterDataPut(DAC_I2C_MASTER_BASE, ulData); // // End the transfer. // I2CMasterControl(DAC_I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH); // // Wait until the current byte has been transferred. // while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false) == 0) { } if(I2CMasterErr(DAC_I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE) { return(false); } while(I2CMasterIntStatus(DAC_I2C_MASTER_BASE, false)) { I2CMasterIntClear(DAC_I2C_MASTER_BASE); } return(true); }
/* * ======== I2CCC26XX_hwiFxn ======== * Hwi interrupt handler to service the I2C peripheral * * The handler is a generic handler for a I2C object. */ static void I2CCC26XX_hwiFxn(UArg arg) { I2CDataType errStatus; I2CCC26XX_Object *object; I2CCC26XX_HWAttrs const *hwAttrs; /* Get the pointer to the object and hwAttrs */ object = ((I2C_Handle)arg)->object; hwAttrs = ((I2C_Handle)arg)->hwAttrs; /* Get the interrupt status of the I2C controller */ errStatus = I2CMasterErr(hwAttrs->baseAddr); /* Clear interrupt source to avoid additional interrupts */ I2CMasterIntClear(hwAttrs->baseAddr); /* Check for I2C Errors */ if ((errStatus == I2C_MASTER_ERR_NONE) || (object->mode == I2CCC26XX_ERROR)) { /* No errors, now check what we need to do next */ switch (object->mode) { /* * ERROR case is OK because if an Error is detected, a STOP bit is * sent; which in turn will call another interrupt. This interrupt * call will then post the transferComplete semaphore to unblock the * I2C_transfer function */ case I2CCC26XX_ERROR: break; case I2CCC26XX_IDLE_MODE: I2CCC26XX_completeTransfer((I2C_Handle) arg); break; case I2CCC26XX_WRITE_MODE: /* Decrement write Counter */ object->writeCountIdx--; /* Check if more data needs to be sent */ if (object->writeCountIdx) { Log_print3(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_WRITE_MODE: Data to write: 0x%x; " "To slave: 0x%x", hwAttrs->baseAddr, *(object->writeBufIdx), object->currentTransaction->slaveAddress); /* Write data contents into data register */ I2CMasterDataPut(hwAttrs->baseAddr, *(object->writeBufIdx)); object->writeBufIdx++; if ((object->writeCountIdx < 2) && !(object->readCountIdx)) { /* Everything has been sent, nothing to receive */ /* Next state: Idle mode */ object->mode = I2CCC26XX_IDLE_MODE; /* Send last byte with STOP bit */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_SEND_FINISH); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_WRITE_MODE: ACK received; " "Writing w/ STOP bit", hwAttrs->baseAddr); } else { /* * Either there is more date to be transmitted or some * data needs to be received next */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_SEND_CONT); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_WRITE_MODE: ACK received; Writing", hwAttrs->baseAddr); } } /* At this point, we know that we need to receive data */ else { /* * We need to check after we are done transmitting data, if * we need to receive any data. * In a corner case when we have only one byte transmitted * and no data to receive, the I2C will automatically send * the STOP bit. In other words, here we only need to check * if data needs to be received. If so, how much. */ if (object->readCountIdx) { /* Next state: Receive mode */ object->mode = I2CCC26XX_READ_MODE; /* Switch into Receive mode */ I2CMasterSlaveAddrSet(hwAttrs->baseAddr, object->currentTransaction->slaveAddress, true); if (object->readCountIdx > 1) { /* Send a repeated START */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_RECEIVE_START); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_WRITE_MODE: -> I2CCC26XX_READ_MODE; " "Reading w/ RESTART and ACK", hwAttrs->baseAddr); } else { /* * Send a repeated START with a NACK since it's the * last byte to be received. * I2C_MASTER_CMD_BURST_RECEIVE_START_NACK is * is locally defined because there is no macro to * receive data and send a NACK after sending a * start bit (0x00000003) */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_RECEIVE_START_NACK); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_WRITE_MODE: -> I2CCC26XX_READ_MODE; " "Reading w/ RESTART and NACK", hwAttrs->baseAddr); } } else { /* Done with all transmissions */ object->mode = I2CCC26XX_IDLE_MODE; /* * No more data needs to be received, so follow up with * a STOP bit * Again, there is no equivalent macro (0x00000004) so * I2C_MASTER_CMD_BURST_RECEIVE_STOP is used. */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_RECEIVE_STOP); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_WRITE_MODE: -> I2CCC26XX_IDLE_MODE; " "Sending STOP bit", hwAttrs->baseAddr); } } break; case I2CCC26XX_READ_MODE: /* Save the received data */ *(object->readBufIdx) = I2CMasterDataGet(hwAttrs->baseAddr); Log_print2(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_READ_MODE: Read data byte: 0x%x", hwAttrs->baseAddr, *(object->readBufIdx)); object->readBufIdx++; /* Check if any data needs to be received */ object->readCountIdx--; if (object->readCountIdx) { if (object->readCountIdx > 1) { /* More data to be received */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_RECEIVE_CONT); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_READ_MODE: Reading w/ ACK", hwAttrs->baseAddr); } else { /* * Send NACK because it's the last byte to be received * There is no NACK macro equivalent (0x00000001) so * I2C_MASTER_CMD_BURST_RECEIVE_CONT_NACK is used */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_RECEIVE_CONT_NACK); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_READ_MODE: Reading w/ NACK", hwAttrs->baseAddr); } } else { /* Next state: Idle mode */ object->mode = I2CCC26XX_IDLE_MODE; /* * No more data needs to be received, so follow up with a * STOP bit * Again, there is no equivalent macro (0x00000004) so * I2C_MASTER_CMD_BURST_RECEIVE_STOP is used */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_RECEIVE_STOP); Log_print1(Diags_USER2, "I2C:(%p) ISR I2CCC26XX_READ_MODE: -> I2CCC26XX_IDLE_MODE; " "Sending STOP bit", hwAttrs->baseAddr); } break; default: object->mode = I2CCC26XX_ERROR; break; } } else { /* Some sort of error happened! */ object->mode = I2CCC26XX_ERROR; if (errStatus & I2C_MASTER_ERR_ARB_LOST) { I2CCC26XX_completeTransfer((I2C_Handle) arg); } else { /* Try to send a STOP bit to end all I2C communications immediately */ /* * I2C_MASTER_CMD_BURST_SEND_ERROR_STOP -and- * I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP * have the same values */ I2CMasterControl(hwAttrs->baseAddr, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP); I2CCC26XX_completeTransfer((I2C_Handle) arg); } Log_print2(Diags_USER1, "I2C:(%p) ISR I2C Bus fault (Status Reg: 0x%x)", hwAttrs->baseAddr, errStatus); } return; }