| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2c_001.c
Go to the documentation of this file.
1 /*
2 * @brief I2C driver functions
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "i2c_001.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /* Control flags */
39 #define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
40
41 /*****************************************************************************
42 * Public types/enumerations/variables
43 ****************************************************************************/
44
45 /*****************************************************************************
46 * Private functions
47 ****************************************************************************/
48 /* Match the slave address */
49 static int IP_I2C_SlaveMatchAddr(uint8_t addr1, uint8_t addr2, uint8_t mask)
50 {
51 mask |= 1;
52 return (addr1 & ~mask) == (addr2 & ~mask);
53 }
54
55 /* Get the index of the active slave */
56 static I2C_SLAVE_ID IP_I2C_SlaveIndexLookup(IP_I2C_001_T *pI2C, uint8_t slaveAddr)
57 {
58 if (!(slaveAddr >> 1)) {
59 return I2C_SLAVE_GENERAL; /* General call address */
60 }
61 if (IP_I2C_SlaveMatchAddr(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) {
62 return I2C_SLAVE_0;
63 }
64 if (IP_I2C_SlaveMatchAddr(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) {
65 return I2C_SLAVE_1;
66 }
67 if (IP_I2C_SlaveMatchAddr(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) {
68 return I2C_SLAVE_2;
69 }
70 if (IP_I2C_SlaveMatchAddr(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) {
71 return I2C_SLAVE_3;
72 }
73
74 /* If everything is fine the code should never come here */
75 return I2C_SLAVE_GENERAL;
76 }
77
78 /*****************************************************************************
79 * Public functions
80 ****************************************************************************/
81 /* Master transfer state change handler handler */
82 int IP_I2C_MasterXfer_StateHandler(IP_I2C_001_T *pI2C, I2C_XFER_T *xfer)
83 {
84 uint32_t cclr = I2C_CON_FLAGS;
85
86 switch (IP_I2C_GetCurrentState(pI2C)) {
87 case 0x08: /* Start condition on bus */
88 case 0x10: /* Repeated start condition */
89 pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
90 break;
91
92 /* Tx handling */
93 case 0x18: /* SLA+W sent and ACK received */
94 case 0x28: /* DATA sent and ACK received */
95 if (!xfer->txSz) {
96 cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
97 }
98 else {
99 pI2C->DAT = *xfer->txBuff++;
100 xfer->txSz--;
101 }
102 break;
103
104 /* Rx handling */
105 case 0x58: /* Data Received and NACK sent */
106 cclr &= ~I2C_CON_STO;
107
108 case 0x50: /* Data Received and ACK sent */
109 *xfer->rxBuff++ = pI2C->DAT;
110 xfer->rxSz--;
111
112 case 0x40: /* SLA+R sent and ACK received */
113 if (xfer->rxSz > 1) {
114 cclr &= ~I2C_CON_AA;
115 }
116 break;
117
118 /* NAK Handling */
119 case 0x20: /* SLA+W sent NAK received */
120 case 0x30: /* DATA sent NAK received */
121 case 0x48: /* SLA+R sent NAK received */
122 xfer->status = I2C_STATUS_NAK;
123 cclr &= ~I2C_CON_STO;
124 break;
125
126 case 0x38: /* Arbitration lost */
127 xfer->status = I2C_STATUS_ARBLOST;
128 break;
129
130 /* Bus Error */
131 case 0x00:
132 xfer->status = I2C_STATUS_BUSERR;
133 cclr &= ~I2C_CON_STO;
134 }
135
136 /* Set clear control flags */
137 pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
138 pI2C->CONCLR = cclr;
139
140 /* If stopped return 0 */
141 if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
142 if (xfer->status == I2C_STATUS_BUSY) {
143 xfer->status = I2C_STATUS_DONE;
144 }
145 return 0;
146 }
147 return 1;
148 }
149
150 /* Find the slave address of SLA+W or SLA+R */
151 I2C_SLAVE_ID IP_I2C_GetSlaveIndex(IP_I2C_001_T *pI2C)
152 {
153 switch (IP_I2C_GetCurrentState(pI2C)) {
154 case 0x60:
155 case 0x68:
156 case 0x70:
157 case 0x78:
158 case 0xA8:
159 case 0xB0:
160 return IP_I2C_SlaveIndexLookup(pI2C, pI2C->DAT);
161 }
162
163 /* If everything is fine code should never come here */
164 return I2C_SLAVE_GENERAL;
165 }
166
167 /* Slave state machine handler */
168 int IP_I2C_SlaveXfer_StateHandler(IP_I2C_001_T *pI2C, I2C_XFER_T *xfer)
169 {
170 uint32_t cclr = I2C_CON_FLAGS;
171 int ret = RET_SLAVE_BUSY;
172
173 xfer->status = I2C_STATUS_BUSY;
174 switch (IP_I2C_GetCurrentState(pI2C)) {
175 case 0x80: /* SLA: Data received + ACK sent */
176 case 0x90: /* GC: Data received + ACK sent */
177 *xfer->rxBuff++ = pI2C->DAT;
178 xfer->rxSz--;
179 ret = RET_SLAVE_RX;
180 if (xfer->rxSz > 1) {
181 cclr &= ~I2C_CON_AA;
182 }
183 break;
184
185 case 0x60: /* Own SLA+W received */
186 case 0x68: /* Own SLA+W received after losing arbitration */
187 case 0x70: /* GC+W received */
188 case 0x78: /* GC+W received after losing arbitration */
189 xfer->slaveAddr = pI2C->DAT & ~1;
190 if (xfer->rxSz > 1) {
191 cclr &= ~I2C_CON_AA;
192 }
193 break;
194
195 case 0xA8: /* SLA+R received */
196 case 0xB0: /* SLA+R received after losing arbitration */
197 xfer->slaveAddr = pI2C->DAT & ~1;
198
199 case 0xB8: /* DATA sent and ACK received */
200 pI2C->DAT = *xfer->txBuff++;
201 xfer->txSz--;
202 if (xfer->txSz > 0) {
203 cclr &= ~I2C_CON_AA;
204 }
205 ret = RET_SLAVE_TX;
206 break;
207
208 case 0xC0: /* Data transmitted and NAK received */
209 case 0xC8: /* Last data transmitted and ACK received */
210 case 0x88: /* SLA: Data received + NAK sent */
211 case 0x98: /* GC: Data received + NAK sent */
212 case 0xA0: /* STOP/Repeated START condition received */
213 ret = RET_SLAVE_IDLE;
214 cclr &= ~I2C_CON_AA;
215 xfer->status = I2C_STATUS_DONE;
216 if (xfer->slaveAddr & 1) {
217 cclr &= ~I2C_CON_STA;
218 }
219 break;
220 }
221
222 /* Set clear control flags */
223 pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
224 pI2C->CONCLR = cclr;
225
226 return ret;
227 }