LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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  * This example show how to use the I2C interface
4  *
5  * @note
6  * Copyright(C) NXP Semiconductors, 2012
7  * All rights reserved.
8  *
9  * @par
10  * Software that is described herein is for illustrative purposes only
11  * which provides customers with programming information regarding the
12  * LPC products. This software is supplied "AS IS" without any warranties of
13  * any kind, and NXP Semiconductors and its licensor disclaim any and
14  * all warranties, express or implied, including all implied warranties of
15  * merchantability, fitness for a particular purpose and non-infringement of
16  * intellectual property rights. NXP Semiconductors assumes no responsibility
17  * or liability for the use of the software, conveys no license or rights under any
18  * patent, copyright, mask work right, or any other intellectual property rights in
19  * or to any products. NXP Semiconductors reserves the right to make changes
20  * in the software without notification. NXP Semiconductors also makes no
21  * representation or warranty that such application will be suitable for the
22  * specified use without further testing or modification.
23  *
24  * @par
25  * Permission to use, copy, modify, and distribute this software and its
26  * documentation is hereby granted, under NXP Semiconductors' and its
27  * licensor's relevant copyrights in the software, without fee, provided that it
28  * is used in conjunction with NXP Semiconductors microcontrollers. This
29  * copyright, permission, and disclaimer notice must appear in all copies of
30  * this code.
31  */
32 
33 #include <stdlib.h>
34 #include <string.h>
35 #include "board.h"
36 
136 /*****************************************************************************
137  * Private types/enumerations/variables
138  ****************************************************************************/
139 #ifdef DEBUG_ENABLE
140 #define DEFAULT_I2C I2C0
141 #else
142 #define DEFAULT_I2C I2C1
143 #endif
144 
145 #define I2C_EEPROM_BUS DEFAULT_I2C
146 #define I2C_IOX_BUS DEFAULT_I2C
147 
148 #define SPEED_100KHZ 100000
149 #define SPEED_400KHZ 400000
150 
151 #ifdef DEBUG_ENABLE
152 static const char menu[] =
153  "**************** I2C Demo Menu ****************\r\n"
154  "\t0: Exit Demo\r\n"
155  "\t1: Select I2C peripheral [\033[1;32mI2C%d\033[0;37m]\r\n"
156  "\t2: Toggle mode POLLING/INTERRUPT [\033[1;32m%s\033[0;37m]\r\n"
157  "\t3: Probe for Slave devices\r\n"
158  "\t4: Read slave data\r\n"
159  "\t5: Write slave data\r\n"
160  "\t6: Write/Read slave data\r\n";
161 #endif
162 
163 static int mode_poll; /* Poll/Interrupt mode flag */
164 static I2C_ID_T i2cDev = DEFAULT_I2C; /* Currently active I2C device */
165 
166 /* EEPROM SLAVE data */
167 #define I2C_SLAVE_EEPROM_SIZE 64
168 #define I2C_SLAVE_EEPROM_ADDR 0x5A
169 #define I2C_SLAVE_IOX_ADDR 0x5B
170 
171 /* Xfer structure for slave operations */
174 
175 /* Data area for slave operations */
176 static uint8_t seep_data[I2C_SLAVE_EEPROM_SIZE + 1];
177 static uint8_t buffer[2][256];
178 static uint8_t iox_data[2]; /* PORT0 input port, PORT1 Output port */
179 
180 /*****************************************************************************
181  * Public types/enumerations/variables
182  ****************************************************************************/
183 
184 /*****************************************************************************
185  * Private functions
186  ****************************************************************************/
187 
188 /* State machine handler for I2C0 and I2C1 */
190 {
191  if (Chip_I2C_IsMasterActive(id)) {
193  }
194  else {
196  }
197 }
198 
199 /* Print data to console */
200 static void con_print_data(const uint8_t *dat, int sz)
201 {
202  int i;
203  if (!sz) {
204  return;
205  }
206  for (i = 0; i < sz; i++) {
207  if (!(i & 0xF)) {
208  DEBUGOUT("\r\n%02X: ", i);
209  }
210  DEBUGOUT(" %02X", dat[i]);
211  }
212  DEBUGOUT("\r\n");
213 }
214 
215 /* Get an integer input from UART */
216 static int con_get_input(const char *str)
217 {
218 #ifdef DEBUG_ENABLE
219  int input_valid = 0;
220  int x;
221  char ch[16], *ptr;
222  int i = 0;
223 
224  while (!input_valid) {
225  DEBUGOUT("%s", str);
226  while (1) {
227  /* Setting poll mode for slave is a very bad idea, it works nevertheless */
228  if ((mode_poll & (1 << i2cDev)) && Chip_I2C_IsStateChanged(i2cDev)) {
230  }
231 
232  x = DEBUGIN();
233  if (x == EOF) {
234  continue;
235  }
236  if (i >= sizeof(ch) - 2) {
237  break;
238  }
239  if (((x == '\r') || (x == '\n')) && i) {
240  DEBUGOUT("\r\n");
241  break;
242  }
243  if (x == '\b') {
244  if (i) {
245  DEBUGOUT("\033[1D \033[1D");
246  i--;
247  }
248  continue;
249  }
250  DEBUGOUT("%c", x);
251  ch[i++] = x;
252  }
253  ch[i] = 0;
254  i = strtol(ch, &ptr, 0);
255  if (*ptr) {
256  i = 0;
257  DEBUGOUT("Invalid input. Retry!\r\n");
258  continue;
259  }
260  input_valid = 1;
261  }
262  return i;
263 #else
264  int pressed = 0;
265  volatile uint8_t *pkey = &iox_data[0];
266  static int sind = -1;
267  static uint8_t val[] = {5, I2C_SLAVE_IOX_ADDR, 1, 0};
268  if (sind >= sizeof(val)) {
269  sind = -1;
270  }
271 
272  while (sind < 0) {
273  if (*pkey) {
274  pressed = 1;
275  }
276  if (*pkey && pressed) {
277  continue;
278  }
279  if (!*pkey && !pressed) {
280  continue;
281  }
282  pressed = 0;
283  sind = 0;
284  val[3]++; val[3] &= 0x3;
285  }
286  return val[sind++];
287 #endif
288 }
289 
290 static void i2c_rw_input(I2C_XFER_T *xfer, int ops)
291 {
292  int tmp, i;
293 
294  tmp = con_get_input("Enter 7-Bit Slave address : ");
295  tmp &= 0xFF;
296  xfer->slaveAddr = tmp;
297  xfer->rxBuff = 0;
298  xfer->txBuff = 0;
299  xfer->txSz = 0;
300  xfer->rxSz = 0;
301 
302  if (ops & 1) {
303  tmp = con_get_input("Enter number of bytes to read : ");
304  tmp &= 0xFF;
305  xfer->rxSz = tmp;
306  xfer->rxBuff = buffer[1];
307  }
308 
309  if (ops & 2) {
310  tmp = con_get_input("Enter number of bytes to write : ");
311  tmp &= 0xFF;
312  for (i = 0; i < tmp; i++) {
313  DEBUGOUT("%d:", i + 1);
314  buffer[0][i] = con_get_input("Enter Data: ");
315  }
316  xfer->txSz = tmp;
317  xfer->txBuff = buffer[0];
318  }
319 }
320 
321 /* Set I2C mode to polling/interrupt */
322 static void i2c_set_mode(I2C_ID_T id, int polling)
323 {
324  if (!polling) {
325  mode_poll &= ~(1 << id);
327  NVIC_EnableIRQ(id == I2C0 ? I2C0_IRQn : I2C1_IRQn);
328  }
329  else {
330  mode_poll |= 1 << id;
331  NVIC_DisableIRQ(id == I2C0 ? I2C0_IRQn : I2C1_IRQn);
333  }
334 }
335 
336 /* Initialize the I2C bus */
337 static void i2c_app_init(I2C_ID_T id, int speed)
338 {
339  Board_I2C_Init(id);
340 
341  /* Initialize I2C */
342  Chip_I2C_Init(id);
343  Chip_I2C_SetClockRate(id, speed);
344 
345  /* Set default mode to interrupt */
346  i2c_set_mode(id, 0);
347 }
348 
349 /* Function that probes all available slaves connected to an I2C bus */
351 {
352  int i;
353  uint8_t ch[2];
354 
355  DEBUGOUT("Probing available I2C devices...\r\n");
356  DEBUGOUT("\r\n 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
357  DEBUGOUT("\r\n====================================================");
358  for (i = 0; i <= 0x7F; i++) {
359  if (!(i & 0x0F)) {
360  DEBUGOUT("\r\n%02X ", i >> 4);
361  }
362  if ((i <= 7) || (i > 0x78)) {
363  DEBUGOUT(" ");
364  continue;
365  }
366  /* Address 0x48 points to LM75AIM device which needs 2 bytes be read */
367  if (Chip_I2C_MasterRead(i2c, i, ch, 1 + (i == 0x48)) > 0) {
368  DEBUGOUT(" %02X", i);
369  }
370  else {
371  DEBUGOUT(" --");
372  }
373  }
374  DEBUGOUT("\r\n");
375 }
376 
377 static int i2c_menu(void)
378 {
379  DEBUGOUT(menu, i2cDev, (mode_poll & (1 << i2cDev)) ? "POLLING" : "INTERRUPT");
380  return con_get_input("\r\nSelect an option [0 - 6] :");
381 }
382 
383 /* Update the EEPROM state */
384 static void i2c_eeprom_update_state(I2C_XFER_T *xfer, uint8_t *buff, int sz)
385 {
386  xfer->txBuff = xfer->rxBuff = &buff[buff[0] + 1];
387  xfer->rxSz = xfer->txSz = sz - buff[0] + 1; /* one byte more to avoid last byte problem */
388 }
389 
390 /* Slave event handler for simulated EEPROM */
392 {
393  static int is_addr = 1;
394  switch (event) {
395  case I2C_EVENT_DONE:
396  is_addr = 1;
398  seep_xfer.rxBuff = seep_data;
399  seep_xfer.rxSz++;
400  break;
401 
402  case I2C_EVENT_SLAVE_RX:
403  if (is_addr) {
404  is_addr = 0;
405  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1); /* Correct addr if required */
407  break;
408  }
409 
410  seep_data[0]++;
411  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
412  if (seep_xfer.rxSz == 1) {
414  }
415  break;
416 
417  case I2C_EVENT_SLAVE_TX:
418  seep_data[0]++;
419  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
420  if (seep_xfer.txSz == 1) {
422  }
423  break;
424  }
425 }
426 
427 /* Simulate an I2C EEPROM slave */
428 static void i2c_eeprom_init(I2C_ID_T id)
429 {
430  memset(&seep_data[1], 0xFF, I2C_SLAVE_EEPROM_SIZE);
431  seep_xfer.slaveAddr = (I2C_SLAVE_EEPROM_ADDR << 1);
432  seep_xfer.txBuff = &seep_data[1];
433  seep_xfer.rxBuff = seep_data;
434  seep_xfer.txSz = seep_xfer.rxSz = sizeof(seep_data);
436 }
437 
438 /*-------- IO Expansion slave device implementation ----------*/
439 /* Update IN/OUT port states to real devices */
440 void i2c_iox_update_regs(int ops)
441 {
442  if (ops & 1) { /* update out port */
443  Board_LED_Set(0, iox_data[1] & 1);
444  Board_LED_Set(1, iox_data[1] & 2);
445  Board_LED_Set(2, iox_data[1] & 4);
446  Board_LED_Set(3, iox_data[1] & 8);
447  }
448 
449  if (ops & 2) { /* update in port */
450  iox_data[0] = (uint8_t) Buttons_GetStatus();
451  }
452 }
453 
454 /* Slave event handler for simulated EEPROM */
456 {
457  switch (event) {
458  case I2C_EVENT_DONE:
459  iox_xfer.rxBuff = &iox_data[1];
460  iox_xfer.rxSz = sizeof(iox_data); /* one byte more to avoid last byte problem */
461  iox_xfer.txBuff = (const uint8_t *) iox_data;
462  iox_xfer.txSz = sizeof(iox_data) + 1; /* one byte more to avoid last byte problem */
463  break;
464 
465  case I2C_EVENT_SLAVE_RX:
466  iox_xfer.rxBuff = &iox_data[1];
467  iox_xfer.rxSz = sizeof(iox_data); /* one byte more to avoid last byte problem */
469  break;
470 
471  case I2C_EVENT_SLAVE_TX:
472  if (iox_xfer.txSz == 1) {
473  iox_xfer.txBuff = (const uint8_t *) iox_data[0];
474  iox_xfer.txSz = sizeof(iox_data) + 1; /* one byte more to avoid last byte problem */
475  }
476  break;
477  }
478 }
479 
480 /* Simulate an IO Expansion slave device */
481 static void i2c_iox_init(I2C_ID_T id)
482 {
484  iox_xfer.slaveAddr = (I2C_SLAVE_IOX_ADDR << 1);
486  Chip_I2C_SlaveSetup(id, I2C_SLAVE_1, &iox_xfer, i2c_iox_events, 0);
488  /* Setup SysTick timer to get the button status updated at regular intervals */
489  SysTick_Config(Chip_Clock_GetRate(CLK_MX_MXCORE) / 50);
490 }
491 
492 /*-------------------- End of IO Expansion slave device ----------------------*/
493 
494 /*****************************************************************************
495  * Public functions
496  ****************************************************************************/
502 void SysTick_Handler(void)
503 {
505 }
506 
511 void I2C1_IRQHandler(void)
512 {
514 }
515 
520 void I2C0_IRQHandler(void)
521 {
523 }
524 
529 int main(void)
530 {
531  int tmp;
532  int xflag = 0;
533  static I2C_XFER_T xfer;
534 
535  Board_Init();
538 
539  /* Simulate an EEPROM slave in I2C0 */
541 
542  /* Simuldate an IO Expansion slave in I2C0 */
544 
545  while (!xflag) {
546  switch (i2c_menu()) {
547  case 0:
548  xflag = 1;
549  DEBUGOUT("End of I2C Demo! Bye!\r\n");
550  break;
551 
552  case 1:
553  tmp = con_get_input("Select I2C device [0 or 1] : ");
554  DEBUGOUT("\r\n");
555  if ((I2C_ID_T) tmp == I2C0) {
556  if (i2cDev == I2C0) {
557  break;
558  }
559  i2c_set_mode(I2C0, 0);
560  i2cDev = I2C0;
561  }
562  else if ((I2C_ID_T) tmp == I2C1) {
563  if (i2cDev == I2C1) {
564  break;
565  }
566  i2c_set_mode(I2C1, 0);
567  i2cDev = I2C1;
568  }
569  else {
570  DEBUGOUT("Invalid I2C Device [Must be 0 or 1]\r\n");
571  }
572  break;
573 
574  case 2:
575  i2c_set_mode(i2cDev, !(mode_poll & (1 << i2cDev)));
576  break;
577 
578  case 3:
580  break;
581 
582  case 4:
583  i2c_rw_input(&xfer, 1);
584  tmp = Chip_I2C_MasterRead(i2cDev, xfer.slaveAddr, xfer.rxBuff, xfer.rxSz);
585  DEBUGOUT("Read %d bytes of data from slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
586  con_print_data(buffer[1], tmp);
587  break;
588 
589  case 5:
590  i2c_rw_input(&xfer, 2);
591  if (xfer.txSz == 0) {
592  break;
593  }
594  tmp = Chip_I2C_MasterSend(i2cDev, xfer.slaveAddr, xfer.txBuff, xfer.txSz);
595  DEBUGOUT("Written %d bytes of data to slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
596  break;
597 
598  case 6:
599  i2c_rw_input(&xfer, 3);
600  tmp = xfer.rxSz;
601  if (!tmp && !xfer.txSz) {
602  break;
603  }
605  DEBUGOUT("Master transfer : %s\r\n",
606  xfer.status == I2C_STATUS_DONE ? "SUCCESS" : "FAILURE");
607  DEBUGOUT("Received %d bytes from slave 0x%02X\r\n", tmp - xfer.rxSz, xfer.slaveAddr);
608  con_print_data(buffer[1], tmp - xfer.rxSz);
609  break;
610 
611  default:
612  DEBUGOUT("Input Invalid! Try Again.\r\n");
613  }
614  }
617 
618  return 0;
619 }
620