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