--- /dev/null
+/** @file i2c.c \r
+* @brief I2C Driver Implementation File\r
+* @date 10.March.2012\r
+* @version 03.01.00\r
+*\r
+*/\r
+\r
+/* (c) Texas Instruments 2009-2012, All rights reserved. */\r
+\r
+/* USER CODE BEGIN (0) */\r
+/* USER CODE END */\r
+\r
+#include "i2c.h"\r
+\r
+/* USER CODE BEGIN (1) */\r
+/* USER CODE END */\r
+\r
+/** @struct g_I2CTransfer\r
+* @brief Interrupt mode globals\r
+*\r
+*/\r
+struct g_i2cTransfer\r
+{\r
+ uint32_t mode;\r
+ uint32_t length;\r
+ uint8_t *data;\r
+} g_i2cTransfer[2];\r
+\r
+/* USER CODE BEGIN (2) */\r
+/* USER CODE END */\r
+\r
+/** @fn void i2cInit(void)\r
+* @brief Initializes the i2c Driver\r
+*\r
+* This function initializes the i2c module.\r
+*/\r
+void i2cInit(void)\r
+{\r
+/* USER CODE BEGIN (3) */\r
+/* USER CODE END */\r
+\r
+ /** @b intialize @b I2C */\r
+\r
+ /** - i2c out of reset */\r
+ i2cREG1->MDR = (1 << 5);\r
+\r
+ /** - set i2c mode */\r
+ i2cREG1->MDR = (0 << 15) /* nack mode */ \r
+ | (0 << 14) /* free running */ \r
+ | 0 /* start condtion - master mode only */ \r
+ | (1 <<11) /* stop condtion */ \r
+ | (1 <<10) /* Master/Slave mode */ \r
+ | (I2C_TRANSMITTER) /* Transmitter/receiver */ \r
+ | (I2C_7BIT_AMODE) /* xpanded address */ \r
+ | (0 << 7) /* repeat mode */ \r
+ | (0 << 6) /* digital loopback */ \r
+ | (0 << 4) /* start byte - master only */ \r
+ | (0) /* free data format */ \r
+ | I2C_8_BIT; /* bit count */ \r
+\r
+\r
+ /** - set i2c extended mode */\r
+ i2cREG1->EMDR = (0 << 25);\r
+\r
+ /** - set i2c data count */\r
+ i2cREG1->CNT = 3;\r
+\r
+ /** - disable all interrupts */\r
+ i2cREG1->IMR = 0x00U; \r
+\r
+ /** - set prescale */\r
+ i2cREG1->PSC = 9;\r
+\r
+ /** - set clock rate */\r
+ i2cREG1->CLKH = 35;\r
+ i2cREG1->CLKL = 35;\r
+\r
+ /** - set i2c pins functional mode */\r
+ i2cREG1->FUN = (0 );\r
+\r
+ /** - set i2c pins default output value */\r
+ i2cREG1->DOUT = (0 << 1) /* sda pin */\r
+ | (0); /* scl pin */\r
+\r
+ /** - set i2c pins output direction */\r
+ i2cREG1->DIR = (1 << 1) /* sda pin */\r
+ | (1); /* scl pin */\r
+\r
+ /** - set i2c pins open drain enable */\r
+ i2cREG1->ODR = (0 << 1) /* sda pin */\r
+ | (0); /* scl pin */\r
+\r
+ /** - set i2c pins pullup/pulldown enable */\r
+ i2cREG1->PD = (0 << 1) /* sda pin */\r
+ | (0); /* scl pin */\r
+\r
+ /** - set i2c pins pullup/pulldown select */\r
+ i2cREG1->PSL = (1 << 1) /* sda pin */\r
+ | (1); /* scl pin */\r
+\r
+ /** - set interrupt enable */\r
+ i2cREG1->IMR = (0 << 6) /* Address as slave interrupt */\r
+ | (0 << 5) /* Stop Condition detect interrupt */\r
+ | (1 << 4) /* Transmit data ready interrupt */\r
+ | (1 << 3) /* Receive data ready interrupt */\r
+ | (0 << 2) /* Register Access ready interrupt */\r
+ | (0 << 1) /* No Acknowledgement interrupt */\r
+ | (1); /* Arbitration Lost interrupt */\r
+ \r
+ i2cREG1->MDR |= I2C_RESET_OUT; /* i2c out of reset */ \r
+ \r
+ /** - inialise global transfer variables */\r
+ g_i2cTransfer[0].mode = 1 << 8;\r
+ g_i2cTransfer[0].length = 0;\r
+\r
+/* USER CODE BEGIN (4) */\r
+/* USER CODE END */\r
+\r
+}\r
+\r
+/** @fn void i2cSetOwnAdd(i2cBASE_t *i2c, uint32_t oadd)\r
+* @brief Set I2C Own Address\r
+* @param[in] oadd - I2C Own address (7-bit or 10 -bit address)\r
+* @param[in] i2c - i2c module base address\r
+* Set the Own address of the I2C module.\r
+*/\r
+void i2cSetOwnAdd(i2cBASE_t *i2c, uint32_t oadd)\r
+{\r
+ i2cREG1->OAR = oadd; /* set own address */\r
+}\r
+\r
+/** @fn void i2cSetSlaveAdd(i2cBASE_t *i2c, uint32_t sadd)\r
+* @brief Set Port Direction\r
+* @param[in] sadd - I2C Slave address\r
+* @param[in] i2c - i2c module base address\r
+* Set the Slave address to communicate which is must in Master mode.\r
+*/\r
+void i2cSetSlaveAdd(i2cBASE_t *i2c, uint32_t sadd)\r
+{\r
+ i2cREG1->SAR = sadd; /* set slave address */\r
+}\r
+\r
+/** @fn void i2cSetBaudrate(i2cBASE_t *i2c, uint32_t baud)\r
+* @brief Change baudrate at runtime.\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] baud - baudrate in KHz\r
+*\r
+* Change the i2c baudrate at runtime.\r
+*/\r
+void i2cSetBaudrate(i2cBASE_t *i2c, uint32_t baud)\r
+{\r
+ uint32_t prescale;\r
+ uint32_t d; \r
+ uint32_t ck; \r
+ double vclk = 80.000 * 1000000.0;\r
+\r
+/* USER CODE BEGIN (5) */\r
+/* USER CODE END */\r
+ prescale = (uint32_t) ((vclk /8000000) - 1);\r
+\r
+ if(prescale>=2)\r
+ {\r
+ d = 5;\r
+ }\r
+ else\r
+ {\r
+ d = prescale ? 6 : 7;\r
+ }\r
+\r
+ ck = ((vclk)/(2*baud*1000*(prescale+1)))-d;\r
+\r
+ i2cREG1->PSC = prescale;\r
+ i2cREG1->CLKH = ck;\r
+ i2cREG1->CLKL = ck; \r
+\r
+/* USER CODE BEGIN (6) */\r
+/* USER CODE END */\r
+\r
+}\r
+\r
+/** @fn void i2cSetStart(i2cBASE_t *i2c)\r
+* @brief Set i2c start condition\r
+* @param[in] i2c - i2c module base address\r
+* Set i2c to generate a start bit (Only in Master mode)\r
+*/\r
+void i2cSetStart(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (7) */\r
+/* USER CODE END */\r
+\r
+ i2cREG1->MDR |= I2C_START_COND; /* set start condition */\r
+\r
+/* USER CODE BEGIN (8) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void i2cSetStop(i2cBASE_t *i2c)\r
+* @brief Set i2c stop condition\r
+* @param[in] i2c - i2c module base address\r
+* Set i2c to generate a stop bit (Only in Master mode)\r
+*/\r
+void i2cSetStop(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (9) */\r
+/* USER CODE END */\r
+\r
+ i2cREG1->MDR |= I2C_STOP_COND; /* generate stop condition */\r
+\r
+/* USER CODE BEGIN (10) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void i2cSetCount(i2cBASE_t *i2c,uint32_t cnt)\r
+* @brief Set i2c data count\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] cnt - data count\r
+* Set i2c count to a transfer value after which the stop condition needs to be generated.\r
+* (Only in Master Mode)\r
+*/\r
+void i2cSetCount(i2cBASE_t *i2c ,uint32_t cnt)\r
+{\r
+/* USER CODE BEGIN (11) */\r
+/* USER CODE END */\r
+\r
+ i2cREG1->CNT = cnt; /* set i2c count */\r
+\r
+/* USER CODE BEGIN (12) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn uint32_t i2cIsTxReady(i2cBASE_t *i2c)\r
+* @brief Check if Tx buffer empty\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* @return The TX ready flag\r
+*\r
+* Checks to see if the Tx buffer ready flag is set, returns\r
+* 0 is flags not set otherwise will return the Tx flag itself.\r
+*/\r
+uint32_t i2cIsTxReady(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (13) */\r
+/* USER CODE END */\r
+\r
+ return i2cREG1->STR & I2C_TX_INT;\r
+\r
+/* USER CODE BEGIN (14) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void i2cSendByte(i2cBASE_t *i2c, uint8_t byte)\r
+* @brief Send Byte\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] byte - byte to transfer\r
+*\r
+* Sends a single byte in polling mode, will wait in the\r
+* routine until the transmit buffer is empty before sending\r
+* the byte. Use i2cIsTxReady to check for Tx buffer empty\r
+* before calling i2cSendByte to avoid waiting.\r
+*/\r
+void i2cSendByte(i2cBASE_t *i2c, uint8_t byte)\r
+{\r
+/* USER CODE BEGIN (15) */\r
+/* USER CODE END */\r
+\r
+ while ((i2cREG1->STR & I2C_TX_INT) == 0) { /* wait */ };\r
+ i2cREG1->DXR = byte;\r
+\r
+/* USER CODE BEGIN (16) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void i2cSend(i2cBASE_t *i2c, uint32_t length, uint8_t *data)\r
+* @brief Send Data\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] length - number of data words to transfer\r
+* @param[in] data - pointer to data to send\r
+*\r
+* Send a block of data pointed to by 'data' and 'length' bytes\r
+* long. If interrupts have been enabled the data is sent using\r
+* interrupt mode, otherwise polling mode is used. In interrupt\r
+* mode transmition of the first byte is started and the routine\r
+* returns imediatly, i2cSend must not be called again until the\r
+* transfer is complete, when the i2cNotification callback will\r
+* be called. In polling mode, i2cSend will not return until \r
+* the transfer is complete.\r
+*\r
+* @note if data word is less than 8 bits, then the data must be left\r
+* aligned in the data byte.\r
+*/\r
+void i2cSend(i2cBASE_t *i2c, uint32_t length, uint8_t *data)\r
+{\r
+ uint32_t index = i2c == i2cREG1 ? 0 : 1;\r
+\r
+/* USER CODE BEGIN (17) */\r
+/* USER CODE END */\r
+\r
+ if ((g_i2cTransfer[index].mode & I2C_TX_INT) != 0)\r
+ {\r
+ /* we are in interrupt mode */\r
+ \r
+ g_i2cTransfer[index].length = length;\r
+ g_i2cTransfer[index].data = data;\r
+\r
+ /* start transmit by sending first byte */ \r
+ i2cREG1->DXR = *g_i2cTransfer[index].data++;\r
+ i2cREG1->IMR = I2C_TX_INT;\r
+ }\r
+ else\r
+ {\r
+ /* send the data */\r
+ while (length-- > 0)\r
+ {\r
+ while ((i2cREG1->STR & I2C_TX_INT) == 0) { /* wait */ };\r
+ i2cREG1->DXR = *data++;\r
+ }\r
+ }\r
+/* USER CODE BEGIN (18) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn uint32_t i2cIsRxReady(i2cBASE_t *i2c)\r
+* @brief Check if Rx buffer full\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* @return The Rx ready flag\r
+*\r
+* Checks to see if the Rx buffer full flag is set, returns\r
+* 0 is flags not set otherwise will return the Rx flag itself.\r
+*/\r
+uint32_t i2cIsRxReady(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (19) */\r
+/* USER CODE END */\r
+\r
+ return i2cREG1->STR & I2C_RX_INT;\r
+\r
+/* USER CODE BEGIN (20) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r
+/** @fn uint32_t i2cRxError(i2cBASE_t *i2c)\r
+* @brief Return Rx Error flags\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* @return The Rx error flags\r
+*\r
+* Returns the Rx framing, overun and parity errors flags,\r
+* also clears the error flags before returning.\r
+*/\r
+uint32_t i2cRxError(i2cBASE_t *i2c)\r
+{\r
+ uint32_t status = i2cREG1->STR & (I2C_AL_INT | I2C_NACK_INT);\r
+\r
+/* USER CODE BEGIN (21) */\r
+/* USER CODE END */\r
+\r
+ i2cREG1->STR = I2C_AL_INT | I2C_NACK_INT;\r
+ \r
+/* USER CODE BEGIN (22) */\r
+/* USER CODE END */\r
+ \r
+ return status;\r
+\r
+}\r
+\r
+/** @fn void i2cClearSCD(i2cBASE_t *i2c)\r
+* @brief Clears the Stop condition detect flags.\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* This sunction is called to clear the Stop condition detect(SCD) flag\r
+*/\r
+void i2cClearSCD(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (23) */\r
+/* USER CODE END */\r
+\r
+ i2cREG1->STR = I2C_SCD_INT;\r
+ \r
+/* USER CODE BEGIN (24) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn uint32_t i2cReceiveByte(i2cBASE_t *i2c)\r
+* @brief Receive Byte\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* @return Received byte\r
+*\r
+* Recieves a single byte in polling mode. If there is\r
+* not a byte in the receive buffer the routine will wait\r
+* until one is received. Use i2cIsRxReady to check to\r
+* see if the buffer is full to avoid waiting.\r
+*/\r
+uint32_t i2cReceiveByte(i2cBASE_t *i2c)\r
+{\r
+ while ((i2cREG1->STR & I2C_RX_INT) == 0) { /* wait */ };\r
+\r
+/* USER CODE BEGIN (25) */\r
+/* USER CODE END */\r
+\r
+ return i2cREG1->DRR;\r
+}\r
+\r
+/** @fn void i2cReceive(i2cBASE_t *i2c, uint32_t length, uint8_t *data)\r
+* @brief Receive Data\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] length - number of data words to transfer\r
+* @param[in] data - pointer to data buffer\r
+*\r
+* Receive a block of 'length' bytes long and place it into the \r
+* data buffer pointed to by 'data'. If interrupts have been \r
+* enabled the data is received using interrupt mode, otherwise\r
+* polling mode is used. In interrupt mode receive is setup and\r
+* the routine returns imediatly, i2cReceive must not be called \r
+* again until the transfer is complete, when the i2cNotification \r
+* callback will be called. In polling mode, i2cReceive will not\r
+* return until the transfer is complete.\r
+*/\r
+void i2cReceive(i2cBASE_t *i2c, uint32_t length, uint8_t *data)\r
+{\r
+\r
+/* USER CODE BEGIN (26) */\r
+/* USER CODE END */\r
+ if ((i2cREG1->IMR & I2C_RX_INT) != 0)\r
+ {\r
+ /* we are in interrupt mode */\r
+ uint32_t index = i2c == i2cREG1 ? 0 : 1;\r
+ \r
+ /* clear error flags */\r
+ i2cREG1->STR = I2C_AL_INT | I2C_NACK_INT;\r
+\r
+ g_i2cTransfer[index].length = length;\r
+ g_i2cTransfer[index].data = data;\r
+ }\r
+ else\r
+ { \r
+ while (length-- > 0)\r
+ {\r
+ while ((i2cREG1->STR & I2C_RX_INT) == 0) { /* wait */ };\r
+ *data++ = i2cREG1->DRR;\r
+ }\r
+ }\r
+\r
+/* USER CODE BEGIN (27) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void i2cEnableLoopback(i2cBASE_t *i2c)\r
+* @brief Enable Loopback mode for self test\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* This function enables the Loopback mode for self test.\r
+*/\r
+void i2cEnableLoopback(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (28) */\r
+/* USER CODE END */\r
+\r
+ /* enable digital loopback */\r
+ i2cREG1->MDR |= (1 << 6); \r
+\r
+/* USER CODE BEGIN (29) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn void i2cDisableLoopback(i2cBASE_t *i2c)\r
+* @brief Enable Loopback mode for self test\r
+* @param[in] i2c - i2c module base address\r
+*\r
+* This function disable the Loopback mode.\r
+*/\r
+void i2cDisableLoopback(i2cBASE_t *i2c)\r
+{\r
+/* USER CODE BEGIN (30) */\r
+/* USER CODE END */\r
+ \r
+ /* Disable Loopback Mode */\r
+ i2cREG1->MDR &= 0xFFFFFFBF; \r
+\r
+/* USER CODE BEGIN (31) */\r
+/* USER CODE END */\r
+}\r
+\r
+/** @fn i2cEnableNotification(i2cBASE_t *i2c, uint32_t flags)\r
+* @brief Enable interrupts\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] flags - Interrupts to be enabled, can be ored value of:\r
+* i2c_FE_INT - framming error,\r
+* i2c_OE_INT - overrun error,\r
+* i2c_PE_INT - parity error,\r
+* i2c_RX_INT - receive buffer ready,\r
+* i2c_TX_INT - transmit buffer ready,\r
+* i2c_WAKE_INT - wakeup,\r
+* i2c_BREAK_INT - break detect\r
+*/\r
+void i2cEnableNotification(i2cBASE_t *i2c, uint32_t flags)\r
+{\r
+ uint32_t index = i2c == i2cREG1 ? 0 : 1;\r
+\r
+/* USER CODE BEGIN (32) */\r
+/* USER CODE END */\r
+\r
+ g_i2cTransfer[index].mode |= (flags & I2C_TX_INT);\r
+ i2cREG1->IMR = (flags & ~I2C_TX_INT);\r
+}\r
+\r
+/** @fn i2cDisableNotification(i2cBASE_t *i2c, uint32_t flags)\r
+* @brief Disable interrupts\r
+* @param[in] i2c - i2c module base address\r
+* @param[in] flags - Interrupts to be disabled, can be ored value of:\r
+* i2c_FE_INT - framming error,\r
+* i2c_OE_INT - overrun error,\r
+* i2c_PE_INT - parity error,\r
+* i2c_RX_INT - receive buffer ready,\r
+* i2c_TX_INT - transmit buffer ready,\r
+* i2c_WAKE_INT - wakeup,\r
+* i2c_BREAK_INT - break detect\r
+*/\r
+void i2cDisableNotification(i2cBASE_t *i2c, uint32_t flags)\r
+{\r
+ uint32_t index = i2c == i2cREG1 ? 0 : 1;\r
+\r
+/* USER CODE BEGIN (33) */\r
+/* USER CODE END */\r
+\r
+ g_i2cTransfer[index].mode &= ~(flags & I2C_TX_INT);\r
+ i2cREG1->IMR = (flags & ~I2C_TX_INT);\r
+}\r
+\r
+/** @fn void i2cInterrupt(void)\r
+* @brief Interrupt for I2C\r
+*/\r
+#pragma INTERRUPT(i2cInterrupt, IRQ)\r
+\r
+void i2cInterrupt(void)\r
+{\r
+ uint32_t vec = (i2cREG1->IVR & 0x00000007);\r
+\r
+/* USER CODE BEGIN (34) */\r
+/* USER CODE END */\r
+\r
+ switch (vec)\r
+ {\r
+ case 1:\r
+/* USER CODE BEGIN (35) */\r
+/* USER CODE END */\r
+ i2cNotification(i2cREG1, I2C_AL_INT);\r
+ break;\r
+ case 2:\r
+/* USER CODE BEGIN (36) */\r
+/* USER CODE END */\r
+ i2cNotification(i2cREG1, I2C_NACK_INT);\r
+ break;\r
+ case 3:\r
+/* USER CODE BEGIN (37) */\r
+/* USER CODE END */\r
+ i2cNotification(i2cREG1, I2C_ARDY_INT);\r
+ break;\r
+ case 4:\r
+/* USER CODE BEGIN (38) */\r
+/* USER CODE END */\r
+ /* receive */\r
+ { uint32_t byte = i2cREG1->DRR;\r
+\r
+ if (g_i2cTransfer[0].length > 0)\r
+ {\r
+ *g_i2cTransfer[0].data++ = byte;\r
+ g_i2cTransfer[0].length--;\r
+ if (g_i2cTransfer[0].length == 0)\r
+ {\r
+ i2cNotification(i2cREG1, I2C_RX_INT);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 5:\r
+/* USER CODE BEGIN (39) */\r
+/* USER CODE END */\r
+ /* transmit */\r
+ if (--g_i2cTransfer[0].length > 0)\r
+ {\r
+ i2cREG1->DXR = *g_i2cTransfer[0].data++;\r
+ }\r
+ else\r
+ {\r
+ i2cREG1->STR = I2C_TX_INT;\r
+ i2cNotification(i2cREG1, I2C_TX_INT);\r
+ }\r
+ break;\r
+\r
+\r
+ case 6:\r
+/* USER CODE BEGIN (40) */\r
+/* USER CODE END */\r
+ /* transmit */ \r
+ i2cNotification(i2cREG1, I2C_SCD_INT);\r
+ break;\r
+\r
+ case 7:\r
+/* USER CODE BEGIN (41) */\r
+/* USER CODE END */\r
+ i2cNotification(i2cREG1, I2C_AAS_INT);\r
+ break;\r
+\r
+ default:\r
+/* USER CODE BEGIN (42) */\r
+/* USER CODE END */\r
+ /* phantom interrupt, clear flags and return */\r
+ i2cREG1->STR = 0x000007FF;\r
+ break;\r
+ }\r
+/* USER CODE BEGIN (43) */\r
+/* USER CODE END */\r
+}\r
+\r
+\r