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  *
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 */
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 */
123 {
124  if (Chip_I2C_IsMasterActive(id)) {
126  } else {
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)) {
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);
238  NVIC_EnableIRQ(I2C0_IRQn);
239  } else {
240  mode_poll |= 1 << id;
241  NVIC_DisableIRQ(I2C0_IRQn);
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 */
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 */
298 {
299  static int is_addr = 1;
300  switch(event) {
301  case I2C_EVENT_DONE:
302  is_addr = 1;
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 */
313  break;
314  }
315 
316  seep_data[0] ++;
317  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
318  if (seep_xfer.rxSz == 1)
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)
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);
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 */
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);
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
390 #endif
391  iox_xfer.slaveAddr = (I2C_SLAVE_IOX_ADDR << 1);
393  Chip_I2C_SlaveSetup(id, I2C_SLAVE_1, &iox_xfer, i2c_iox_events, 0);
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 {
412  tick_cnt ++;
413 }
414 
419 void I2C_IRQHandler(void)
420 {
422 }
423 
428 int main(void)
429 {
430  int tmp;
431  int xflag = 0;
432  static I2C_XFER_T xfer;
433 
434  Board_Init();
436 
437  /* Simulate an EEPROM slave in I2C0 */
439 
440  /* Simuldate an IO Expansion slave in I2C0 */
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:
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;
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  }
492 
493  return 0;
494 }
495