]> git.sur5r.net Git - freertos/blob
d309b1eeceacd9653caef2df4566278975317a55
[freertos] /
1 /**********************************************************************\r
2 * $Id$          lpc18xx_i2c.c           2011-06-02\r
3 *//**\r
4 * @file         lpc18xx_i2c.c\r
5 * @brief        Contains all functions support for I2C firmware library\r
6 *                       on LPC18xx\r
7 * @version      1.0\r
8 * @date         02. June. 2011\r
9 * @author       NXP MCU SW Application Team\r
10 *\r
11 * Copyright(C) 2011, NXP Semiconductor\r
12 * All rights reserved.\r
13 *\r
14 ***********************************************************************\r
15 * Software that is described herein is for illustrative purposes only\r
16 * which provides customers with programming information regarding the\r
17 * products. This software is supplied "AS IS" without any warranties.\r
18 * NXP Semiconductors assumes no responsibility or liability for the\r
19 * use of the software, conveys no license or title under any patent,\r
20 * copyright, or mask work right to the product. NXP Semiconductors\r
21 * reserves the right to make changes in the software without\r
22 * notification. NXP Semiconductors also make no representation or\r
23 * warranty that such application will be suitable for the specified\r
24 * use without further testing or modification.\r
25 **********************************************************************/\r
26 \r
27 /* Peripheral group ----------------------------------------------------------- */\r
28 /** @addtogroup I2C\r
29  * @{\r
30  */\r
31 \r
32 /* Includes ------------------------------------------------------------------- */\r
33 #include "lpc18xx_i2c.h"\r
34 #include "lpc18xx_cgu.h"\r
35 #include "lpc18xx_scu.h"\r
36 \r
37 /* If this source file built with example, the LPC18xx FW library configuration\r
38  * file in each example directory ("lpc18xx_libcfg.h") must be included,\r
39  * otherwise the default FW library configuration file must be included instead\r
40  */\r
41 #ifdef __BUILD_WITH_EXAMPLE__\r
42 #include "lpc18xx_libcfg.h"\r
43 #else\r
44 #include "lpc18xx_libcfg_default.h"\r
45 #endif /* __BUILD_WITH_EXAMPLE__ */\r
46 \r
47 \r
48 #ifdef _I2C\r
49 \r
50 \r
51 /* Private Types -------------------------------------------------------------- */\r
52 /** @defgroup I2C_Private_Types I2C Private Types\r
53  * @{\r
54  */\r
55 #define SFSP2_3_CONFIGURE_I2C1_SDA                                      (0x00000001 | MD_ZI | MD_EZI)\r
56 #define SFSP2_4_CONFIGURE_I2C1_SCL                                      (0x00000001 | MD_ZI | MD_EZI)\r
57 #define SFSI2C0_CONFIGURE_STANDARD_FAST_MODE            (1<<3 | 1<<11)\r
58 #define SFSI2C0_CONFIGURE_FASTPLUS_HIGHSPEED_MODE       (2<<1 | 1<<3 | 1<<7 | 1<<10 | 1<<11)\r
59 \r
60 /**\r
61  * @brief I2C device configuration structure type\r
62  */\r
63 typedef struct\r
64 {\r
65   uint32_t      txrx_setup;                                             /* Transmission setup */\r
66   int32_t               dir;                                                            /* Current direction phase, 0 - write, 1 - read */\r
67 } I2C_CFG_T;\r
68 \r
69 /**\r
70  * @}\r
71  */\r
72 \r
73 /* Private Variables ---------------------------------------------------------- */\r
74 /**\r
75  * @brief II2C driver data for I2C0, I2C1\r
76  */\r
77 static I2C_CFG_T i2cdat[3];\r
78 \r
79 static uint32_t I2C_MasterComplete[3];\r
80 static uint32_t I2C_SlaveComplete[3];\r
81 \r
82 static uint32_t I2C_MonitorBufferIndex;\r
83 \r
84 /* Private Functions ---------------------------------------------------------- */\r
85 \r
86 /* Get I2C number */\r
87 static int32_t I2C_getNum(LPC_I2Cn_Type *I2Cx);\r
88 \r
89 /* Generate a start condition on I2C bus (in master mode only) */\r
90 static uint32_t I2C_Start (LPC_I2Cn_Type *I2Cx);\r
91 \r
92 /* Generate a stop condition on I2C bus (in master mode only) */\r
93 static void I2C_Stop (LPC_I2Cn_Type *I2Cx);\r
94 \r
95 /* I2C send byte subroutine */\r
96 static uint32_t I2C_SendByte (LPC_I2Cn_Type *I2Cx, uint8_t databyte);\r
97 \r
98 /* I2C get byte subroutine */\r
99 static uint32_t I2C_GetByte (LPC_I2Cn_Type *I2Cx, uint8_t *retdat, Bool ack);\r
100 \r
101 /*--------------------------------------------------------------------------------*/\r
102 /********************************************************************//**\r
103  * @brief               Convert from I2C peripheral to number\r
104  * @param[in]   I2Cx I2C peripheral selected, should be:\r
105  *                                      - LPC_I2C0      :I2C0 peripheral\r
106  *                                      - LPC_I2C1      :I2C1 peripheral\r
107  * @return              I2C number or error code, could be:\r
108  *                                      - 0             :I2C0\r
109  *                                      - 1             :I2C1\r
110  *                                      - (-1)  :Error\r
111  *********************************************************************/\r
112 static int32_t I2C_getNum(LPC_I2Cn_Type *I2Cx){\r
113         if (I2Cx == LPC_I2C0) {\r
114                 return (0);\r
115         } else if (I2Cx == LPC_I2C1) {\r
116                 return (1);\r
117         }\r
118         return (-1);\r
119 }\r
120 \r
121 \r
122 /********************************************************************//**\r
123  * @brief               Generate a start condition on I2C bus (in master mode only)\r
124  * @param[in]   I2Cx I2C peripheral selected, should be:\r
125  *                                      - LPC_I2C0      :I2C0 peripheral\r
126  *                                      - LPC_I2C1      :I2C1 peripheral\r
127  * @return              value of I2C status register after generate a start condition\r
128  *********************************************************************/\r
129 static uint32_t I2C_Start (LPC_I2Cn_Type *I2Cx)\r
130 {\r
131         I2Cx->CONSET = I2C_I2CONSET_STA;\r
132         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
133 \r
134         // Wait for complete\r
135         while (!(I2Cx->CONSET & I2C_I2CONSET_SI));\r
136         I2Cx->CONCLR = I2C_I2CONCLR_STAC;\r
137         return (I2Cx->STAT & I2C_STAT_CODE_BITMASK);\r
138 }\r
139 \r
140 \r
141 /********************************************************************//**\r
142  * @brief               Generate a stop condition on I2C bus (in master mode only)\r
143  * @param[in]   I2Cx I2C peripheral selected, should be:\r
144  *                                      - LPC_I2C0      :I2C0 peripheral\r
145  *                                      - LPC_I2C1      :I2C1 peripheral\r
146  * @return              None\r
147  *********************************************************************/\r
148 static void I2C_Stop (LPC_I2Cn_Type *I2Cx)\r
149 {\r
150 \r
151         /* Make sure start bit is not active */\r
152         if (I2Cx->CONSET & I2C_I2CONSET_STA)\r
153         {\r
154                 I2Cx->CONCLR = I2C_I2CONCLR_STAC;\r
155         }\r
156         I2Cx->CONSET = I2C_I2CONSET_STO;\r
157         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
158 }\r
159 \r
160 \r
161 /********************************************************************//**\r
162  * @brief               Send a byte\r
163  * @param[in]   I2Cx I2C peripheral selected, should be:\r
164  *                                      - LPC_I2C0      :I2C0 peripheral\r
165  *                                      - LPC_I2C1      :I2C1 peripheral\r
166  * @param[in]   databyte        sent data\r
167  * @return              value of I2C status register after sending\r
168  *********************************************************************/\r
169 static uint32_t I2C_SendByte (LPC_I2Cn_Type *I2Cx, uint8_t databyte)\r
170 {\r
171         /* Make sure start bit is not active */\r
172         if (I2Cx->CONSET & I2C_I2CONSET_STA)\r
173         {\r
174                 I2Cx->CONCLR = I2C_I2CONCLR_STAC;\r
175         }\r
176         I2Cx->DAT = databyte & I2C_I2DAT_BITMASK;\r
177         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
178 \r
179         while (!(I2Cx->CONSET & I2C_I2CONSET_SI));\r
180         return (I2Cx->STAT & I2C_STAT_CODE_BITMASK);\r
181 }\r
182 \r
183 \r
184 /********************************************************************//**\r
185  * @brief               Get a byte\r
186  * @param[in]   I2Cx I2C peripheral selected, should be:\r
187  *                                      - LPC_I2C0      :I2C0 peripheral\r
188  *                                      - LPC_I2C1      :I2C1 peripheral\r
189  * @param[out]  retdat  pointer to return data\r
190  * @param[in]   ack             assert acknowledge or not, should be: TRUE/FALSE\r
191  * @return              value of I2C status register after sending\r
192  *********************************************************************/\r
193 static uint32_t I2C_GetByte (LPC_I2Cn_Type *I2Cx, uint8_t *retdat, Bool ack)\r
194 {\r
195         if (ack == TRUE)\r
196         {\r
197                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
198         }\r
199         else\r
200         {\r
201                 I2Cx->CONCLR = I2C_I2CONCLR_AAC;\r
202         }\r
203         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
204 \r
205         while (!(I2Cx->CONSET & I2C_I2CONSET_SI));\r
206         *retdat = (uint8_t) (I2Cx->DAT & I2C_I2DAT_BITMASK);\r
207         return (I2Cx->STAT & I2C_STAT_CODE_BITMASK);\r
208 }\r
209 \r
210 /* End of Private Functions --------------------------------------------------- */\r
211 \r
212 \r
213 /* Public Functions ----------------------------------------------------------- */\r
214 /** @addtogroup I2C_Public_Functions\r
215  * @{\r
216  */\r
217 \r
218 /********************************************************************//**\r
219  * @brief               Initializes the I2Cx peripheral with specified parameter.\r
220  * @param[in]   I2Cx    I2C peripheral selected, should be\r
221  *                                      - LPC_I2C0      :I2C0 peripheral\r
222  *                                      - LPC_I2C1      :I2C1 peripheral\r
223  * @param[in]   clockrate Target clock rate value to initialized I2C\r
224  *                              peripheral (Hz)\r
225  * @return              None\r
226  *********************************************************************/\r
227 void I2C_Init(LPC_I2Cn_Type *I2Cx, uint32_t clockrate)\r
228 {\r
229         uint32_t tem;\r
230 \r
231         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
232 \r
233         if (I2Cx==LPC_I2C0)\r
234         {\r
235                 /* Set up clock for I2C0 module */\r
236                 //LPC_CGU->BASE_VPB1_CLK = (SRC_PL160M_0<<24) | (1<<11);\r
237                 CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_APB1);\r
238                 /* Select weather standard, fast, fast plus mode*/\r
239                 if(clockrate>=1000000)// Fast mode plus: 1MHz, high speed 3.4MHz\r
240                         LPC_SCU->SFSI2C0 = SFSI2C0_CONFIGURE_FASTPLUS_HIGHSPEED_MODE;\r
241                 else                              // standard 100KHz, fast 400KHz\r
242                         LPC_SCU->SFSI2C0 = SFSI2C0_CONFIGURE_STANDARD_FAST_MODE;\r
243         }\r
244         else if (I2Cx==LPC_I2C1)\r
245         {\r
246                 /* Set up clock for I2C1 module */\r
247                 //LPC_CGU->BASE_VPB3_CLK = (SRC_PL160M_0<<24) | (1<<11);\r
248                 CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_APB3);\r
249                 /* Configure pin function for I2C1*/\r
250                 LPC_SCU->SFSP2_3 = SFSP2_3_CONFIGURE_I2C1_SDA;                  /* SDA */\r
251                 LPC_SCU->SFSP2_4 = SFSP2_4_CONFIGURE_I2C1_SCL;                  /* SCL */\r
252                 /* Check if I2C1 run fast mode*/\r
253                 if(clockrate != 400000)\r
254                         return;\r
255         }\r
256         else {\r
257                 // Up-Support this device\r
258                 return;\r
259         }\r
260 \r
261     /* Set clock rate */\r
262         if(clockrate<1000)      //make sure SCLH,SCLL not exceed its 16bit value\r
263                 return;\r
264         tem = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE) / clockrate;\r
265         I2Cx->SCLH = (uint32_t)(tem / 2);\r
266         I2Cx->SCLL = (uint32_t)(tem - I2Cx->SCLH);\r
267     /* Set I2C operation to default */\r
268     I2Cx->CONCLR = (I2C_I2CONCLR_AAC |I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_I2ENC);\r
269 }\r
270 \r
271 \r
272 /*********************************************************************//**\r
273  * @brief               De-initializes the I2C peripheral registers to their\r
274  *                  default reset values.\r
275  * @param[in]   I2Cx    I2C peripheral selected, should be\r
276  *                                      - LPC_I2C0      :I2C0 peripheral\r
277  *                                      - LPC_I2C1      :I2C1 peripheral\r
278  * @return              None\r
279  **********************************************************************/\r
280 void I2C_DeInit(LPC_I2Cn_Type* I2Cx)\r
281 {\r
282         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
283 \r
284         /* Disable I2C control */\r
285         I2Cx->CONCLR = I2C_I2CONCLR_I2ENC;\r
286 \r
287 }\r
288 \r
289 \r
290 /*********************************************************************//**\r
291  * @brief               Enable or disable I2C peripheral's operation\r
292  * @param[in]   I2Cx I2C peripheral selected, should be\r
293  *                                      - LPC_I2C0      :I2C0 peripheral\r
294  *                                      - LPC_I2C1      :I2C1 peripheral\r
295  * @param[in]   NewState New State of I2Cx peripheral's operation, should be:\r
296  *                                      - ENABLE        :enable I2C operation\r
297  *                                      - DISABLE       :disable I2C operation\r
298  * @return              none\r
299  **********************************************************************/\r
300 void I2C_Cmd(LPC_I2Cn_Type* I2Cx, FunctionalState NewState)\r
301 {\r
302         CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));\r
303         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
304 \r
305         if (NewState == ENABLE)\r
306         {\r
307                 I2Cx->CONSET = I2C_I2CONSET_I2EN;\r
308         }\r
309         else\r
310         {\r
311                 I2Cx->CONCLR = I2C_I2CONCLR_I2ENC;\r
312         }\r
313 }\r
314 \r
315 \r
316 /*********************************************************************//**\r
317  * @brief               Enable/Disable interrupt for I2C peripheral\r
318  * @param[in]   I2Cx    I2C peripheral selected, should be:\r
319  *                                      - LPC_I2C0      :I2C0 peripheral\r
320  *                                      - LPC_I2C1      :I2C1 peripheral\r
321  * @param[in]   NewState        New State of I2C peripheral interrupt in NVIC core\r
322  *                              should be:\r
323  *                                      - ENABLE: enable interrupt for this I2C peripheral\r
324  *                                      - DISABLE: disable interrupt for this I2C peripheral\r
325  * @return              None\r
326  **********************************************************************/\r
327 void I2C_IntCmd (LPC_I2Cn_Type *I2Cx, Bool NewState)\r
328 {\r
329         if (NewState)\r
330         {\r
331                 if(I2Cx == LPC_I2C0)\r
332                 {\r
333                         NVIC_EnableIRQ(I2C0_IRQn);\r
334                 }\r
335                 else if (I2Cx == LPC_I2C1)\r
336                 {\r
337                         NVIC_EnableIRQ(I2C1_IRQn);\r
338                 }\r
339         }\r
340         else\r
341         {\r
342                 if(I2Cx == LPC_I2C0)\r
343                 {\r
344                         NVIC_DisableIRQ(I2C0_IRQn);\r
345                 }\r
346                 else if (I2Cx == LPC_I2C1)\r
347                 {\r
348                         NVIC_DisableIRQ(I2C1_IRQn);\r
349                 }\r
350         }\r
351     return;\r
352 }\r
353 \r
354 \r
355 /*********************************************************************//**\r
356  * @brief               General Master Interrupt handler for I2C peripheral\r
357  * @param[in]   I2Cx    I2C peripheral selected, should be:\r
358  *                                      - LPC_I2C0      :I2C0 peripheral\r
359  *                                      - LPC_I2C1      :I2C1 peripheral\r
360  * @return              None\r
361  **********************************************************************/\r
362 void I2C_MasterHandler (LPC_I2Cn_Type  *I2Cx)\r
363 {\r
364         int32_t tmp;\r
365         uint8_t returnCode;\r
366         I2C_M_SETUP_Type *txrx_setup;\r
367 \r
368         tmp = I2C_getNum(I2Cx);\r
369         txrx_setup = (I2C_M_SETUP_Type *) i2cdat[tmp].txrx_setup;\r
370 \r
371         returnCode = (I2Cx->STAT & I2C_STAT_CODE_BITMASK);\r
372         // Save current status\r
373         txrx_setup->status = returnCode;\r
374         // there's no relevant information\r
375         if (returnCode == I2C_I2STAT_NO_INF){\r
376                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
377                 return;\r
378         }\r
379 \r
380         /* ----------------------------- TRANSMIT PHASE --------------------------*/\r
381         if (i2cdat[tmp].dir == 0){\r
382                 switch (returnCode)\r
383                 {\r
384                 /* A start/repeat start condition has been transmitted -------------------*/\r
385                 case I2C_I2STAT_M_TX_START:\r
386                 case I2C_I2STAT_M_TX_RESTART:\r
387                         I2Cx->CONCLR = I2C_I2CONCLR_STAC;\r
388                         /*\r
389                          * If there's any transmit data, then start to\r
390                          * send SLA+W right now, otherwise check whether if there's\r
391                          * any receive data for next state.\r
392                          */\r
393                         if ((txrx_setup->tx_data != NULL) && (txrx_setup->tx_length != 0)){\r
394                                 I2Cx->DAT = (txrx_setup->sl_addr7bit << 1);\r
395                                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
396                         } else {\r
397                                 goto next_stage;\r
398                         }\r
399                         break;\r
400 \r
401                 /* SLA+W has been transmitted, ACK has been received ----------------------*/\r
402                 case I2C_I2STAT_M_TX_SLAW_ACK:\r
403                 /* Data has been transmitted, ACK has been received */\r
404                 case I2C_I2STAT_M_TX_DAT_ACK:\r
405                         /* Send more data */\r
406                         if ((txrx_setup->tx_count < txrx_setup->tx_length) \\r
407                                         && (txrx_setup->tx_data != NULL)){\r
408                                 I2Cx->DAT =  *(uint8_t *)(txrx_setup->tx_data + txrx_setup->tx_count);\r
409                                 txrx_setup->tx_count++;\r
410                                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
411                         }\r
412                         // no more data, switch to next stage\r
413                         else {\r
414 next_stage:\r
415                                 // change direction\r
416                                 i2cdat[tmp].dir = 1;\r
417                                 // Check if any data to receive\r
418                                 if ((txrx_setup->rx_length != 0) && (txrx_setup->rx_data != NULL)){\r
419                                                 // check whether if we need to issue an repeat start\r
420                                                 if ((txrx_setup->tx_length != 0) && (txrx_setup->tx_data != NULL)){\r
421                                                         // Send out an repeat start command\r
422                                                         I2Cx->CONSET = I2C_I2CONSET_STA;\r
423                                                         I2Cx->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC;\r
424                                                 }\r
425                                                 // Don't need issue an repeat start, just goto send SLA+R\r
426                                                 else {\r
427                                                         goto send_slar;\r
428                                                 }\r
429                                 }\r
430                                 // no more data send, the go to end stage now\r
431                                 else {\r
432                                         // success, goto end stage\r
433                                         txrx_setup->status |= I2C_SETUP_STATUS_DONE;\r
434                                         goto end_stage;\r
435                                 }\r
436                         }\r
437                         break;\r
438 \r
439                 /* SLA+W has been transmitted, NACK has been received ----------------------*/\r
440                 case I2C_I2STAT_M_TX_SLAW_NACK:\r
441                 /* Data has been transmitted, NACK has been received -----------------------*/\r
442                 case I2C_I2STAT_M_TX_DAT_NACK:\r
443                         // update status\r
444                         txrx_setup->status |= I2C_SETUP_STATUS_NOACKF;\r
445                         goto retry;\r
446                 /* Arbitration lost in SLA+R/W or Data bytes -------------------------------*/\r
447                 case I2C_I2STAT_M_TX_ARB_LOST:\r
448                         // update status\r
449                         txrx_setup->status |= I2C_SETUP_STATUS_ARBF;\r
450                 default:\r
451                         goto retry;\r
452                 }\r
453         }\r
454 \r
455         /* ----------------------------- RECEIVE PHASE --------------------------*/\r
456         else if (i2cdat[tmp].dir == 1){\r
457                 switch (returnCode){\r
458                         /* A start/repeat start condition has been transmitted ---------------------*/\r
459                 case I2C_I2STAT_M_RX_START:\r
460                 case I2C_I2STAT_M_RX_RESTART:\r
461                         I2Cx->CONCLR = I2C_I2CONCLR_STAC;\r
462                         /*\r
463                          * If there's any receive data, then start to\r
464                          * send SLA+R right now, otherwise check whether if there's\r
465                          * any receive data for end of state.\r
466                          */\r
467                         if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_length != 0)){\r
468 send_slar:\r
469                                 I2Cx->DAT = (txrx_setup->sl_addr7bit << 1) | 0x01;\r
470                                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
471                         } else {\r
472                                 // Success, goto end stage\r
473                                 txrx_setup->status |= I2C_SETUP_STATUS_DONE;\r
474                                 goto end_stage;\r
475                         }\r
476                         break;\r
477 \r
478                 /* SLA+R has been transmitted, ACK has been received -----------------*/\r
479                 case I2C_I2STAT_M_RX_SLAR_ACK:\r
480                         if (txrx_setup->rx_count < (txrx_setup->rx_length - 1)) {\r
481                                 /*Data will be received,  ACK will be return*/\r
482                                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
483                         }\r
484                         else {\r
485                                 /*Last data will be received,  NACK will be return*/\r
486                                 I2Cx->CONCLR = I2C_I2CONSET_AA;\r
487                         }\r
488                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
489                         break;\r
490 \r
491                 /* Data has been received, ACK has been returned ----------------------*/\r
492                 case I2C_I2STAT_M_RX_DAT_ACK:\r
493                         // Note save data and increase counter first, then check later\r
494                         /* Save data  */\r
495                         if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_count < txrx_setup->rx_length)){\r
496                                 *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (I2Cx->DAT & I2C_I2DAT_BITMASK);\r
497                                 txrx_setup->rx_count++;\r
498                         }\r
499                         if (txrx_setup->rx_count < (txrx_setup->rx_length - 1)) {\r
500                                 /*Data will be received,  ACK will be return*/\r
501                                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
502                         }\r
503                         else {\r
504                                 /*Last data will be received,  NACK will be return*/\r
505                                 I2Cx->CONCLR = I2C_I2CONSET_AA;\r
506                         }\r
507 \r
508                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
509                         break;\r
510 \r
511                 /* Data has been received, NACK has been return -------------------------*/\r
512                 case I2C_I2STAT_M_RX_DAT_NACK:\r
513                         /* Save the last data */\r
514                         if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_count < txrx_setup->rx_length)){\r
515                                 *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (I2Cx->DAT & I2C_I2DAT_BITMASK);\r
516                                 txrx_setup->rx_count++;\r
517                         }\r
518                         // success, go to end stage\r
519                         txrx_setup->status |= I2C_SETUP_STATUS_DONE;\r
520                         goto end_stage;\r
521 \r
522                 /* SLA+R has been transmitted, NACK has been received ------------------*/\r
523                 case I2C_I2STAT_M_RX_SLAR_NACK:\r
524                         // update status\r
525                         txrx_setup->status |= I2C_SETUP_STATUS_NOACKF;\r
526                         goto retry;\r
527 \r
528                 /* Arbitration lost ----------------------------------------------------*/\r
529                 case I2C_I2STAT_M_RX_ARB_LOST:\r
530                         // update status\r
531                         txrx_setup->status |= I2C_SETUP_STATUS_ARBF;\r
532                 default:\r
533 retry:\r
534                         // check if retransmission is available\r
535                         if (txrx_setup->retransmissions_count < txrx_setup->retransmissions_max){\r
536                                 // Clear tx count\r
537                                 txrx_setup->tx_count = 0;\r
538                                 I2Cx->CONSET = I2C_I2CONSET_STA;\r
539                                 I2Cx->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC;\r
540                                 txrx_setup->retransmissions_count++;\r
541                         }\r
542                         // End of stage\r
543                         else {\r
544 end_stage:\r
545                                 // Disable interrupt\r
546                                 I2C_IntCmd(I2Cx, FALSE);\r
547                                 // Send stop\r
548                                 I2C_Stop(I2Cx);\r
549 \r
550                                 I2C_MasterComplete[tmp] = TRUE;\r
551                         }\r
552                         break;\r
553                 }\r
554         }\r
555 }\r
556 \r
557 \r
558 /*********************************************************************//**\r
559  * @brief               General Slave Interrupt handler for I2C peripheral\r
560  * @param[in]   I2Cx    I2C peripheral selected, should be:\r
561  *                                      - LPC_I2C0      :I2C0 peripheral\r
562  *                                      - LPC_I2C1      :I2C1 peripheral\r
563  * @return              None\r
564  **********************************************************************/\r
565 void I2C_SlaveHandler (LPC_I2Cn_Type  *I2Cx)\r
566 {\r
567         int32_t tmp;\r
568         uint8_t returnCode;\r
569         I2C_S_SETUP_Type *txrx_setup;\r
570         uint32_t timeout;\r
571 \r
572         tmp = I2C_getNum(I2Cx);\r
573         txrx_setup = (I2C_S_SETUP_Type *) i2cdat[tmp].txrx_setup;\r
574 \r
575         returnCode = (I2Cx->STAT & I2C_STAT_CODE_BITMASK);\r
576         // Save current status\r
577         txrx_setup->status = returnCode;\r
578         // there's no relevant information\r
579         if (returnCode == I2C_I2STAT_NO_INF){\r
580                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
581                 return;\r
582         }\r
583 \r
584 \r
585         switch (returnCode)\r
586         {\r
587 \r
588         /* No status information */\r
589         case I2C_I2STAT_NO_INF:\r
590                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
591                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
592                 break;\r
593 \r
594         /* Reading phase -------------------------------------------------------- */\r
595         /* Own SLA+R has been received, ACK has been returned */\r
596         case I2C_I2STAT_S_RX_SLAW_ACK:\r
597         /* General call address has been received, ACK has been returned */\r
598         case I2C_I2STAT_S_RX_GENCALL_ACK:\r
599                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
600                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
601                 break;\r
602 \r
603         /* Previously addressed with own SLA;\r
604          * DATA byte has been received;\r
605          * ACK has been returned */\r
606         case I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK:\r
607         /* DATA has been received, ACK hasn been return */\r
608         case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK:\r
609                 /*\r
610                  * All data bytes that over-flow the specified receive\r
611                  * data length, just ignore them.\r
612                  */\r
613                 if ((txrx_setup->rx_count < txrx_setup->rx_length) \\r
614                                 && (txrx_setup->rx_data != NULL)){\r
615                         *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (uint8_t)I2Cx->DAT;\r
616                         txrx_setup->rx_count++;\r
617                 }\r
618                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
619                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
620                 break;\r
621 \r
622         /* Previously addressed with own SLA;\r
623          * DATA byte has been received;\r
624          * NOT ACK has been returned */\r
625         case I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK:\r
626         /* DATA has been received, NOT ACK has been returned */\r
627         case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK:\r
628                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
629                 break;\r
630 \r
631         /*\r
632          * Note that: Return code only let us know a stop condition mixed\r
633          * with a repeat start condition in the same code value.\r
634          * So we should provide a time-out. In case this is really a stop\r
635          * condition, this will return back after time out condition. Otherwise,\r
636          * next session that is slave receive data will be completed.\r
637          */\r
638 \r
639         /* A Stop or a repeat start condition */\r
640         case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX:\r
641                 // Temporally lock the interrupt for timeout condition\r
642                 I2C_IntCmd(I2Cx, FALSE);\r
643                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
644                 // enable time out\r
645                 timeout = I2C_SLAVE_TIME_OUT;\r
646                 while(1){\r
647                         if (I2Cx->CONSET & I2C_I2CONSET_SI){\r
648                                 // re-Enable interrupt\r
649                                 I2C_IntCmd(I2Cx, TRUE);\r
650                                 break;\r
651                         } else {\r
652                                 timeout--;\r
653                                 if (timeout == 0){\r
654                                         // timeout occur, it's really a stop condition\r
655                                         txrx_setup->status |= I2C_SETUP_STATUS_DONE;\r
656                                         goto s_int_end;\r
657                                 }\r
658                         }\r
659                 }\r
660                 break;\r
661 \r
662         /* Writing phase -------------------------------------------------------- */\r
663         /* Own SLA+R has been received, ACK has been returned */\r
664         case I2C_I2STAT_S_TX_SLAR_ACK:\r
665         /* Data has been transmitted, ACK has been received */\r
666         case I2C_I2STAT_S_TX_DAT_ACK:\r
667                 /*\r
668                  * All data bytes that over-flow the specified receive\r
669                  * data length, just ignore them.\r
670                  */\r
671                 if ((txrx_setup->tx_count < txrx_setup->tx_length) \\r
672                                 && (txrx_setup->tx_data != NULL)){\r
673                         I2Cx->DAT = *(uint8_t *) (txrx_setup->tx_data + txrx_setup->tx_count);\r
674                         txrx_setup->tx_count++;\r
675                 }\r
676                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
677                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
678                 break;\r
679 \r
680         /* Data has been transmitted, NACK has been received,\r
681          * that means there's no more data to send, exit now */\r
682         /*\r
683          * Note: Don't wait for stop event since in slave transmit mode,\r
684          * since there no proof lets us know when a stop signal has been received\r
685          * on slave side.\r
686          */\r
687         case I2C_I2STAT_S_TX_DAT_NACK:\r
688                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
689                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
690                 txrx_setup->status |= I2C_SETUP_STATUS_DONE;\r
691                 goto s_int_end;\r
692 \r
693         // Other status must be captured\r
694         default:\r
695 s_int_end:\r
696                 // Disable interrupt\r
697                 I2C_IntCmd(I2Cx, FALSE);\r
698                 I2Cx->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;\r
699                 I2C_SlaveComplete[tmp] = TRUE;\r
700                 break;\r
701         }\r
702 }\r
703 \r
704 \r
705 /*********************************************************************//**\r
706  * @brief               Transmit and Receive data in master mode\r
707  * @param[in]   I2Cx I2C peripheral selected, should be:\r
708  *                                      - LPC_I2C0      :I2C0 peripheral\r
709  *                                      - LPC_I2C1      :I2C1 peripheral\r
710  * @param[in]   TransferCfg     Pointer to a I2C_M_SETUP_Type structure that\r
711  *                              contains specified information about the configuration\r
712  *                              for master transfer.\r
713  * @param[in]   Opt     a I2C_TRANSFER_OPT_Type type that selected for interrupt\r
714  *                              or polling mode.\r
715  * @return              Transmit/receive status, should be:\r
716  *                                      - SUCCESS\r
717  *                                      - ERROR\r
718  *\r
719  * Note:\r
720  * - In case of using I2C to transmit data only, either transmit length set to 0\r
721  * or transmit data pointer set to NULL.\r
722  * - In case of using I2C to receive data only, either receive length set to 0\r
723  * or receive data pointer set to NULL.\r
724  * - In case of using I2C to transmit followed by receive data, transmit length,\r
725  * transmit data pointer, receive length and receive data pointer should be set\r
726  * corresponding.\r
727  **********************************************************************/\r
728 Status I2C_MasterTransferData(LPC_I2Cn_Type *I2Cx, I2C_M_SETUP_Type *TransferCfg, \\r
729                                                                 I2C_TRANSFER_OPT_Type Opt)\r
730 {\r
731         uint8_t *txdat;\r
732         uint8_t *rxdat;\r
733         uint32_t CodeStatus;\r
734         uint8_t tmp;\r
735 \r
736         // reset all default state\r
737         txdat = (uint8_t *) TransferCfg->tx_data;\r
738         rxdat = (uint8_t *) TransferCfg->rx_data;\r
739         // Reset I2C setup value to default state\r
740         TransferCfg->tx_count = 0;\r
741         TransferCfg->rx_count = 0;\r
742         TransferCfg->status = 0;\r
743 \r
744         if (Opt == I2C_TRANSFER_POLLING){\r
745 \r
746                 /* First Start condition -------------------------------------------------------------- */\r
747                 TransferCfg->retransmissions_count = 0;\r
748 retry:\r
749                 // reset all default state\r
750                 txdat = (uint8_t *) TransferCfg->tx_data;\r
751                 rxdat = (uint8_t *) TransferCfg->rx_data;\r
752                 // Reset I2C setup value to default state\r
753                 TransferCfg->tx_count = 0;\r
754                 TransferCfg->rx_count = 0;\r
755                 CodeStatus = 0;\r
756 \r
757                 // Start command\r
758                 CodeStatus = I2C_Start(I2Cx);\r
759                 if ((CodeStatus != I2C_I2STAT_M_TX_START) \\r
760                                 && (CodeStatus != I2C_I2STAT_M_TX_RESTART)){\r
761                         TransferCfg->retransmissions_count++;\r
762                         if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
763                                 // save status\r
764                                 TransferCfg->status = CodeStatus;\r
765                                 goto error;\r
766                         } else {\r
767                                 goto retry;\r
768                         }\r
769                 }\r
770 \r
771                 /* In case of sending data first --------------------------------------------------- */\r
772                 if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL)){\r
773 \r
774                         /* Send slave address + WR direction bit = 0 ----------------------------------- */\r
775                         CodeStatus = I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit << 1));\r
776                         if (CodeStatus != I2C_I2STAT_M_TX_SLAW_ACK){\r
777                                 TransferCfg->retransmissions_count++;\r
778                                 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
779                                         // save status\r
780                                         TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF;\r
781                                         goto error;\r
782                                 } else {\r
783                                         goto retry;\r
784                                 }\r
785                         }\r
786 \r
787                         /* Send a number of data bytes ---------------------------------------- */\r
788                         while (TransferCfg->tx_count < TransferCfg->tx_length)\r
789                         {\r
790                                 CodeStatus = I2C_SendByte(I2Cx, *txdat);\r
791                                 if (CodeStatus != I2C_I2STAT_M_TX_DAT_ACK){\r
792                                         TransferCfg->retransmissions_count++;\r
793                                         if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
794                                                 // save status\r
795                                                 TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF;\r
796                                                 goto error;\r
797                                         } else {\r
798                                                 goto retry;\r
799                                         }\r
800                                 }\r
801 \r
802                                 txdat++;\r
803                                 TransferCfg->tx_count++;\r
804                         }\r
805                 }\r
806 \r
807                 /* Second Start condition (Repeat Start) ------------------------------------------- */\r
808                 if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL) \\r
809                                 && (TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){\r
810 \r
811                         CodeStatus = I2C_Start(I2Cx);\r
812                         if ((CodeStatus != I2C_I2STAT_M_RX_START) \\r
813                                         && (CodeStatus != I2C_I2STAT_M_RX_RESTART)){\r
814                                 TransferCfg->retransmissions_count++;\r
815                                 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
816                                         // Update status\r
817                                         TransferCfg->status = CodeStatus;\r
818                                         goto error;\r
819                                 } else {\r
820                                         goto retry;\r
821                                 }\r
822                         }\r
823                 }\r
824 \r
825                 /* Then, start reading after sending data -------------------------------------- */\r
826                 if ((TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){\r
827                         /* Send slave address + RD direction bit = 1 ----------------------------------- */\r
828 \r
829                         CodeStatus = I2C_SendByte(I2Cx, ((TransferCfg->sl_addr7bit << 1) | 0x01));\r
830                         if (CodeStatus != I2C_I2STAT_M_RX_SLAR_ACK){\r
831                                 TransferCfg->retransmissions_count++;\r
832                                 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
833                                         // update status\r
834                                         TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF;\r
835                                         goto error;\r
836                                 } else {\r
837                                         goto retry;\r
838                                 }\r
839                         }\r
840 \r
841                         /* Receive a number of data bytes ------------------------------------------------- */\r
842                         while (TransferCfg->rx_count < TransferCfg->rx_length){\r
843 \r
844                                 /*\r
845                                  * Note that: if data length is only one, the master should not\r
846                                  * issue an ACK signal on bus after reading to avoid of next data frame\r
847                                  * on slave side\r
848                                  */\r
849                                 if (TransferCfg->rx_count < (TransferCfg->rx_length - 1)){\r
850                                         // Issue an ACK signal for next data frame\r
851                                         CodeStatus = I2C_GetByte(I2Cx, &tmp, TRUE);\r
852                                         if (CodeStatus != I2C_I2STAT_M_RX_DAT_ACK){\r
853                                                 TransferCfg->retransmissions_count++;\r
854                                                 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
855                                                         // update status\r
856                                                         TransferCfg->status = CodeStatus;\r
857                                                         goto error;\r
858                                                 } else {\r
859                                                         goto retry;\r
860                                                 }\r
861                                         }\r
862                                 } else {\r
863                                         // Do not issue an ACK signal\r
864                                         CodeStatus = I2C_GetByte(I2Cx, &tmp, FALSE);\r
865                                         if (CodeStatus != I2C_I2STAT_M_RX_DAT_NACK){\r
866                                                 TransferCfg->retransmissions_count++;\r
867                                                 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){\r
868                                                         // update status\r
869                                                         TransferCfg->status = CodeStatus;\r
870                                                         goto error;\r
871                                                 } else {\r
872                                                         goto retry;\r
873                                                 }\r
874                                         }\r
875                                 }\r
876                                 *rxdat++ = tmp;\r
877                                 TransferCfg->rx_count++;\r
878                         }\r
879                 }\r
880 \r
881                 /* Send STOP condition ------------------------------------------------- */\r
882                 I2C_Stop(I2Cx);\r
883                 return SUCCESS;\r
884 \r
885 error:\r
886                 // Send stop condition\r
887                 I2C_Stop(I2Cx);\r
888                 return ERROR;\r
889         }\r
890 \r
891         else if (Opt == I2C_TRANSFER_INTERRUPT){\r
892                 // Setup tx_rx data, callback and interrupt handler\r
893                 tmp = I2C_getNum(I2Cx);\r
894                 i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg;\r
895                 // Set direction phase, write first\r
896                 i2cdat[tmp].dir = 0;\r
897 \r
898                 /* First Start condition -------------------------------------------------------------- */\r
899                 I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
900                 I2Cx->CONSET = I2C_I2CONSET_STA;\r
901                 I2C_IntCmd(I2Cx, TRUE);\r
902 \r
903                 return (SUCCESS);\r
904         }\r
905 \r
906         return ERROR;\r
907 }\r
908 \r
909 \r
910 /*********************************************************************//**\r
911  * @brief               Receive and Transmit data in slave mode\r
912  * @param[in]   I2Cx    I2C peripheral selected, should be\r
913  *                                      - LPC_I2C0      :I2C0 peripheral\r
914  *                                      - LPC_I2C1      :I2C1 peripheral\r
915  * @param[in]   TransferCfg             Pointer to a I2C_S_SETUP_Type structure that\r
916  *                              contains specified information about the configuration for\r
917  *                              master transfer.\r
918  * @param[in]   Opt     I2C_TRANSFER_OPT_Type type that selected for interrupt\r
919  *                              or polling mode.\r
920  * @return              Transmit/receive status, could be:\r
921  *                                      - SUCCESS\r
922  *                                      - ERRRO\r
923  *\r
924  * Note:\r
925  * The mode of slave's operation depends on the command sent from master on\r
926  * the I2C bus. If the master send a SLA+W command, this sub-routine will\r
927  * use receive data length and receive data pointer. If the master send a SLA+R\r
928  * command, this sub-routine will use transmit data length and transmit data\r
929  * pointer.\r
930  * If the master issue an repeat start command or a stop command, the slave will\r
931  * enable an time out condition, during time out condition, if there's no activity\r
932  * on I2C bus, the slave will exit, otherwise (i.e. the master send a SLA+R/W),\r
933  * the slave then switch to relevant operation mode. The time out should be used\r
934  * because the return status code can not show difference from stop and repeat\r
935  * start command in slave operation.\r
936  * In case of the expected data length from master is greater than data length\r
937  * that slave can support:\r
938  * - In case of reading operation (from master): slave will return I2C_I2DAT_IDLE_CHAR\r
939  * value.\r
940  * - In case of writing operation (from master): slave will ignore remain data from master.\r
941  **********************************************************************/\r
942 Status I2C_SlaveTransferData(LPC_I2Cn_Type *I2Cx, I2C_S_SETUP_Type *TransferCfg, \\r
943                                                                 I2C_TRANSFER_OPT_Type Opt)\r
944 {\r
945         uint8_t *txdat;\r
946         uint8_t *rxdat;\r
947         uint32_t CodeStatus;\r
948         uint32_t timeout;\r
949         int32_t time_en;\r
950         int32_t tmp;\r
951 \r
952         // reset all default state\r
953         txdat = (uint8_t *) TransferCfg->tx_data;\r
954         rxdat = (uint8_t *) TransferCfg->rx_data;\r
955         // Reset I2C setup value to default state\r
956         TransferCfg->tx_count = 0;\r
957         TransferCfg->rx_count = 0;\r
958         TransferCfg->status = 0;\r
959 \r
960 \r
961         // Polling option\r
962         if (Opt == I2C_TRANSFER_POLLING){\r
963 \r
964                 /* Set AA bit to ACK command on I2C bus */\r
965                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
966                 /* Clear SI bit to be ready ... */\r
967                 I2Cx->CONCLR = (I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC);\r
968 \r
969                 time_en = 0;\r
970                 timeout = 0;\r
971 \r
972                 while (1)\r
973                 {\r
974                         /* Check SI flag ready */\r
975                         if (I2Cx->CONSET & I2C_I2CONSET_SI)\r
976                         {\r
977                                 time_en = 0;\r
978 \r
979                                 switch (CodeStatus = (I2Cx->STAT & I2C_STAT_CODE_BITMASK))\r
980                                 {\r
981 \r
982                                 /* No status information */\r
983                                 case I2C_I2STAT_NO_INF:\r
984                                         I2Cx->CONSET = I2C_I2CONSET_AA;\r
985                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
986                                         break;\r
987 \r
988                                 /* Reading phase -------------------------------------------------------- */\r
989                                 /* Own SLA+R has been received, ACK has been returned */\r
990                                 case I2C_I2STAT_S_RX_SLAW_ACK:\r
991                                 /* General call address has been received, ACK has been returned */\r
992                                 case I2C_I2STAT_S_RX_GENCALL_ACK:\r
993                                         I2Cx->CONSET = I2C_I2CONSET_AA;\r
994                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
995                                         break;\r
996 \r
997                                 /* Previously addressed with own SLA;\r
998                                  * DATA byte has been received;\r
999                                  * ACK has been returned */\r
1000                                 case I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK:\r
1001                                 /* DATA has been received, ACK hasn been return */\r
1002                                 case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK:\r
1003                                         /*\r
1004                                          * All data bytes that over-flow the specified receive\r
1005                                          * data length, just ignore them.\r
1006                                          */\r
1007                                         if ((TransferCfg->rx_count < TransferCfg->rx_length) \\r
1008                                                         && (TransferCfg->rx_data != NULL)){\r
1009                                                 *rxdat++ = (uint8_t)I2Cx->DAT;\r
1010                                                 TransferCfg->rx_count++;\r
1011                                         }\r
1012                                         I2Cx->CONSET = I2C_I2CONSET_AA;\r
1013                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1014                                         break;\r
1015 \r
1016                                 /* Previously addressed with own SLA;\r
1017                                  * DATA byte has been received;\r
1018                                  * NOT ACK has been returned */\r
1019                                 case I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK:\r
1020                                 /* DATA has been received, NOT ACK has been returned */\r
1021                                 case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK:\r
1022                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1023                                         break;\r
1024 \r
1025                                 /*\r
1026                                  * Note that: Return code only let us know a stop condition mixed\r
1027                                  * with a repeat start condition in the same code value.\r
1028                                  * So we should provide a time-out. In case this is really a stop\r
1029                                  * condition, this will return back after time out condition. Otherwise,\r
1030                                  * next session that is slave receive data will be completed.\r
1031                                  */\r
1032 \r
1033                                 /* A Stop or a repeat start condition */\r
1034                                 case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX:\r
1035                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1036                                         // enable time out\r
1037                                         time_en = 1;\r
1038                                         timeout = 0;\r
1039                                         break;\r
1040 \r
1041                                 /* Writing phase -------------------------------------------------------- */\r
1042                                 /* Own SLA+R has been received, ACK has been returned */\r
1043                                 case I2C_I2STAT_S_TX_SLAR_ACK:\r
1044                                 /* Data has been transmitted, ACK has been received */\r
1045                                 case I2C_I2STAT_S_TX_DAT_ACK:\r
1046                                         /*\r
1047                                          * All data bytes that over-flow the specified receive\r
1048                                          * data length, just ignore them.\r
1049                                          */\r
1050                                         if ((TransferCfg->tx_count < TransferCfg->tx_length) \\r
1051                                                         && (TransferCfg->tx_data != NULL)){\r
1052                                                 I2Cx->DAT = *txdat++;\r
1053                                                 TransferCfg->tx_count++;\r
1054                                         }\r
1055                                         I2Cx->CONSET = I2C_I2CONSET_AA;\r
1056                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1057                                         break;\r
1058 \r
1059                                 /* Data has been transmitted, NACK has been received,\r
1060                                  * that means there's no more data to send, exit now */\r
1061                                 /*\r
1062                                  * Note: Don't wait for stop event since in slave transmit mode,\r
1063                                  * since there no proof lets us know when a stop signal has been received\r
1064                                  * on slave side.\r
1065                                  */\r
1066                                 case I2C_I2STAT_S_TX_DAT_NACK:\r
1067                                         I2Cx->CONSET = I2C_I2CONSET_AA;\r
1068                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1069                                         // enable time out\r
1070                                         time_en = 1;\r
1071                                         timeout = 0;\r
1072                                         break;\r
1073 \r
1074                                 // Other status must be captured\r
1075                                 default:\r
1076                                         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1077                                         goto s_error;\r
1078                                 }\r
1079                         } else if (time_en){\r
1080                                 if (timeout++ > I2C_SLAVE_TIME_OUT){\r
1081                                         // it's really a stop condition, goto end stage\r
1082                                         goto s_end_stage;\r
1083                                 }\r
1084                         }\r
1085                 }\r
1086 \r
1087 s_end_stage:\r
1088                 /* Clear AA bit to disable ACK on I2C bus */\r
1089                 I2Cx->CONCLR = I2C_I2CONCLR_AAC;\r
1090                 // Check if there's no error during operation\r
1091                 // Update status\r
1092                 TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_DONE;\r
1093                 return SUCCESS;\r
1094 \r
1095 s_error:\r
1096                 /* Clear AA bit to disable ACK on I2C bus */\r
1097                 I2Cx->CONCLR = I2C_I2CONCLR_AAC;\r
1098                 // Update status\r
1099                 TransferCfg->status = CodeStatus;\r
1100                 return ERROR;\r
1101         }\r
1102 \r
1103         else if (Opt == I2C_TRANSFER_INTERRUPT){\r
1104                 // Setup tx_rx data, callback and interrupt handler\r
1105                 tmp = I2C_getNum(I2Cx);\r
1106                 i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg;\r
1107                 // Set direction phase, read first\r
1108                 i2cdat[tmp].dir = 1;\r
1109 \r
1110                 // Enable AA\r
1111                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
1112                 I2Cx->CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;\r
1113                 I2C_IntCmd(I2Cx, TRUE);\r
1114 \r
1115                 return (SUCCESS);\r
1116         }\r
1117 \r
1118         return ERROR;\r
1119 }\r
1120 \r
1121 /*********************************************************************//**\r
1122  * @brief               Set Own slave address in I2C peripheral corresponding to\r
1123  *                              parameter specified in OwnSlaveAddrConfigStruct.\r
1124  * @param[in]   I2Cx    I2C peripheral selected, should be\r
1125  *                                      - LPC_I2C0      :I2C0 peripheral\r
1126  *                                      - LPC_I2C1      :I2C1 peripheral\r
1127  * @param[in]   OwnSlaveAddrConfigStruct        Pointer to a I2C_OWNSLAVEADDR_CFG_Type\r
1128  *                              structure that contains the configuration information for the\r
1129  *              specified I2C slave address.\r
1130  * @return              None\r
1131  **********************************************************************/\r
1132 void I2C_SetOwnSlaveAddr(LPC_I2Cn_Type *I2Cx, I2C_OWNSLAVEADDR_CFG_Type *OwnSlaveAddrConfigStruct)\r
1133 {\r
1134         uint32_t tmp;\r
1135         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
1136         CHECK_PARAM(PARAM_I2C_SLAVEADDR_CH(OwnSlaveAddrConfigStruct->SlaveAddrChannel));\r
1137         CHECK_PARAM(PARAM_FUNCTIONALSTATE(OwnSlaveAddrConfigStruct->GeneralCallState));\r
1138 \r
1139         tmp = (((uint32_t)(OwnSlaveAddrConfigStruct->SlaveAddr_7bit << 1)) \\r
1140                         | ((OwnSlaveAddrConfigStruct->GeneralCallState == ENABLE) ? 0x01 : 0x00))& I2C_I2ADR_BITMASK;\r
1141         switch (OwnSlaveAddrConfigStruct->SlaveAddrChannel)\r
1142         {\r
1143         case 0:\r
1144                 I2Cx->ADR0 = tmp;\r
1145                 I2Cx->MASK[0] = I2C_I2MASK_MASK((uint32_t) \\r
1146                                 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));\r
1147                 break;\r
1148         case 1:\r
1149                 I2Cx->ADR1 = tmp;\r
1150                 I2Cx->MASK[1] = I2C_I2MASK_MASK((uint32_t) \\r
1151                                 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));\r
1152                 break;\r
1153         case 2:\r
1154                 I2Cx->ADR2 = tmp;\r
1155                 I2Cx->MASK[2] = I2C_I2MASK_MASK((uint32_t) \\r
1156                                 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));\r
1157                 break;\r
1158         case 3:\r
1159                 I2Cx->ADR3 = tmp;\r
1160                 I2Cx->MASK[3] = I2C_I2MASK_MASK((uint32_t) \\r
1161                                 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));\r
1162                 break;\r
1163         }\r
1164 }\r
1165 \r
1166 \r
1167 /*********************************************************************//**\r
1168  * @brief               Configures functionality in I2C monitor mode\r
1169  * @param[in]   I2Cx    I2C peripheral selected, should be\r
1170  *                                      - LPC_I2C0      :I2C0 peripheral\r
1171  *                                      - LPC_I2C1      :I2C1 peripheral\r
1172  * @param[in]   MonitorCfgType Monitor Configuration type, should be:\r
1173  *                                      - I2C_MONITOR_CFG_SCL_OUTPUT    :I2C module can 'stretch'\r
1174  *                              the clock line (hold it low) until it has had time to respond\r
1175  *                              to an I2C interrupt.\r
1176  *                                      - I2C_MONITOR_CFG_MATCHALL              :When this bit is set to '1'\r
1177  *                              and the I2C is in monitor mode, an interrupt will be generated\r
1178  *                              on ANY address received.\r
1179  * @param[in]   NewState New State of this function, should be:\r
1180  *                                      - ENABLE        :Enable this function.\r
1181  *                                      - DISABLE       :Disable this function.\r
1182  * @return              None\r
1183  **********************************************************************/\r
1184 void I2C_MonitorModeConfig(LPC_I2Cn_Type *I2Cx, uint32_t MonitorCfgType, FunctionalState NewState)\r
1185 {\r
1186         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
1187         CHECK_PARAM(PARAM_I2C_MONITOR_CFG(MonitorCfgType));\r
1188         CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));\r
1189 \r
1190         if (NewState == ENABLE)\r
1191         {\r
1192                 I2Cx->MMCTRL |= MonitorCfgType;\r
1193         }\r
1194         else\r
1195         {\r
1196                 I2Cx->MMCTRL &= (~MonitorCfgType) & I2C_I2MMCTRL_BITMASK;\r
1197         }\r
1198 }\r
1199 \r
1200 \r
1201 /*********************************************************************//**\r
1202  * @brief               Enable/Disable I2C monitor mode\r
1203  * @param[in]   I2Cx    I2C peripheral selected, should be\r
1204  *                                      - LPC_I2C0      :I2C0 peripheral\r
1205  *                                      - LPC_I2C1      :I2C1 peripheral\r
1206  * @param[in]   NewState New State of this function, should be:\r
1207  *                                      - ENABLE        :Enable monitor mode.\r
1208  *                                      - DISABLE       :Disable monitor mode.\r
1209  * @return              None\r
1210  **********************************************************************/\r
1211 void I2C_MonitorModeCmd(LPC_I2Cn_Type *I2Cx, FunctionalState NewState)\r
1212 {\r
1213         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
1214         CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));\r
1215 \r
1216         if (NewState == ENABLE)\r
1217         {\r
1218                 I2Cx->MMCTRL |= I2C_I2MMCTRL_MM_ENA;\r
1219                 I2Cx->CONSET = I2C_I2CONSET_AA;\r
1220                 I2Cx->CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;\r
1221         }\r
1222         else\r
1223         {\r
1224                 I2Cx->MMCTRL &= (~I2C_I2MMCTRL_MM_ENA) & I2C_I2MMCTRL_BITMASK;\r
1225                 I2Cx->CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_AAC;\r
1226         }\r
1227         I2C_MonitorBufferIndex = 0;\r
1228 }\r
1229 \r
1230 \r
1231 /*********************************************************************//**\r
1232  * @brief               Get data from I2C data buffer in monitor mode.\r
1233  * @param[in]   I2Cx    I2C peripheral selected, should be\r
1234  *                                      - LPC_I2C0      :I2C0 peripheral\r
1235  *                                      - LPC_I2C1      :I2C1 peripheral\r
1236  * @return              None\r
1237  * Note:        In monitor mode, the I2C module may lose the ability to stretch\r
1238  * the clock (stall the bus) if the ENA_SCL bit is not set. This means that\r
1239  * the processor will have a limited amount of time to read the contents of\r
1240  * the data received on the bus. If the processor reads the I2DAT shift\r
1241  * register, as it ordinarily would, it could have only one bit-time to\r
1242  * respond to the interrupt before the received data is overwritten by\r
1243  * new data.\r
1244  **********************************************************************/\r
1245 uint8_t I2C_MonitorGetDatabuffer(LPC_I2Cn_Type *I2Cx)\r
1246 {\r
1247         CHECK_PARAM(PARAM_I2Cx(I2Cx));\r
1248         return ((uint8_t)(I2Cx->DATA_BUFFER));\r
1249 }\r
1250 \r
1251 \r
1252 /*********************************************************************//**\r
1253  * @brief               Get data from I2C data buffer in monitor mode.\r
1254  * @param[in]   I2Cx    I2C peripheral selected, should be\r
1255  *                                      - LPC_I2C0      :I2C0 peripheral\r
1256  *                                      - LPC_I2C1      :I2C1 peripheral\r
1257  * @return              None\r
1258  * Note:        In monitor mode, the I2C module may lose the ability to stretch\r
1259  * the clock (stall the bus) if the ENA_SCL bit is not set. This means that\r
1260  * the processor will have a limited amount of time to read the contents of\r
1261  * the data received on the bus. If the processor reads the I2DAT shift\r
1262  * register, as it ordinarily would, it could have only one bit-time to\r
1263  * respond to the interrupt before the received data is overwritten by\r
1264  * new data.\r
1265  **********************************************************************/\r
1266 BOOL_8 I2C_MonitorHandler(LPC_I2Cn_Type *I2Cx, uint8_t *buffer, uint32_t size)\r
1267 {\r
1268         BOOL_8 ret=FALSE;\r
1269 \r
1270         I2Cx->CONCLR = I2C_I2CONCLR_SIC;\r
1271 \r
1272         buffer[I2C_MonitorBufferIndex] = (uint8_t)(I2Cx->DATA_BUFFER);\r
1273         I2C_MonitorBufferIndex++;\r
1274         if(I2C_MonitorBufferIndex >= size)\r
1275         {\r
1276                 ret = TRUE;\r
1277         }\r
1278         return ret;\r
1279 }\r
1280 \r
1281 \r
1282 /*********************************************************************//**\r
1283  * @brief               Get status of Master Transfer\r
1284  * @param[in]   I2Cx    I2C peripheral selected, should be:\r
1285  *                                      - LPC_I2C0      :I2C0 peripheral\r
1286  *                                      - LPC_I2C1      :I2C1 peripheral\r
1287  * @return              Master transfer status, could be:\r
1288  *                                      - TRUE          :master transfer completed\r
1289  *                                      - FALSE         :master transfer have not completed yet\r
1290  **********************************************************************/\r
1291 uint32_t I2C_MasterTransferComplete(LPC_I2Cn_Type *I2Cx)\r
1292 {\r
1293         uint32_t retval, tmp;\r
1294         tmp = I2C_getNum(I2Cx);\r
1295         retval = I2C_MasterComplete[tmp];\r
1296         I2C_MasterComplete[tmp] = FALSE;\r
1297         return retval;\r
1298 }\r
1299 \r
1300 \r
1301 /*********************************************************************//**\r
1302  * @brief               Get status of Slave Transfer\r
1303  * @param[in]   I2Cx    I2C peripheral selected, should be:\r
1304  *                                      - LPC_I2C0      :I2C0 peripheral\r
1305  *                                      - LPC_I2C1      :I2C1 peripheral\r
1306  * @return              Complete status, could be: TRUE/FALSE\r
1307  **********************************************************************/\r
1308 uint32_t I2C_SlaveTransferComplete(LPC_I2Cn_Type *I2Cx)\r
1309 {\r
1310         uint32_t retval, tmp;\r
1311         tmp = I2C_getNum(I2Cx);\r
1312         retval = I2C_SlaveComplete[tmp];\r
1313         I2C_SlaveComplete[tmp] = FALSE;\r
1314         return retval;\r
1315 }\r
1316 \r
1317 \r
1318 \r
1319 /**\r
1320  * @}\r
1321  */\r
1322 \r
1323 #endif /* _I2C */\r
1324 \r
1325 /**\r
1326  * @}\r
1327  */\r
1328 \r
1329 /* --------------------------------- End Of File ------------------------------ */\r