| 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.c
Go to the documentation of this file.
1 /*
2 * @brief I2C example.
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 <stdlib.h>
33 #include <string.h>
34 #include "board.h"
35
72 /*****************************************************************************
73 * Private types/enumerations/variables
74 ****************************************************************************/
75 #define DEFAULT_I2C I2C0
76
77 #define I2C_EEPROM_BUS DEFAULT_I2C
78 #define I2C_IOX_BUS DEFAULT_I2C
79
80 #define SPEED_100KHZ 100000
81 #define SPEED_400KHZ 400000
82
83 #ifdef DEBUG_ENABLE
84 static const char menu[] =
85 "**************** I2C Demo Menu ****************\r\n"
86 "\t0: Exit Demo\r\n"
87 "\t1: Select I2C peripheral [\033[1;32mI2C%d\033[0;37m]\r\n"
88 "\t2: Toggle mode POLLING/INTERRUPT [\033[1;32m%s\033[0;37m]\r\n"
89 "\t3: Probe for Slave devices\r\n"
90 "\t4: Read slave data\r\n"
91 "\t5: Write slave data\r\n"
92 "\t6: Write/Read slave data\r\n";
93 #endif
94
95 static int mode_poll; /* Poll/Interrupt mode flag */
96 static I2C_ID_T i2cDev = DEFAULT_I2C; /* Currently active I2C device */
97
98 /* EEPROM SLAVE data */
99 #define I2C_SLAVE_EEPROM_SIZE 64
100 #define I2C_SLAVE_EEPROM_ADDR 0x5A
101 #define I2C_SLAVE_IOX_ADDR 0x5B
102
103 /* Xfer structure for slave operations */
104 static I2C_XFER_T seep_xfer;
105 static I2C_XFER_T iox_xfer;
106
107 /* Data area for slave operations */
108 static uint8_t seep_data[I2C_SLAVE_EEPROM_SIZE + 1];
109 static uint8_t buffer[2][256];
110 static uint8_t iox_data[2]; /* PORT0 input port, PORT1 Output port */
111 static volatile uint32_t tick_cnt;
112
113 /*****************************************************************************
114 * Public types/enumerations/variables
115 ****************************************************************************/
116
117 /*****************************************************************************
118 * Private functions
119 ****************************************************************************/
120
121 /* State machine handler for I2C0 and I2C1 */
122 static void i2c_state_handling(I2C_ID_T id)
123 {
124 if (Chip_I2C_IsMasterActive(id)) {
125 Chip_I2C_MasterStateHandler(id);
126 } else {
127 Chip_I2C_SlaveStateHandler(id);
128 }
129 }
130
131 /* Print data to console */
132 static void con_print_data(const uint8_t *dat, int sz)
133 {
134 int i;
135 if (!sz) return;
136 for (i = 0; i < sz; i++) {
137 if (!(i & 0xF)) DEBUGOUT("\r\n%02X: ", i);
138 DEBUGOUT(" %02X", dat[i]);
139 }
140 DEBUGOUT("\r\n");
141 }
142
143 /* Get an integer input from UART */
144 static int con_get_input(const char *str)
145 {
146 #ifdef DEBUG_ENABLE
147 int input_valid = 0;
148 int x;
149 char ch[16], *ptr;
150 int i = 0;
151
152 while (!input_valid) {
153 DEBUGOUT("%s", str);
154 while(1) {
155 /* Setting poll mode for slave is a very bad idea, it works nevertheless */
156 if((mode_poll & (1 << i2cDev)) && Chip_I2C_IsStateChanged(i2cDev)) {
157 Chip_I2C_SlaveStateHandler(i2cDev);
158 }
159
160 x = DEBUGIN();
161 if (x == EOF) continue;
162 if (i >= sizeof(ch) - 2) break;
163 if ((x == '\r' || x == '\n') && i) {
164 DEBUGOUT("\r\n");
165 break;
166 }
167 if (x == '\b') {
168 if (i) {
169 DEBUGOUT("\033[1D \033[1D");
170 i --;
171 }
172 continue;
173 }
174 DEBUGOUT("%c", x);
175 ch[i++] = x;
176 };
177 ch[i] = 0;
178 i = strtol(ch, &ptr, 0);
179 if (*ptr) {
180 i = 0;
181 DEBUGOUT("Invalid input. Retry!\r\n");
182 continue;
183 }
184 input_valid = 1;
185 }
186 return i;
187 #else
188 static int sind = -1;
189 static uint8_t val[] = {5, I2C_SLAVE_IOX_ADDR, 1, 0};
190 if (sind >= sizeof(val)) sind = -1;
191 while (sind < 0 && (tick_cnt & 0x7F)) {}
192 if (sind < 0){
193 sind = 0;
194 val[3] = !val[3];
195 tick_cnt++;
196 }
197 return val[sind++];
198 #endif
199 }
200
201 static void i2c_rw_input(I2C_XFER_T *xfer, int ops)
202 {
203 int tmp, i;
204
205 tmp = con_get_input("Enter 7-Bit Slave address : ");
206 tmp &= 0xFF;
207 xfer->slaveAddr = tmp;
208 xfer->rxBuff = 0;
209 xfer->txBuff = 0;
210 xfer->txSz = 0;
211 xfer->rxSz = 0;
212
213 if (ops & 1) {
214 tmp = con_get_input("Enter number of bytes to read : ");
215 tmp &= 0xFF;
216 xfer->rxSz = tmp;
217 xfer->rxBuff = buffer[1];
218 }
219
220 if (ops & 2) {
221 tmp = con_get_input("Enter number of bytes to write : ");
222 tmp &= 0xFF;
223 for (i = 0; i < tmp; i++) {
224 DEBUGOUT("%d:", i + 1);
225 buffer[0][i] = con_get_input("Enter Data: ");
226 }
227 xfer->txSz = tmp;
228 xfer->txBuff = buffer[0];
229 }
230 }
231
232 /* Set I2C mode to polling/interrupt */
233 static void i2c_set_mode(I2C_ID_T id, int polling)
234 {
235 if(!polling) {
236 mode_poll &= ~(1 << id);
237 Chip_I2C_SetMasterEventHandler(id, Chip_I2C_EventHandler);
238 NVIC_EnableIRQ(I2C0_IRQn);
239 } else {
240 mode_poll |= 1 << id;
241 NVIC_DisableIRQ(I2C0_IRQn);
242 Chip_I2C_SetMasterEventHandler(id, Chip_I2C_EventHandlerPolling);
243 }
244 }
245
246 /* Initialize the I2C bus */
247 static void i2c_app_init(I2C_ID_T id, int speed)
248 {
249 Board_I2C_Init(id);
250
251 /* Initialize I2C */
252 Chip_I2C_Init(id);
253 Chip_I2C_SetClockRate(id, speed);
254
255 /* Set default mode to interrupt */
256 i2c_set_mode(id, 0);
257 }
258
259 /* Function that probes all available slaves connected to an I2C bus */
260 static void i2c_probe_slaves(I2C_ID_T i2c)
261 {
262 int i;
263 uint8_t ch[2];
264
265 DEBUGOUT("Probing available I2C devices...\r\n");
266 DEBUGOUT("\r\n 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
267 DEBUGOUT("\r\n====================================================");
268 for (i = 0; i <= 0x7F; i++) {
269 if (!(i & 0x0F)) DEBUGOUT("\r\n%02X ", i >> 4);
270 if (i <= 7 || i > 0x78) {
271 DEBUGOUT(" ");
272 continue;
273 }
274 /* Address 0x48 points to LM75AIM device which needs 2 bytes be read */
275 if(Chip_I2C_MasterRead(i2c, i, ch, 1 + (i == 0x48)) > 0)
276 DEBUGOUT(" %02X", i);
277 else
278 DEBUGOUT(" --");
279 }
280 DEBUGOUT("\r\n");
281 }
282
283 static int i2c_menu(void)
284 {
285 DEBUGOUT(menu, i2cDev, (mode_poll & (1 << i2cDev)) ? "POLLING" : "INTERRUPT");
286 return con_get_input("\r\nSelect an option [0 - 6] :");
287 }
288
289 /* Update the EEPROM state */
290 static void i2c_eeprom_update_state(I2C_XFER_T *xfer, uint8_t *buff, int sz)
291 {
292 xfer->txBuff = xfer->rxBuff = &buff[buff[0]+1];
293 xfer->rxSz = xfer->txSz = sz - buff[0] + 1;
294 }
295
296 /* Slave event handler for simulated EEPROM */
297 static void i2c_eeprom_events(I2C_ID_T id, I2C_EVENT_T event)
298 {
299 static int is_addr = 1;
300 switch(event) {
301 case I2C_EVENT_DONE:
302 is_addr = 1;
303 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
304 seep_xfer.rxBuff = seep_data;
305 seep_xfer.rxSz ++;
306 break;
307
308 case I2C_EVENT_SLAVE_RX:
309 if (is_addr) {
310 is_addr = 0;
311 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1); /* Correct addr if required */
312 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
313 break;
314 }
315
316 seep_data[0] ++;
317 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
318 if (seep_xfer.rxSz == 1)
319 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
320 break;
321
322 case I2C_EVENT_SLAVE_TX:
323 seep_data[0] ++;
324 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
325 if (seep_xfer.txSz == 1)
326 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
327 break;
328 }
329 }
330
331 /* Simulate an I2C EEPROM slave */
332 static void i2c_eeprom_init(I2C_ID_T id)
333 {
334 memset(&seep_data[1], 0xFF, I2C_SLAVE_EEPROM_SIZE);
335 seep_xfer.slaveAddr = (I2C_SLAVE_EEPROM_ADDR << 1);
336 seep_xfer.txBuff = &seep_data[1];
337 seep_xfer.rxBuff = seep_data;
338 seep_xfer.txSz = seep_xfer.rxSz = sizeof(seep_data);
339 Chip_I2C_SlaveSetup(id, I2C_SLAVE_0, &seep_xfer, i2c_eeprom_events, 0);
340 }
341 /*-------- IO Expansion slave device implementation ----------*/
342 /* Update IN/OUT port states to real devices */
343 void i2c_iox_update_regs(int ops)
344 {
345 if (ops & 1) { /* update out port */
346 Board_LED_Set(0, iox_data[1] & 1);
347 Board_LED_Set(1, iox_data[1] & 2);
348 Board_LED_Set(2, iox_data[1] & 4);
349 Board_LED_Set(3, iox_data[1] & 8);
350 }
351
352 #ifndef CHIP_LPC11CXX
353 if (ops & 2) { /* update in port */
354 iox_data[0] = (uint8_t) Buttons_GetStatus();
355 }
356 #endif
357 }
358
359 /* Slave event handler for simulated EEPROM */
360 static void i2c_iox_events(I2C_ID_T id, I2C_EVENT_T event)
361 {
362 switch(event) {
363 case I2C_EVENT_DONE:
364 iox_xfer.rxBuff = &iox_data[1];
365 iox_xfer.rxSz = sizeof(iox_data);
366 iox_xfer.txBuff = (const uint8_t *)iox_data;
367 iox_xfer.txSz = sizeof(iox_data) + 1;
368 break;
369
370 case I2C_EVENT_SLAVE_RX:
371 iox_xfer.rxBuff = &iox_data[1];
372 iox_xfer.rxSz = sizeof(iox_data);
373 i2c_iox_update_regs(1);
374 break;
375
376 case I2C_EVENT_SLAVE_TX:
377 if(iox_xfer.txSz == 1) {
378 iox_xfer.txBuff = (const uint8_t *)iox_data[0];
379 iox_xfer.txSz = sizeof(iox_data) + 1;
380 }
381 break;
382 }
383 }
384
385 /* Simulate an IO Expansion slave device */
386 static void i2c_iox_init(I2C_ID_T id)
387 {
388 #ifndef CHIP_LPC11CXX
389 Board_Buttons_Init();
390 #endif
391 iox_xfer.slaveAddr = (I2C_SLAVE_IOX_ADDR << 1);
392 i2c_iox_events(id, I2C_EVENT_DONE);
393 Chip_I2C_SlaveSetup(id, I2C_SLAVE_1, &iox_xfer, i2c_iox_events, 0);
394 i2c_iox_update_regs(3);
395 /* Setup SysTick timer to get the button status updated at regular intervals */
396 SysTick_Config(Chip_Clock_GetSystemClockRate() / 50);
397 }
398
399 /*-------------------- End of IO Expansion slave device ----------------------*/
400
401 /*****************************************************************************
402 * Public functions
403 ****************************************************************************/
409 void SysTick_Handler(void)
410 {
411 i2c_iox_update_regs(2);
412 tick_cnt ++;
413 }
414
419 void I2C_IRQHandler(void)
420 {
421 i2c_state_handling(I2C0);
422 }
423
428 int main(void)
429 {
430 int tmp;
431 int xflag = 0;
432 static I2C_XFER_T xfer;
433
434 Board_Init();
435 i2c_app_init(I2C0, SPEED_100KHZ);
436
437 /* Simulate an EEPROM slave in I2C0 */
438 i2c_eeprom_init(I2C_EEPROM_BUS);
439
440 /* Simuldate an IO Expansion slave in I2C0 */
441 i2c_iox_init(I2C_IOX_BUS);
442
443 while (!xflag) {
444 switch(i2c_menu()) {
445 case 0:
446 xflag = 1;
447 DEBUGOUT("End of I2C Demo! Bye!\r\n");
448 break;
449
450 case 1:
451 i2cDev = I2C0;
452 break;
453
454 case 2:
455 i2c_set_mode(i2cDev, !(mode_poll & (1 << i2cDev)));
456 break;
457
458 case 3:
459 i2c_probe_slaves(i2cDev);
460 break;
461
462 case 4:
463 i2c_rw_input(&xfer, 1);
464 tmp = Chip_I2C_MasterRead(i2cDev, xfer.slaveAddr, xfer.rxBuff, xfer.rxSz);
465 DEBUGOUT("Read %d bytes of data from slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
466 con_print_data(buffer[1], tmp);
467 break;
468
469 case 5:
470 i2c_rw_input(&xfer, 2);
471 if (xfer.txSz == 0) break;
472 tmp = Chip_I2C_MasterSend(i2cDev, xfer.slaveAddr, xfer.txBuff, xfer.txSz);
473 DEBUGOUT("Written %d bytes of data to slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
474 break;
475
476 case 6:
477 i2c_rw_input(&xfer, 3);
478 tmp = xfer.rxSz;
479 if (!tmp && !xfer.txSz) break;
480 Chip_I2C_MasterTransfer(i2cDev, &xfer);
481 DEBUGOUT("Master transfer : %s\r\n",
482 xfer.status == I2C_STATUS_DONE ? "SUCCESS" : "FAILURE");
483 DEBUGOUT("Received %d bytes from slave 0x%02X\r\n", tmp - xfer.rxSz, xfer.slaveAddr);
484 con_print_data(buffer[1], tmp - xfer.rxSz);
485 break;
486
487 default:
488 DEBUGOUT("Input Invalid! Try Again.\r\n");
489 }
490 }
491 Chip_I2C_DeInit(I2C0);
492
493 return 0;
494 }
495