Initial commit
[hackover2013-badge-firmware.git] / core / i2c / i2c.c
1 /*****************************************************************************
2 * i2c.c: I2C C file for NXP LPC11xx/13xx Family Microprocessors
3 *
4 * Copyright(C) 2008, NXP Semiconductor
5 * Parts of this code are (C) 2010, MyVoice CAD/CAM Services
6 * All rights reserved.
7 *
8 * History
9 * 2009.12.07 ver 1.00 Preliminary version, first Release
10 * 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services:
11 * Major cleaning and a rewrite of some functions
12 * - adding ACK/NACK handling to the state machine
13 * - adding a return result to the I2CEngine()
14 *
15 *****************************************************************************/
16 #include "i2c.h"
17
18 volatile uint32_t I2CMasterState = I2CSTATE_IDLE;
19 volatile uint32_t I2CSlaveState = I2CSTATE_IDLE;
20
21 volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
22 volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
23 volatile uint32_t I2CReadLength;
24 volatile uint32_t I2CWriteLength;
25
26 volatile uint32_t RdIndex = 0;
27 volatile uint32_t WrIndex = 0;
28
29
30 /*****************************************************************************
31 ** Function name: I2C_IRQHandler
32 **
33 ** Descriptions: I2C interrupt handler, deal with master mode only.
34 **
35 ** parameters: None
36 ** Returned value: None
37 **
38 *****************************************************************************/
39 void I2C_IRQHandler(void)
40 {
41 uint8_t StatValue;
42
43 /* this handler deals with master read and master write only */
44 StatValue = I2C_I2CSTAT;
45 switch ( StatValue )
46 {
47 case 0x08:
48 /*
49 * A START condition has been transmitted.
50 * We now send the slave address and initialize
51 * the write buffer
52 * (we always start with a write after START+SLA)
53 */
54 WrIndex = 0;
55 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
56 I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
57 I2CMasterState = I2CSTATE_PENDING;
58 break;
59
60 case 0x10:
61 /*
62 * A repeated START condition has been transmitted.
63 * Now a second, read, transaction follows so we
64 * initialize the read buffer.
65 */
66 RdIndex = 0;
67 /* Send SLA with R bit set, */
68 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
69 I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
70 break;
71
72 case 0x18:
73 /*
74 * SLA+W has been transmitted; ACK has been received.
75 * We now start writing bytes.
76 */
77 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
78 I2C_I2CCONCLR = I2CONCLR_SIC;
79 break;
80
81 case 0x20:
82 /*
83 * SLA+W has been transmitted; NOT ACK has been received.
84 * Send a stop condition to terminate the transaction
85 * and signal I2CEngine the transaction is aborted.
86 */
87 I2C_I2CCONSET = I2CONSET_STO;
88 I2C_I2CCONCLR = I2CONCLR_SIC;
89 I2CMasterState = I2CSTATE_SLA_NACK;
90 break;
91
92 case 0x28:
93 /*
94 * Data in I2DAT has been transmitted; ACK has been received.
95 * Continue sending more bytes as long as there are bytes to send
96 * and after this check if a read transaction should follow.
97 */
98 if ( WrIndex < I2CWriteLength )
99 {
100 /* Keep writing as long as bytes avail */
101 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
102 }
103 else
104 {
105 if ( I2CReadLength != 0 )
106 {
107 /* Send a Repeated START to initialize a read transaction */
108 /* (handled in state 0x10) */
109 I2C_I2CCONSET = I2CONSET_STA; /* Set Repeated-start flag */
110 }
111 else
112 {
113 I2CMasterState = I2CSTATE_ACK;
114 I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
115 }
116 }
117 I2C_I2CCONCLR = I2CONCLR_SIC;
118 break;
119
120 case 0x30:
121 /*
122 * Data byte in I2DAT has been transmitted; NOT ACK has been received
123 * Send a STOP condition to terminate the transaction and inform the
124 * I2CEngine that the transaction failed.
125 */
126 I2C_I2CCONSET = I2CONSET_STO;
127 I2C_I2CCONCLR = I2CONCLR_SIC;
128 I2CMasterState = I2CSTATE_NACK;
129 break;
130
131 case 0x38:
132 /*
133 * Arbitration loss in SLA+R/W or Data bytes.
134 * This is a fatal condition, the transaction did not complete due
135 * to external reasons (e.g. hardware system failure).
136 * Inform the I2CEngine of this and cancel the transaction
137 * (this is automatically done by the I2C hardware)
138 */
139 I2CMasterState = I2CSTATE_ARB_LOSS;
140 I2C_I2CCONCLR = I2CONCLR_SIC;
141 break;
142
143 case 0x40:
144 /*
145 * SLA+R has been transmitted; ACK has been received.
146 * Initialize a read.
147 * Since a NOT ACK is sent after reading the last byte,
148 * we need to prepare a NOT ACK in case we only read 1 byte.
149 */
150 if ( I2CReadLength == 1 )
151 {
152 /* last (and only) byte: send a NACK after data is received */
153 I2C_I2CCONCLR = I2CONCLR_AAC;
154 }
155 else
156 {
157 /* more bytes to follow: send an ACK after data is received */
158 I2C_I2CCONSET = I2CONSET_AA;
159 }
160 I2C_I2CCONCLR = I2CONCLR_SIC;
161 break;
162
163 case 0x48:
164 /*
165 * SLA+R has been transmitted; NOT ACK has been received.
166 * Send a stop condition to terminate the transaction
167 * and signal I2CEngine the transaction is aborted.
168 */
169 I2C_I2CCONSET = I2CONSET_STO;
170 I2C_I2CCONCLR = I2CONCLR_SIC;
171 I2CMasterState = I2CSTATE_SLA_NACK;
172 break;
173
174 case 0x50:
175 /*
176 * Data byte has been received; ACK has been returned.
177 * Read the byte and check for more bytes to read.
178 * Send a NOT ACK after the last byte is received
179 */
180 I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
181 if ( RdIndex < (I2CReadLength-1) )
182 {
183 /* lmore bytes to follow: send an ACK after data is received */
184 I2C_I2CCONSET = I2CONSET_AA;
185 }
186 else
187 {
188 /* last byte: send a NACK after data is received */
189 I2C_I2CCONCLR = I2CONCLR_AAC;
190 }
191 I2C_I2CCONCLR = I2CONCLR_SIC;
192 break;
193
194 case 0x58:
195 /*
196 * Data byte has been received; NOT ACK has been returned.
197 * This is the last byte to read.
198 * Generate a STOP condition and flag the I2CEngine that the
199 * transaction is finished.
200 */
201 I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
202 I2CMasterState = I2CSTATE_ACK;
203 I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
204 I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
205 break;
206
207
208 default:
209 I2C_I2CCONCLR = I2CONCLR_SIC;
210 break;
211 }
212 return;
213 }
214
215 /*****************************************************************************
216 ** Function name: I2CStart
217 **
218 ** Descriptions: Create I2C start condition, a timeout
219 ** value is set if the I2C never gets started,
220 ** and timed out. It's a fatal error.
221 **
222 ** parameters: None
223 ** Returned value: true or false, return false if timed out
224 **
225 *****************************************************************************/
226 static uint32_t I2CStart( void )
227 {
228 uint32_t timeout = 0;
229
230 /*--- Issue a start condition ---*/
231 I2C_I2CCONSET = I2CONSET_STA; /* Set Start flag */
232
233 while((I2CMasterState != I2CSTATE_PENDING) && (timeout < MAX_TIMEOUT))
234 {
235 timeout++;
236 }
237
238 return (timeout < MAX_TIMEOUT);
239 }
240
241 /*****************************************************************************
242 ** Function name: I2CStop
243 **
244 ** Descriptions: Set the I2C stop condition
245 **
246 ** parameters: None
247 ** Returned value: true or never return
248 **
249 *****************************************************************************/
250 static uint32_t I2CStop( void )
251 {
252 uint32_t timeout = 0;
253
254 I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
255 I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
256
257 /*--- Wait for STOP detected ---*/
258 while((I2C_I2CCONSET & I2CONSET_STO) && (timeout < MAX_TIMEOUT))
259 {
260 timeout++;
261 }
262 return (timeout >= MAX_TIMEOUT);
263 }
264
265 /*****************************************************************************
266 ** Function name: I2CInit
267 **
268 ** Descriptions: Initialize I2C controller
269 **
270 ** parameters: I2c mode is either MASTER or SLAVE
271 ** Returned value: true or false, return false if the I2C
272 ** interrupt handler was not installed correctly
273 **
274 *****************************************************************************/
275 uint32_t i2cInit( uint32_t I2cMode )
276 {
277 SCB_PRESETCTRL |= (0x1<<1);
278
279 // Enable I2C clock
280 SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_I2C);
281
282 // Configure pin 0.4 for SCL
283 IOCON_PIO0_4 &= ~(IOCON_PIO0_4_FUNC_MASK | IOCON_PIO0_4_I2CMODE_MASK);
284 IOCON_PIO0_4 |= (IOCON_PIO0_4_FUNC_I2CSCL);
285
286 // Configure pin 0.5 for SDA
287 IOCON_PIO0_5 &= ~(IOCON_PIO0_5_FUNC_MASK | IOCON_PIO0_5_I2CMODE_MASK);
288 IOCON_PIO0_5 |= IOCON_PIO0_5_FUNC_I2CSDA;
289
290 // Clear flags
291 I2C_I2CCONCLR = I2C_I2CCONCLR_AAC |
292 I2C_I2CCONCLR_SIC |
293 I2C_I2CCONCLR_STAC |
294 I2C_I2CCONCLR_I2ENC;
295
296 // See p.128 for appropriate values for SCLL and SCLH
297 #if I2C_FAST_MODE_PLUS
298 IOCON_PIO0_4 |= (IOCON_PIO0_4_I2CMODE_FASTPLUSI2C);
299 IOCON_PIO0_5 |= (IOCON_PIO0_5_I2CMODE_FASTPLUSI2C);
300 I2C_I2CSCLL = I2C_SCLL_HS_SCLL;
301 I2C_I2CSCLH = I2C_SCLH_HS_SCLH;
302 #else
303 I2C_I2CSCLL = I2SCLL_SCLL;
304 I2C_I2CSCLH = I2SCLH_SCLH;
305 #endif
306
307 if ( I2cMode == I2CSLAVE )
308 {
309 I2C_I2CADR0 = SLAVE_ADDR;
310 }
311
312 /* Enable the I2C Interrupt */
313 NVIC_EnableIRQ(I2C_IRQn);
314 I2C_I2CCONSET = I2C_I2CCONSET_I2EN;
315
316 return( TRUE );
317 }
318
319 /*****************************************************************************
320 ** Function name: I2CEngine
321 **
322 ** Descriptions: The routine to complete a I2C transaction
323 ** from start to stop. All the intermitten
324 ** steps are handled in the interrupt handler.
325 ** Before this routine is called, the read
326 ** length, write length and I2C master buffer
327 ** need to be filled.
328 **
329 ** parameters: None
330 ** Returned value: Any of the I2CSTATE_... values. See i2c.h
331 **
332 *****************************************************************************/
333 uint32_t i2cEngine( void )
334 {
335 I2CMasterState = I2CSTATE_IDLE;
336 RdIndex = 0;
337 WrIndex = 0;
338 if ( I2CStart() != TRUE )
339 {
340 I2CStop();
341 return ( FALSE );
342 }
343
344 /* wait until the state is a terminal state */
345 while (I2CMasterState < 0x100);
346
347 return ( I2CMasterState );
348 }
349
350 /******************************************************************************
351 ** End Of File
352 ******************************************************************************/
353
This page took 0.061901 seconds and 5 git commands to generate.