Made IRQHandlers optional
[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 * 2011.02.19 ver 1.20 KTownsend - microBuilder.eu
15 * - Added slave mode status values to
16 * I2C_IRQHandler
17 *
18 *****************************************************************************/
19 #include "i2c.h"
20
21 volatile uint32_t I2CMasterState = I2CSTATE_IDLE;
22 volatile uint32_t I2CSlaveState = I2CSTATE_IDLE;
23
24 volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE]; // Master Mode
25 volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE]; // Master Mode
26
27 //volatile uint8_t I2CWrBuffer[I2C_BUFSIZE]; // Slave Mode
28 //volatile uint8_t I2CRdBuffer[I2C_BUFSIZE]; // Slave Mode
29
30 volatile uint32_t I2CReadLength;
31 volatile uint32_t I2CWriteLength;
32
33 volatile uint32_t RdIndex;
34 volatile uint32_t WrIndex;
35
36 volatile uint32_t _I2cMode; // I2CMASTER or I2CSLAVE
37
38 /*****************************************************************************
39 ** Function name: I2C_IRQHandler
40 **
41 ** Descriptions: I2C interrupt handler, deal with master mode only.
42 **
43 ** parameters: None
44 ** Returned value: None
45 **
46 *****************************************************************************/
47 void I2C_IRQHandler(void)
48 {
49 uint8_t StatValue;
50
51 /* this handler deals with master read and master write only */
52 StatValue = I2C_I2CSTAT;
53 switch ( StatValue )
54 {
55 case 0x08:
56 /*
57 * A START condition has been transmitted.
58 * We now send the slave address and initialize
59 * the write buffer
60 * (we always start with a write after START+SLA)
61 */
62 WrIndex = 0;
63 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
64 I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
65 I2CMasterState = I2CSTATE_PENDING;
66 break;
67
68 case 0x10:
69 /*
70 * A repeated START condition has been transmitted.
71 * Now a second, read, transaction follows so we
72 * initialize the read buffer.
73 */
74 RdIndex = 0;
75 /* Send SLA with R bit set, */
76 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
77 I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
78 break;
79
80 case 0x18:
81 /*
82 * SLA+W has been transmitted; ACK has been received.
83 * We now start writing bytes.
84 */
85 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
86 I2C_I2CCONCLR = I2CONCLR_SIC;
87 break;
88
89 case 0x20:
90 /*
91 * SLA+W has been transmitted; NOT ACK has been received.
92 * Send a stop condition to terminate the transaction
93 * and signal I2CEngine the transaction is aborted.
94 */
95 I2C_I2CCONSET = I2CONSET_STO;
96 I2C_I2CCONCLR = I2CONCLR_SIC;
97 I2CMasterState = I2CSTATE_SLA_NACK;
98 break;
99
100 case 0x28:
101 /*
102 * Data in I2DAT has been transmitted; ACK has been received.
103 * Continue sending more bytes as long as there are bytes to send
104 * and after this check if a read transaction should follow.
105 */
106 if ( WrIndex < I2CWriteLength )
107 {
108 /* Keep writing as long as bytes avail */
109 I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
110 }
111 else
112 {
113 if ( I2CReadLength != 0 )
114 {
115 /* Send a Repeated START to initialize a read transaction */
116 /* (handled in state 0x10) */
117 I2C_I2CCONSET = I2CONSET_STA; /* Set Repeated-start flag */
118 }
119 else
120 {
121 I2CMasterState = I2CSTATE_ACK;
122 I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
123 }
124 }
125 I2C_I2CCONCLR = I2CONCLR_SIC;
126 break;
127
128 case 0x30:
129 /*
130 * Data byte in I2DAT has been transmitted; NOT ACK has been received
131 * Send a STOP condition to terminate the transaction and inform the
132 * I2CEngine that the transaction failed.
133 */
134 I2C_I2CCONSET = I2CONSET_STO;
135 I2C_I2CCONCLR = I2CONCLR_SIC;
136 I2CMasterState = I2CSTATE_NACK;
137 break;
138
139 case 0x38:
140 /*
141 * Arbitration loss in SLA+R/W or Data bytes.
142 * This is a fatal condition, the transaction did not complete due
143 * to external reasons (e.g. hardware system failure).
144 * Inform the I2CEngine of this and cancel the transaction
145 * (this is automatically done by the I2C hardware)
146 */
147 I2CMasterState = I2CSTATE_ARB_LOSS;
148 I2C_I2CCONCLR = I2CONCLR_SIC;
149 break;
150
151 case 0x40:
152 /*
153 * SLA+R has been transmitted; ACK has been received.
154 * Initialize a read.
155 * Since a NOT ACK is sent after reading the last byte,
156 * we need to prepare a NOT ACK in case we only read 1 byte.
157 */
158 if ( I2CReadLength == 1 )
159 {
160 /* last (and only) byte: send a NACK after data is received */
161 I2C_I2CCONCLR = I2CONCLR_AAC;
162 }
163 else
164 {
165 /* more bytes to follow: send an ACK after data is received */
166 I2C_I2CCONSET = I2CONSET_AA;
167 }
168 I2C_I2CCONCLR = I2CONCLR_SIC;
169 break;
170
171 case 0x48:
172 /*
173 * SLA+R has been transmitted; NOT ACK has been received.
174 * Send a stop condition to terminate the transaction
175 * and signal I2CEngine the transaction is aborted.
176 */
177 I2C_I2CCONSET = I2CONSET_STO;
178 I2C_I2CCONCLR = I2CONCLR_SIC;
179 I2CMasterState = I2CSTATE_SLA_NACK;
180 break;
181
182 case 0x50:
183 /*
184 * Data byte has been received; ACK has been returned.
185 * Read the byte and check for more bytes to read.
186 * Send a NOT ACK after the last byte is received
187 */
188 I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
189 if ( RdIndex < (I2CReadLength-1) )
190 {
191 /* lmore bytes to follow: send an ACK after data is received */
192 I2C_I2CCONSET = I2CONSET_AA;
193 }
194 else
195 {
196 /* last byte: send a NACK after data is received */
197 I2C_I2CCONCLR = I2CONCLR_AAC;
198 }
199 I2C_I2CCONCLR = I2CONCLR_SIC;
200 break;
201
202 case 0x58:
203 /*
204 * Data byte has been received; NOT ACK has been returned.
205 * This is the last byte to read.
206 * Generate a STOP condition and flag the I2CEngine that the
207 * transaction is finished.
208 */
209 I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
210 I2CMasterState = I2CSTATE_ACK;
211 I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
212 I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
213 break;
214
215
216 /* Slave Mode */
217
218 // case 0x60: /* An own SLA_W has been received. */
219 // case 0x70:
220 // RdIndex = 0;
221 // I2C_I2CCONSET = I2CONSET_AA; /* assert ACK after SLV_W is received */
222 // I2C_I2CCONCLR = I2CONCLR_SIC;
223 // I2CSlaveState = I2C_WR_STARTED;
224 // break;
225 //
226 // case 0x80: /* data receive */
227 // case 0x90:
228 // if ( I2CSlaveState == I2C_WR_STARTED )
229 // {
230 // I2CRdBuffer[RdIndex++] = I2C_I2CDAT;
231 // I2C_I2CCONSET = I2CONSET_AA; /* assert ACK after data is received */
232 // }
233 // else
234 // {
235 // I2C_I2CCONCLR = I2CONCLR_AAC; /* assert NACK */
236 // }
237 // // ToDo: Set a flag to indicate data is ready and process it somewhere
238 // I2C_I2CCONCLR = I2CONCLR_SIC;
239 // break;
240 //
241 // case 0xA8: /* An own SLA_R has been received. */
242 // case 0xB0:
243 // // RdIndex = 0;
244 // WrIndex = I2CRdBuffer[0]; /* The 1st byte is the index. */
245 // I2C_I2CDAT = I2CRdBuffer[WrIndex+1]; /* write the same data back to master */
246 // WrIndex++; /* Need to skip the index byte in RdBuffer */
247 // I2C_I2CCONSET = I2CONSET_AA; /* assert ACK after SLV_R is received */
248 // I2C_I2CCONCLR = I2CONCLR_SIC;
249 // I2CSlaveState = I2C_RD_STARTED;
250 // break;
251 //
252 // case 0xB8: /* Data byte has been transmitted */
253 // case 0xC8:
254 // if ( I2CSlaveState == I2C_RD_STARTED )
255 // {
256 // I2C_I2CDAT = I2CRdBuffer[WrIndex+1]; /* write the same data back to master */
257 // WrIndex++; /* Need to skip the index byte in RdBuffer */
258 // I2C_I2CCONSET = I2CONSET_AA; /* assert ACK */
259 // }
260 // else
261 // {
262 // I2C_I2CCONCLR = I2CONCLR_AAC; /* assert NACK */
263 // }
264 // I2C_I2CCONCLR = I2CONCLR_SIC;
265 // break;
266 //
267 // case 0xC0: /* Data byte has been transmitted, NACK */
268 // I2C_I2CCONCLR = I2CONCLR_AAC; /* assert NACK */
269 // I2C_I2CCONCLR = I2CONCLR_SIC;
270 // I2CSlaveState = DATA_NACK;
271 // break;
272 //
273 // case 0xA0: /* Stop condition or repeated start has */
274 // I2C_I2CCONSET = I2CONSET_AA; /* been received, assert ACK. */
275 // I2C_I2CCONCLR = I2CONCLR_SIC;
276 // I2CSlaveState = I2C_IDLE;
277 // break;
278
279 default:
280 I2C_I2CCONCLR = I2CONCLR_SIC;
281 // if (_I2cMode = I2CSLAVE)
282 // {
283 // I2C_I2CCONSET = I2CONSET_I2EN | I2CONSET_SI;
284 // }
285 break;
286 }
287 return;
288 }
289
290 /*****************************************************************************
291 ** Function name: I2CStart
292 **
293 ** Descriptions: Create I2C start condition, a timeout
294 ** value is set if the I2C never gets started,
295 ** and timed out. It's a fatal error.
296 **
297 ** parameters: None
298 ** Returned value: true or false, return false if timed out
299 **
300 *****************************************************************************/
301 static uint32_t I2CStart( void )
302 {
303 uint32_t timeout = 0;
304
305 /*--- Issue a start condition ---*/
306 I2C_I2CCONSET = I2CONSET_STA; /* Set Start flag */
307
308 while((I2CMasterState != I2CSTATE_PENDING) && (timeout < MAX_TIMEOUT))
309 {
310 timeout++;
311 }
312
313 return (timeout < MAX_TIMEOUT);
314 }
315
316 /*****************************************************************************
317 ** Function name: I2CStop
318 **
319 ** Descriptions: Set the I2C stop condition
320 **
321 ** parameters: None
322 ** Returned value: true or never return
323 **
324 *****************************************************************************/
325 static uint32_t I2CStop( void )
326 {
327 uint32_t timeout = 0;
328
329 I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
330 I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
331
332 /*--- Wait for STOP detected ---*/
333 while((I2C_I2CCONSET & I2CONSET_STO) && (timeout < MAX_TIMEOUT))
334 {
335 timeout++;
336 }
337 return (timeout >= MAX_TIMEOUT);
338 }
339
340 /*****************************************************************************
341 ** Function name: I2CInit
342 **
343 ** Descriptions: Initialize I2C controller
344 **
345 ** parameters: I2c mode is either MASTER or SLAVE
346 ** Returned value: true or false, return false if the I2C
347 ** interrupt handler was not installed correctly
348 **
349 *****************************************************************************/
350 uint32_t i2cInit( uint32_t I2cMode )
351 {
352 _I2cMode = I2cMode;
353
354 SCB_PRESETCTRL |= (0x1<<1);
355
356 // Enable I2C clock
357 SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_I2C);
358
359 // Configure pin 0.4 for SCL
360 IOCON_PIO0_4 &= ~(IOCON_PIO0_4_FUNC_MASK | IOCON_PIO0_4_I2CMODE_MASK);
361 IOCON_PIO0_4 |= (IOCON_PIO0_4_FUNC_I2CSCL);
362
363 // Configure pin 0.5 for SDA
364 IOCON_PIO0_5 &= ~(IOCON_PIO0_5_FUNC_MASK | IOCON_PIO0_5_I2CMODE_MASK);
365 IOCON_PIO0_5 |= IOCON_PIO0_5_FUNC_I2CSDA;
366
367 // Clear flags
368 I2C_I2CCONCLR = I2C_I2CCONCLR_AAC |
369 I2C_I2CCONCLR_SIC |
370 I2C_I2CCONCLR_STAC |
371 I2C_I2CCONCLR_I2ENC;
372
373 // See p.128 for appropriate values for SCLL and SCLH
374 #if I2C_FAST_MODE_PLUS
375 IOCON_PIO0_4 |= (IOCON_PIO0_4_I2CMODE_FASTPLUSI2C);
376 IOCON_PIO0_5 |= (IOCON_PIO0_5_I2CMODE_FASTPLUSI2C);
377 I2C_I2CSCLL = I2C_SCLL_HS_SCLL;
378 I2C_I2CSCLH = I2C_SCLH_HS_SCLH;
379 #else
380 I2C_I2CSCLL = I2SCLL_SCLL;
381 I2C_I2CSCLH = I2SCLH_SCLH;
382 #endif
383
384 if ( _I2cMode == I2CSLAVE )
385 {
386 I2C_I2CADR0 = SLAVE_ADDR;
387 I2CSlaveState = I2C_IDLE;
388 }
389
390 /* Enable the I2C Interrupt */
391 NVIC_EnableIRQ(I2C_IRQn);
392 if ( _I2cMode == I2CMASTER )
393 {
394 I2C_I2CCONSET = I2C_I2CCONSET_I2EN;
395 }
396 // else
397 // {
398 // I2C_I2CCONSET = I2C_I2CCONSET_I2EN | I2C_I2CCONSET_SI;
399 // }
400
401 return( TRUE );
402 }
403
404 /*****************************************************************************
405 ** Function name: I2CEngine
406 **
407 ** Descriptions: The routine to complete a I2C transaction
408 ** from start to stop. All the intermitten
409 ** steps are handled in the interrupt handler.
410 ** Before this routine is called, the read
411 ** length, write length and I2C master buffer
412 ** need to be filled.
413 **
414 ** parameters: None
415 ** Returned value: Any of the I2CSTATE_... values. See i2c.h
416 **
417 *****************************************************************************/
418 uint32_t i2cEngine( void )
419 {
420 I2CMasterState = I2CSTATE_IDLE;
421 RdIndex = 0;
422 WrIndex = 0;
423 if ( I2CStart() != TRUE )
424 {
425 I2CStop();
426 return ( FALSE );
427 }
428
429 /* wait until the state is a terminal state */
430 while (I2CMasterState < 0x100);
431
432 return ( I2CMasterState );
433 }
434
435 /******************************************************************************
436 ** End Of File
437 ******************************************************************************/
438
This page took 0.069514 seconds and 5 git commands to generate.