1 /***************************************************************************//**
2 * \file cy_scb_i2c.c
3 * \version 3.10
4 *
5 * Provides I2C API implementation of the SCB driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2021 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *     http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include "cy_device.h"
26 
27 #if (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB))
28 
29 #include "cy_scb_i2c.h"
30 
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34 
35 /***************************************
36 *        Function Prototypes
37 ***************************************/
38 
39 static void SlaveHandleAddress     (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
40 static void SlaveHandleDataReceive (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
41 static void SlaveHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
42 static void SlaveHandleStop        (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
43 
44 static void MasterHandleEvents      (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
45 static void MasterHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
46 static void MasterHandleDataReceive (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
47 static void MasterHandleStop        (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
48 static void MasterHandleComplete    (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
49 
50 static cy_en_scb_i2c_status_t HandleStatus(CySCB_Type *base, uint32_t status,
51                                            cy_stc_scb_i2c_context_t *context);
52 static uint32_t WaitOneUnit(uint32_t *timeout);
53 
54 
55 /*******************************************************************************
56 * Function Name: Cy_SCB_I2C_Init
57 ****************************************************************************//**
58 *
59 * Initializes the SCB for the I2C operation.
60 *
61 * \param base
62 * The pointer to the I2C SCB instance.
63 *
64 * \param config
65 * The pointer to the configuration structure \ref cy_stc_scb_i2c_config_t.
66 *
67 * \param context
68 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
69 * by the user. The structure is used during the I2C operation for internal
70 * configuration and data retention. The user must not modify anything
71 * in this structure.
72 *
73 * \return
74 * \ref cy_en_scb_i2c_status_t
75 *
76 * \note
77 * If SCB is already enabled, ensure that the SCB block is disabled \ref Cy_SCB_I2C_Disable
78 * before calling this function.
79 *******************************************************************************/
Cy_SCB_I2C_Init(CySCB_Type * base,cy_stc_scb_i2c_config_t const * config,cy_stc_scb_i2c_context_t * context)80 cy_en_scb_i2c_status_t Cy_SCB_I2C_Init(CySCB_Type *base, cy_stc_scb_i2c_config_t const *config, cy_stc_scb_i2c_context_t *context)
81 {
82     /* Input parameters verification */
83     if ((NULL == base) || (NULL == config) || (NULL == context))
84     {
85         return CY_SCB_I2C_BAD_PARAM;
86     }
87 
88     CY_ASSERT_L3(CY_SCB_I2C_IS_MODE_VALID(config->i2cMode));
89     CY_ASSERT_L2((config->useRxFifo) ? (!config->acceptAddrInFifo) : true);
90     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID     (config->slaveAddress));
91     CY_ASSERT_L2(CY_SCB_I2C_IS_ADDR_MASK_VALID(config->slaveAddressMask));
92     CY_ASSERT_L2(CY_SCB_I2C_IS_PHASE_OVERSAMPLE_VALID(config->highPhaseDutyCycle));
93     CY_ASSERT_L2(CY_SCB_I2C_IS_PHASE_OVERSAMPLE_VALID(config->lowPhaseDutyCycle));
94 
95     /* Configure the I2C interface */
96     SCB_CTRL(base) = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, config->acceptAddrInFifo)   |
97                      _BOOL2FLD(SCB_CTRL_EC_AM_MODE, config->enableWakeFromSleep);
98 #if(defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION==1))
99     SCB_CTRL(base) |= SCB_CTRL_BYTE_MODE_Msk;
100 #endif /* CY_IP_MXSCB_VERSION */
101 
102     SCB_I2C_CTRL(base) = _BOOL2FLD(SCB_I2C_CTRL_S_GENERAL_IGNORE, !config->ackGeneralAddr)        |
103                          _VAL2FLD(SCB_I2C_CTRL_HIGH_PHASE_OVS, (config->highPhaseDutyCycle - 1U)) |
104                          _VAL2FLD(SCB_I2C_CTRL_LOW_PHASE_OVS,  (config->lowPhaseDutyCycle - 1U))  |
105                          _VAL2FLD(CY_SCB_I2C_CTRL_MODE, (uint32_t) config->i2cMode);
106 
107     {
108         /* Enable digital filter for only for master modes */
109         bool enableDigFilter = (CY_SCB_I2C_SLAVE != config->i2cMode) && (config->enableDigitalFilter);
110 
111         /* Configure the RX direction */
112         SCB_RX_CTRL(base)      = _BOOL2FLD(SCB_RX_CTRL_MEDIAN, enableDigFilter) |
113                                  CY_SCB_I2C_RX_CTRL;
114 
115         /* Configure an analog filter */
116         SCB_I2C_CFG(base) = (enableDigFilter) ? CY_SCB_I2C_DISABLE_ANALOG_FITLER : CY_SCB_I2C_ENABLE_ANALOG_FITLER;
117     }
118 
119     SCB_RX_FIFO_CTRL(base) = (config->useRxFifo ? (CY_SCB_I2C_FIFO_SIZE - 1UL) : 0UL);
120 
121     /* Set the default address and mask */
122     SCB_RX_MATCH(base) = _VAL2FLD(SCB_RX_MATCH_ADDR, ((uint32_t) config->slaveAddress << 1UL)) |
123                          _VAL2FLD(SCB_RX_MATCH_MASK, (uint32_t)  config->slaveAddressMask);
124 
125     /* Configure the TX direction */
126     SCB_TX_CTRL(base)      = CY_SCB_I2C_TX_CTRL;
127     SCB_TX_FIFO_CTRL(base) = (config->useTxFifo ? CY_SCB_I2C_HALF_FIFO_SIZE : 1UL);
128 
129     /* Configure interrupt sources */
130     SCB_INTR_SPI_EC_MASK(base) = 0UL;
131     SCB_INTR_I2C_EC_MASK(base) = 0UL;
132     SCB_INTR_RX_MASK(base)     = 0UL;
133     SCB_INTR_TX_MASK(base)     = 0UL;
134     SCB_INTR_M_MASK(base)      = 0UL;
135 
136     SCB_INTR_S_MASK(base) = (CY_SCB_I2C_MASTER != config->i2cMode) ? CY_SCB_I2C_SLAVE_INTR : 0UL;
137 
138     /* Initialize the context */
139     context->useRxFifo = config->useRxFifo;
140     context->useTxFifo = config->useTxFifo;
141 
142     context->state = CY_SCB_I2C_IDLE;
143 
144     /* Master-specific */
145     context->masterStatus     = 0UL;
146     context->masterBufferIdx  = 0UL;
147 
148     /* Slave-specific */
149     context->slaveStatus       = 0UL;
150 
151     context->slaveRxBufferIdx  = 0UL;
152     context->slaveRxBufferSize = 0UL;
153 
154     context->slaveTxBufferIdx  = 0UL;
155     context->slaveTxBufferSize = 0UL;
156 
157     /* Unregister callbacks */
158     context->cbEvents = NULL;
159     context->cbAddr   = NULL;
160 
161     return CY_SCB_I2C_SUCCESS;
162 }
163 
164 
165 /*******************************************************************************
166 *  Function Name: Cy_SCB_I2C_DeInit
167 ****************************************************************************//**
168 *
169 * De-initializes the SCB block and returns register values to default.
170 *
171 * \param base
172 * The pointer to the I2C SCB instance.
173 *
174 * \note
175 * Ensure that the SCB block is disabled \ref Cy_SCB_I2C_Disable before calling this function.
176 *
177 *******************************************************************************/
Cy_SCB_I2C_DeInit(CySCB_Type * base)178 void Cy_SCB_I2C_DeInit(CySCB_Type *base)
179 {
180     /* Returns block registers into the default state */
181     SCB_CTRL(base)     = CY_SCB_CTRL_DEF_VAL;
182     SCB_I2C_CTRL(base) = CY_SCB_I2C_CTRL_DEF_VAL;
183     SCB_I2C_CFG(base)  = CY_SCB_I2C_CFG_DEF_VAL;
184 
185     SCB_RX_CTRL(base)      = CY_SCB_RX_CTRL_DEF_VAL;
186     SCB_RX_FIFO_CTRL(base) = 0UL;
187     SCB_RX_MATCH(base)     = 0UL;
188 
189     SCB_TX_CTRL(base)      = CY_SCB_TX_CTRL_DEF_VAL;
190     SCB_TX_FIFO_CTRL(base) = 0UL;
191 
192     SCB_INTR_SPI_EC_MASK(base) = 0UL;
193     SCB_INTR_I2C_EC_MASK(base) = 0UL;
194     SCB_INTR_RX_MASK(base)     = 0UL;
195     SCB_INTR_TX_MASK(base)     = 0UL;
196     SCB_INTR_M_MASK(base)      = 0UL;
197     SCB_INTR_S_MASK(base)      = 0UL;
198 }
199 
200 
201 /*******************************************************************************
202 * Function Name: Cy_SCB_I2C_Disable
203 ****************************************************************************//**
204 *
205 * Disables the SCB block and clears context statuses.
206 * Note that after the block is disabled, the TX and RX FIFOs and hardware
207 * statuses are cleared. Also, the hardware stops driving the output and
208 * ignores the input.
209 *
210 * \param base
211 * The pointer to the I2C SCB instance.
212 *
213 * \param context
214 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
215 * by the user. The structure is used during the I2C operation for internal
216 * configuration and data retention. The user must not modify anything
217 * in this structure.
218 *
219 * \note
220 * Calling this function when I2C is busy (master preforms transaction or slave
221 * was addressed and is communicating with master) may cause transaction corruption
222 * because the hardware stops driving the outputs and ignores the inputs.
223 * Ensure that I2C is not busy before calling this function.
224 *
225 *******************************************************************************/
Cy_SCB_I2C_Disable(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)226 void Cy_SCB_I2C_Disable(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
227 {
228     SCB_CTRL(base) &= (uint32_t) ~SCB_CTRL_ENABLED_Msk;
229 
230     /* Set the state to default and clear statuses */
231     context->state        = CY_SCB_I2C_IDLE;
232     context->masterStatus = 0UL;
233     context->slaveStatus  = 0UL;
234 }
235 
236 
237 /*******************************************************************************
238 * Function Name: Cy_SCB_I2C_DeepSleepCallback
239 ****************************************************************************//**
240 *
241 * This function handles the transition of the I2C SCB into and out of
242 * Deep Sleep mode. It prevents the device from entering Deep Sleep
243 * mode if the I2C slave or master is actively communicating.
244 * The  behavior of the I2C SCB in Deep Sleep depends on whether the SCB block is
245 * wakeup-capable or not:
246 * * <b>Wakeup-capable</b>: during Deep Sleep mode on incoming I2C slave address
247 *   the slave receives address and stretches the clock until the device is
248 *   awoken from Deep Sleep mode. If the slave address occurs before the device
249 *   enters Deep Sleep mode, the device will not enter Deep Sleep mode.
250 *   Only the I2C slave can be configured to be a wakeup source from Deep Sleep
251 *   mode.
252 * * <b>Not wakeup-capable</b>: the SCB is disabled in Deep Sleep mode.
253 *   It is re-enabled if the device fails to enter Deep Sleep mode or when the
254 *   device is awoken from Deep Sleep mode. While the SCB is disabled it stops
255 *   driving the outputs and ignores the inputs. The slave NACKs all incoming
256 *   addresses.
257 *
258 * This function must be called during execution of \ref Cy_SysPm_CpuEnterDeepSleep.
259 * To do it, register this function as a callback before calling
260 * \ref Cy_SysPm_CpuEnterDeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
261 * type and call \ref Cy_SysPm_RegisterCallback.
262 *
263 * \param callbackParams
264 * The pointer to the callback parameters structure
265 * \ref cy_stc_syspm_callback_params_t.
266 *
267 * \param mode
268 * Callback mode, see \ref cy_en_syspm_callback_mode_t
269 *
270 * \return
271 * \ref cy_en_syspm_status_t
272 *
273 * \note
274 * Only applicable for <b>rev-08 of the CY8CKIT-062-BLE</b>.
275 * For proper operation, when the I2C slave is configured to be a wakeup source
276 * from Deep Sleep mode, this function must be copied and modified by the user.
277 * The I2C clock disable code must be inserted in the \ref CY_SYSPM_BEFORE_TRANSITION
278 * and clock enable code in the \ref CY_SYSPM_AFTER_TRANSITION mode processing.
279 *
280 *******************************************************************************/
Cy_SCB_I2C_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)281 cy_en_syspm_status_t Cy_SCB_I2C_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
282 {
283     CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
284     cy_stc_scb_i2c_context_t *locContext = (cy_stc_scb_i2c_context_t *) callbackParams->context;
285 
286     cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
287 
288     switch(mode)
289     {
290         case CY_SYSPM_CHECK_READY:
291         {
292             /* Disable the slave interrupt sources to protect the state */
293             Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
294 
295             /* If the I2C is in the IDLE state, it is ready for Deep Sleep mode
296             * (either the master or the slave is not busy),
297             * otherwise return fail and restore the slave interrupt sources.
298             */
299             if (CY_SCB_I2C_IDLE == locContext->state)
300             {
301                 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
302                 {
303                     /* The SCB is wakeup-capable: do not restore the address
304                     * match and general call interrupt sources. The next
305                     * transaction intended to the slave will be paused
306                     * (SCL is stretched) before the address is ACKed because
307                     * the corresponding interrupt source is disabled.
308                     */
309                     Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR_NO_ADDR);
310                 }
311                 else
312                 {
313                     /* The SCB is NOT wakeup-capable: disable the I2C. The slave
314                     * stops responding to the master and the master stops
315                     * driving the bus until the I2C is enabled. This happens
316                     * when the device failed to enter into Deep Sleep mode or it
317                     * is awaken from Deep Sleep mode.
318                     */
319                     Cy_SCB_I2C_Disable(locBase, locContext);
320                     Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
321                 }
322 
323                 retStatus = CY_SYSPM_SUCCESS;
324             }
325             else
326             {
327                 /* Restore the slave interrupt sources */
328                 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
329             }
330         }
331         break;
332 
333         case CY_SYSPM_CHECK_FAIL:
334         {
335             /* The other driver is not ready for Deep Sleep mode. Restore
336             * Active mode configuration.
337             */
338 
339             if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
340             {
341                 /* The SCB is wakeup-capable: restore the slave interrupt sources */
342                 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
343             }
344             else
345             {
346                 /* The SCB is NOT wakeup-capable: enable the I2C to operate */
347                 Cy_SCB_I2C_Enable(locBase);
348             }
349 
350             retStatus = CY_SYSPM_SUCCESS;
351         }
352         break;
353 
354         case CY_SYSPM_BEFORE_TRANSITION:
355         {
356             /* This code executes inside the critical section. Enabling the
357             * active interrupt source makes the interrupt pending in the NVIC.
358             * However, the interrupt processing is delayed until the code exits
359             * the critical section. The pending interrupt force WFI instruction
360             * does nothing and the device remains in Active mode.
361             */
362 
363             if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
364             {
365                 /* The SCB is wakeup-capable: enable the I2C wakeup interrupt
366                 * source. If any transaction was paused, the I2C interrupt
367                 * becomes pending and prevents entering Deep Sleep mode.
368                 * The transaction continues as soon as the global interrupts
369                 * are enabled.
370                 */
371                 Cy_SCB_SetI2CInterruptMask(locBase, CY_SCB_I2C_INTR_WAKEUP);
372 
373                 /* Disable SCB clock */
374                 SCB_I2C_CFG(locBase) &= (uint32_t) ~CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
375 
376                 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
377                 * for proper entering Deep Sleep mode the I2C clock must be disabled.
378                 * This code must be inserted by the user because the driver
379                 * does not have access to the clock.
380                 */
381             }
382 
383             retStatus = CY_SYSPM_SUCCESS;
384         }
385         break;
386 
387         case CY_SYSPM_AFTER_TRANSITION:
388         {
389             if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
390             {
391                 /* Enable SCB clock */
392                 SCB_I2C_CFG(locBase) |= CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
393 
394                 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
395                 * for proper exiting Deep Sleep, the I2C clock must be enabled.
396                 * This code must be inserted by the user because the driver
397                 * does not have access to the clock.
398                 */
399 
400                 /* The SCB is wakeup-capable: disable the I2C wakeup interrupt
401                 * source and restore slave interrupt sources.
402                 */
403                 Cy_SCB_SetI2CInterruptMask  (locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
404                 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
405             }
406             else
407             {
408                 /* The SCB is NOT wakeup-capable: enable the I2C to operate */
409                 Cy_SCB_I2C_Enable(locBase);
410             }
411 
412             retStatus = CY_SYSPM_SUCCESS;
413         }
414         break;
415 
416         default:
417             /* Unknown state */
418             break;
419     }
420 
421     return (retStatus);
422 }
423 
424 
425 /*******************************************************************************
426 * Function Name: Cy_SCB_I2C_HibernateCallback
427 ****************************************************************************//**
428 *
429 * This function handles the transition of the I2C SCB block into Hibernate
430 * mode. It prevents the device from entering Hibernate mode if the I2C slave or
431 * master is actively communicating.
432 * If the I2C is ready to enter Hibernate mode it is disabled. If the device
433 * failed to enter Hibernate mode, the SCB is enabled. After the SCB is disabled,
434 * it stops driving the outputs and ignores the inputs. The slave NACKs all
435 * incoming addresses.
436 *
437 * This function must be called during execution of \ref Cy_SysPm_SystemEnterHibernate.
438 * To do it, register this function as a callback before calling
439 * \ref Cy_SysPm_SystemEnterHibernate : specify \ref CY_SYSPM_HIBERNATE as the callback
440 * type and call \ref Cy_SysPm_RegisterCallback.
441 *
442 * \param callbackParams
443 * The pointer to the callback parameters structure
444 * \ref cy_stc_syspm_callback_params_t.
445 *
446 * \param mode
447 * Callback mode, see \ref cy_en_syspm_callback_mode_t
448 *
449 * \return
450 * \ref cy_en_syspm_status_t
451 *
452 *******************************************************************************/
Cy_SCB_I2C_HibernateCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)453 cy_en_syspm_status_t Cy_SCB_I2C_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
454 {
455     CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
456     cy_stc_scb_i2c_context_t *locContext = (cy_stc_scb_i2c_context_t *) callbackParams->context;
457 
458     cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
459 
460     switch(mode)
461     {
462         case CY_SYSPM_CHECK_READY:
463         {
464             /* Disable the slave interrupt sources to protect the state */
465             Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
466 
467             /* If the I2C is in the IDLE state, it is ready for Hibernate mode
468             * (either the master or the slave is not busy).
469             * Otherwise, return fail and restore the slave interrupt sources.
470             */
471             if (CY_SCB_I2C_IDLE == locContext->state)
472             {
473                 /* Disable the I2C. The slave stops responding to the master and
474                 * the master stops driving the bus until the I2C is enabled.
475                 * This happens if the device failed to enter Hibernate mode.
476                 */
477                 Cy_SCB_I2C_Disable(locBase, locContext);
478 
479                 retStatus = CY_SYSPM_SUCCESS;
480             }
481 
482             /* Restore the slave interrupt sources */
483             Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
484         }
485         break;
486 
487         case CY_SYSPM_CHECK_FAIL:
488         {
489             /* The other driver is not ready for Hibernate mode. Restore the
490             * Active mode configuration.
491             */
492 
493             /* Enable the I2C to operate */
494             Cy_SCB_I2C_Enable(locBase);
495 
496             retStatus = CY_SYSPM_SUCCESS;
497         }
498         break;
499 
500         case CY_SYSPM_BEFORE_TRANSITION:
501         case CY_SYSPM_AFTER_TRANSITION:
502         {
503             /* The SCB is not capable of waking up from Hibernate mode: do nothing */
504             retStatus = CY_SYSPM_SUCCESS;
505         }
506         break;
507 
508         default:
509             /* Unknown state */
510             break;
511     }
512 
513     return (retStatus);
514 }
515 
516 
517 /*******************************************************************************
518 * Function Name: Cy_SCB_I2C_SetDataRate
519 ****************************************************************************//**
520 *
521 * Configures the SCB to work at the desired data rate.
522 *
523 * \param base
524 * The pointer to the I2C SCB instance.
525 *
526 * \param dataRateHz
527 * The desired data Rate in Hz.
528 *
529 * \param scbClockHz
530 * The frequency of the clock connected to the SCB in Hz.
531 *
532 * \return
533 * The achieved data rate in Hz. \n
534 * When zero value is returned there is an error in the input parameters:
535 * data rate or clk_scb is out of valid range.
536 *
537 * \note
538 * This function does not change the values of the clock divider connected
539 * to the SCB, it changes only the SCB clock oversample registers. If this
540 * function is not able to achieve the desired data rate, then the clock
541 * divider must be adjusted. Call this function only while the SCB is
542 * disabled. For the slave, this function only checks that the attached clock is
543 * fast enough to meet the desired data rate. It does not change any registers.
544 *
545 *******************************************************************************/
Cy_SCB_I2C_SetDataRate(CySCB_Type * base,uint32_t dataRateHz,uint32_t scbClockHz)546 uint32_t Cy_SCB_I2C_SetDataRate(CySCB_Type *base, uint32_t dataRateHz, uint32_t scbClockHz)
547 {
548     CY_ASSERT_L2(scbClockHz > 0UL);
549     CY_ASSERT_L2(CY_SCB_I2C_IS_DATA_RATE_VALID(dataRateHz));
550 
551     uint32_t actualDataRateHz = 0UL;
552 
553     if (((uint32_t) CY_SCB_I2C_SLAVE) == _FLD2VAL(CY_SCB_I2C_CTRL_MODE, SCB_I2C_CTRL(base)))
554     {
555         actualDataRateHz = Cy_SCB_I2C_GetDataRate(base, scbClockHz);
556 
557         /* Use an analog filter for the slave */
558         SCB_RX_CTRL(base) &= (uint32_t) ~SCB_RX_CTRL_MEDIAN_Msk;
559         SCB_I2C_CFG(base)  = CY_SCB_I2C_ENABLE_ANALOG_FITLER;
560     }
561     else
562     {
563         bool errorRange = true;
564         uint32_t sclLow;
565         uint32_t sclHigh;
566 
567         uint32_t lowPhase  = 8U;
568         uint32_t highPhase = 8U;
569         bool enableMedian  = false;
570 
571         /* Get duration of SCL low and high for the selected data rate */
572         if ((0U == dataRateHz) || (dataRateHz > CY_SCB_I2C_FSTP_DATA_RATE))
573         {
574             errorRange = true;
575         }
576         else if (dataRateHz <= CY_SCB_I2C_STD_DATA_RATE)
577         {
578             /* Check SCB clock ranges for Standard rate */
579             if ((scbClockHz >= CY_SCB_I2C_MASTER_STD_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_MASTER_STD_CLK_MAX))
580             {
581                 sclLow  = CY_SCB_I2C_MASTER_STD_SCL_LOW;
582                 sclHigh = CY_SCB_I2C_MASTER_STD_SCL_HIGH;
583                 enableMedian = false;
584 
585                 errorRange = false;
586             }
587         }
588         else if (dataRateHz <= CY_SCB_I2C_FST_DATA_RATE)
589         {
590             /* Check SCB clock ranges for Fast rate */
591             if ((scbClockHz >= CY_SCB_I2C_MASTER_FST_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_MASTER_FST_CLK_MAX))
592             {
593                 sclLow  = CY_SCB_I2C_MASTER_FST_SCL_LOW;
594                 sclHigh = CY_SCB_I2C_MASTER_FST_SCL_HIGH;
595                 enableMedian = false;
596 
597                 errorRange = false;
598             }
599         }
600         else
601         {
602             /* Check SCB clock ranges for Fast rate */
603             if ((scbClockHz >= CY_SCB_I2C_MASTER_FSTP_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_MASTER_FSTP_CLK_MAX))
604             {
605                 /* Check SCB clock ranges for Fast rate */
606                 sclLow  = CY_SCB_I2C_MASTER_FSTP_SCL_LOW;
607                 sclHigh = CY_SCB_I2C_MASTER_FSTP_SCL_HIGH;
608                 enableMedian = true;
609 
610                 errorRange = false;
611             }
612         }
613 
614         /* Calculate data rate if data rate and clock ranges are valid */
615         if (!errorRange)
616         {
617             bool updateLowPhase;
618 
619             /* Get period of the SCB clock in ns */
620             uint32_t period = 1000000000U / scbClockHz;
621 
622             /* Get low phase minimum value in SCB clocks */
623             lowPhase = sclLow / period;
624 
625             if ((period * lowPhase) < sclLow)
626             {
627                 ++lowPhase;
628             }
629 
630             if (lowPhase > CY_SCB_I2C_LOW_PHASE_MAX)
631             {
632                 lowPhase = CY_SCB_I2C_LOW_PHASE_MAX;
633             }
634 
635             /* Define if update low phase */
636             updateLowPhase = (lowPhase < CY_SCB_I2C_LOW_PHASE_MAX);
637 
638             /* Get high phase minimum value in SCB clocks */
639             highPhase = sclHigh / period;
640 
641             if ((period * highPhase) < sclHigh)
642             {
643                 ++highPhase;
644             }
645 
646             if (highPhase > CY_SCB_I2C_HIGH_PHASE_MAX)
647             {
648                 highPhase = CY_SCB_I2C_HIGH_PHASE_MAX;
649             }
650 
651             /* Get actual data rate */
652             actualDataRateHz = scbClockHz / (lowPhase + highPhase);
653 
654             /* Find desired data rate */
655             while ((actualDataRateHz > dataRateHz) && ((lowPhase + highPhase) < CY_SCB_I2C_DUTY_CYCLE_MAX))
656             {
657                 /* Increase low and high phase to reach desired data rate */
658                 if (updateLowPhase)
659                 {
660                     if (lowPhase < CY_SCB_I2C_LOW_PHASE_MAX)
661                     {
662                         /* Update low phase */
663                         lowPhase++;
664                         updateLowPhase = false;
665                     }
666                 }
667                 else
668                 {
669                     if (highPhase < CY_SCB_I2C_HIGH_PHASE_MAX)
670                     {
671                         /* Update high phase */
672                         highPhase++;
673                         updateLowPhase = (lowPhase < CY_SCB_I2C_LOW_PHASE_MAX);
674                     }
675                 }
676 
677                 /* Update actual data rate */
678                 actualDataRateHz = scbClockHz / (lowPhase + highPhase);
679             }
680 
681             /* Set filter configuration based on actual data rate */
682             if (enableMedian)
683             {
684                 /* Use a digital filter */
685                 SCB_RX_CTRL(base) |= (uint32_t) SCB_RX_CTRL_MEDIAN_Msk;
686                 SCB_I2C_CFG(base)  = CY_SCB_I2C_DISABLE_ANALOG_FITLER;
687             }
688             else
689             {
690                 /* Use an analog filter */
691                 SCB_RX_CTRL(base) &= (uint32_t) ~SCB_RX_CTRL_MEDIAN_Msk;
692                 SCB_I2C_CFG(base)  = CY_SCB_I2C_ENABLE_ANALOG_FITLER;
693             }
694 
695             /* Set phase low and high */
696             Cy_SCB_I2C_MasterSetLowPhaseDutyCycle (base, lowPhase);
697             Cy_SCB_I2C_MasterSetHighPhaseDutyCycle(base, highPhase);
698         }
699     }
700 
701     return (actualDataRateHz);
702 }
703 
704 
705 /*******************************************************************************
706 * Function Name: Cy_SCB_I2C_GetDataRate
707 ****************************************************************************//**
708 *
709 * Returns the data rate for the selected SCB block.
710 *
711 * \param base
712 * The pointer to the I2C SCB instance.
713 *
714 * \param scbClockHz
715 * The frequency of the clock connected to the SCB in Hz.
716 *
717 * \return
718 * The data rate in Hz. \n
719 * For slave mode when zero value is returned the clk_scb is out of valid
720 * range.
721 *
722 *******************************************************************************/
Cy_SCB_I2C_GetDataRate(CySCB_Type const * base,uint32_t scbClockHz)723 uint32_t Cy_SCB_I2C_GetDataRate(CySCB_Type const *base, uint32_t scbClockHz)
724 {
725     CY_ASSERT_L2(scbClockHz > 0UL);
726 
727     uint32_t actualDataRate = 0UL;
728 
729     if (((uint32_t) CY_SCB_I2C_SLAVE) == _FLD2VAL(CY_SCB_I2C_CTRL_MODE, SCB_I2C_CTRL(base)))
730     {
731         /* Check the clock frequency range to get maximum supported data rate */
732         if ((scbClockHz >= CY_SCB_I2C_SLAVE_FST_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_SLAVE_FST_CLK_MAX))
733         {
734             actualDataRate = CY_SCB_I2C_FST_DATA_RATE;
735         }
736         else if ((scbClockHz >= CY_SCB_I2C_SLAVE_STD_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_SLAVE_STD_CLK_MAX))
737         {
738             actualDataRate = CY_SCB_I2C_STD_DATA_RATE;
739         }
740         else if ((scbClockHz >= CY_SCB_I2C_SLAVE_FSTP_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_SLAVE_FSTP_CLK_MAX))
741         {
742             actualDataRate = CY_SCB_I2C_FSTP_DATA_RATE;
743         }
744         else
745         {
746             /* The clock frequency is too low or it gets to the gap between
747             * Fast and Fast Plus data rates.
748             */
749             actualDataRate = 0UL;
750         }
751     }
752     else
753     {
754         if (scbClockHz > 0U)
755         {
756             uint32_t dutyCycle;
757 
758             /* Get number of clocks in one SCL period */
759             dutyCycle = _FLD2VAL(SCB_I2C_CTRL_LOW_PHASE_OVS,  SCB_I2C_CTRL(base)) +
760                         _FLD2VAL(SCB_I2C_CTRL_HIGH_PHASE_OVS, SCB_I2C_CTRL(base)) +
761                         2UL;
762 
763             /* Calculate the actual data rate */
764             actualDataRate = (scbClockHz / dutyCycle);
765         }
766     }
767 
768     return (actualDataRate);
769 }
770 
771 
772 /*******************************************************************************
773 *                         I2C Slave API
774 *******************************************************************************/
775 
776 /*******************************************************************************
777 * Function Name: Cy_SCB_I2C_SlaveGetStatus
778 ****************************************************************************//**
779 *
780 * Returns the current I2C slave status.
781 * This status is a bit mask and the value returned may have multiple bits set.
782 *
783 * \param base
784 * The pointer to the I2C SCB instance.
785 *
786 * \param context
787 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
788 * by the user. The structure is used during the I2C operation for internal
789 * configuration and data retention. The user must not modify anything
790 * in this structure.
791 *
792 * \return
793 * \ref group_scb_i2c_macros_slave_status.
794 *
795 *******************************************************************************/
Cy_SCB_I2C_SlaveGetStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)796 uint32_t Cy_SCB_I2C_SlaveGetStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
797 {
798     /* Suppress a compiler warning about unused variables */
799     (void) base;
800 
801     return (context->slaveStatus);
802 }
803 
804 
805 /*******************************************************************************
806 * Function Name: Cy_SCB_I2C_SlaveConfigReadBuf
807 ****************************************************************************//**
808 *
809 * Configures the buffer pointer and the read buffer size. This is the buffer
810 * from which the master reads data. After this function is called, data
811 * transfer from the read buffer to the master is handled by
812 * \ref Cy_SCB_I2C_Interrupt.
813 *
814 * When the Read transaction is completed (master generated Stop, ReStart or
815 * error occurred), the \ref CY_SCB_I2C_SLAVE_RD_BUSY status is cleared and
816 * the \ref CY_SCB_I2C_SLAVE_RD_CMPLT is set. Also
817 * the \ref CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT event is generated.
818 *
819 * \param base
820 * The pointer to the I2C SCB instance.
821 *
822 * \param buffer
823 * The pointer to the buffer with data to be read by the master.
824 *
825 * \param size
826 * Size of the buffer.
827 *
828 * \param context
829 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
830 * by the user. The structure is used during the I2C operation for internal
831 * configuration and data retention. The user must not modify anything
832 * in this structure.
833 *
834 * \note
835 * * The Read buffer must not be modified and stay allocated until it has been
836 *   read by the master.
837 * * If this function has not been called, and the master tries to read data
838 *   from the slave a \ref CY_SCB_I2C_DEFAULT_TX is returned to the master.
839 * * If the master tries to read more bytes than available in the Read buffer,
840 *   a \ref CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT event occurs. The
841 *   \ref CY_SCB_I2C_DEFAULT_TX is returned to the master if the buffer remains
842 *   empty after an event notification.
843 *
844 *******************************************************************************/
Cy_SCB_I2C_SlaveConfigReadBuf(CySCB_Type const * base,uint8_t * buffer,uint32_t size,cy_stc_scb_i2c_context_t * context)845 void Cy_SCB_I2C_SlaveConfigReadBuf(CySCB_Type const *base, uint8_t *buffer, uint32_t size,
846                                    cy_stc_scb_i2c_context_t *context)
847 {
848     CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
849 
850     /* Suppress a compiler warning about unused variables */
851     (void) base;
852 
853     context->slaveTxBuffer     = buffer;
854     context->slaveTxBufferSize = size;
855     context->slaveTxBufferIdx  = 0UL;
856     context->slaveTxBufferCnt  = 0UL;
857 }
858 
859 
860 /*******************************************************************************
861 * Function Name: Cy_SCB_I2C_SlaveAbortRead
862 ****************************************************************************//**
863 *
864 * Aborts the configured slave read buffer to be read by the master.
865 * If the master reads and "abort operation" is requested, the
866 * \ref CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT event occurs. The
867 * \ref CY_SCB_I2C_DEFAULT_TX is returned to the master if the buffer remains
868 * empty after the event notification.
869 *
870 * \param base
871 * The pointer to the I2C SCB instance.
872 *
873 * \param context
874 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
875 * by the user. The structure is used during the I2C operation for internal
876 * configuration and data retention. The user must not modify anything
877 * in this structure.
878 *
879 * \sideeffect
880 * If the TX FIFO is used, this function clears it.
881 * The TX FIFO clear operation also clears the shift register, thus
882 * the shifter can be cleared in the middle of a data element transfer,
883 * corrupting it. The data element corruption means that all bits that have
884 * not been transmitted are transmitted as "ones" on the bus.
885 *
886 *******************************************************************************/
Cy_SCB_I2C_SlaveAbortRead(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)887 void Cy_SCB_I2C_SlaveAbortRead(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
888 {
889     uint32_t intrState;
890 
891     /* Suppress a compiler warning about unused variables */
892     (void) base;
893 
894     intrState = Cy_SysLib_EnterCriticalSection();
895 
896     /* Reset index to make write buffer empty */
897     context->slaveTxBufferSize = 0UL;
898 
899     if ((context->useTxFifo) &&
900         (0UL != (CY_SCB_I2C_SLAVE_RD_BUSY & context->slaveStatus)))
901     {
902         /* Clear TX FIFO from available data */
903         Cy_SCB_ClearTxFifo(base);
904     }
905 
906     Cy_SysLib_ExitCriticalSection(intrState);
907 }
908 
909 
910 /*******************************************************************************
911 * Function Name: Cy_SCB_I2C_SlaveGetReadTransferCount
912 ****************************************************************************//**
913 *
914 * Returns the number of bytes read by the master since the last time
915 * \ref Cy_SCB_I2C_SlaveConfigReadBuf was called.
916 *
917 * \param base
918 * The pointer to the I2C SCB instance.
919 *
920 * \param context
921 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
922 * by the user. The structure is used during the I2C operation for internal
923 * configuration and data retention. The user must not modify anything
924 * in this structure.
925 *
926 * \return
927 * The number of bytes read by the master.
928 *
929 * \note
930 * * This function returns an invalid value if a read transaction was
931 *   aborted or any listed event occurs during the transaction:
932 *   \ref CY_SCB_I2C_SLAVE_ARB_LOST, \ref CY_SCB_I2C_SLAVE_BUS_ERR.
933 * * This number is updated only when a transaction completes, either through
934 *   an error or successfully.
935 *
936 *******************************************************************************/
Cy_SCB_I2C_SlaveGetReadTransferCount(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)937 uint32_t Cy_SCB_I2C_SlaveGetReadTransferCount(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
938 {
939     /* Suppress a compiler warning about unused variables */
940     (void) base;
941 
942     return (context->slaveTxBufferCnt);
943 }
944 
945 
946 /*******************************************************************************
947 * Function Name: Cy_SCB_I2C_SlaveClearReadStatus
948 ****************************************************************************//**
949 *
950 * Clears the read status and error conditions flags and returns their values.
951 *
952 * \param base
953 * The pointer to the I2C SCB instance.
954 *
955 * \param context
956 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
957 * by the user. The structure is used during the I2C operation for internal
958 * configuration and data retention. The user must not modify anything
959 * in this structure.
960 *
961 * \return
962 * \ref group_scb_i2c_macros_slave_status.
963 *
964 * \note
965 * The \ref CY_SCB_I2C_SLAVE_RD_BUSY flag is not cleared.
966 *
967 *******************************************************************************/
Cy_SCB_I2C_SlaveClearReadStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t * context)968 uint32_t Cy_SCB_I2C_SlaveClearReadStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t *context)
969 {
970     uint32_t retStatus;
971 
972     /* Suppress a compiler warning about unused variables */
973     (void) base;
974 
975     retStatus = (context->slaveStatus & CY_SCB_I2C_SLAVE_RD_CLEAR);
976     context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_RD_CLEAR;
977 
978     return (retStatus);
979 }
980 
981 
982 /*******************************************************************************
983 * Function Name: Cy_SCB_I2C_SlaveConfigWriteBuf
984 ****************************************************************************//**
985 *
986 * Configures the buffer pointer and size of the write buffer. This is the buffer
987 * that the master writes data to. After this function is called data transfer
988 * from the master into the write buffer is handled by \ref Cy_SCB_I2C_Interrupt.
989 *
990 * When write transaction is completed (master generated Stop, ReStart or
991 * error occurred) the \ref CY_SCB_I2C_SLAVE_WR_BUSY status is cleared and
992 * the \ref CY_SCB_I2C_SLAVE_WR_CMPLT is set, also
993 * the \ref CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT event is generated.
994 *
995 * \param base
996 * The pointer to the I2C SCB instance.
997 *
998 * \param buffer
999 * The pointer to buffer to store data written by the master.
1000 *
1001 * \param size
1002 * Size of the buffer.
1003 *
1004 * \param context
1005 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1006 * by the user. The structure is used during the I2C operation for internal
1007 * configuration and data retention. The user must not modify anything
1008 * in this structure.
1009 *
1010 * \note
1011 * * The write buffer must not be modified and must stay allocated until it has been
1012 *   written by the master.
1013 * * If this function has not been called and the master tries to write data,
1014 *   the first byte is NAKed and discarded.
1015 * * If the master writes more bytes than the slave can store in the write buffer,
1016 *   the \ref CY_SCB_I2C_SLAVE_WR_OVRFL status is set and the slave will NACK last
1017 *   byte, unless the RX FIFO is used. Then the slave will NAK only after
1018 *   RX FIFO becomes full.
1019 * * If the RX FIFO is used, the minimum write buffer size is automatically
1020 *   the size of the RX FIFO. If a write buffer is less than the RX FIFO size, extra
1021 *   bytes are ACKed and stored into RX FIFO but ignored by firmware.
1022 *
1023 *******************************************************************************/
Cy_SCB_I2C_SlaveConfigWriteBuf(CySCB_Type const * base,uint8_t * buffer,uint32_t size,cy_stc_scb_i2c_context_t * context)1024 void Cy_SCB_I2C_SlaveConfigWriteBuf(CySCB_Type const *base, uint8_t *buffer, uint32_t size,
1025                                     cy_stc_scb_i2c_context_t *context)
1026 {
1027     CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
1028 
1029     /* Suppress a compiler warning about unused variables */
1030     (void) base;
1031 
1032     context->slaveRxBuffer     = buffer;
1033     context->slaveRxBufferSize = size;
1034     context->slaveRxBufferIdx  = 0UL;
1035 }
1036 
1037 
1038 /*******************************************************************************
1039 * Function Name: Cy_SCB_I2C_SlaveAbortWrite
1040 ****************************************************************************//**
1041 *
1042 * Aborts the configured slave write buffer to be written by the master.
1043 * If master writes and an "abort operation" is requested, the next incoming
1044 * byte will be NAKed.
1045 *
1046 * \param base
1047 * The pointer to the I2C SCB instance.
1048 *
1049 * \param context
1050 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1051 * by the user. The structure is used during the I2C operation for internal
1052 * configuration and data retention. The user must not modify anything
1053 * in this structure.
1054 *
1055 * \note
1056 * If the RX FIFO is used, the NAK will not be sent until RX FIFO
1057 * becomes full, however bytes accepted after an abort request are ignored.
1058 *
1059 *******************************************************************************/
Cy_SCB_I2C_SlaveAbortWrite(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)1060 void Cy_SCB_I2C_SlaveAbortWrite(CySCB_Type *base,  cy_stc_scb_i2c_context_t *context)
1061 {
1062     uint32_t intrState;
1063 
1064     /* Suppress a compiler warning about unused variables */
1065     (void) base;
1066 
1067     intrState = Cy_SysLib_EnterCriticalSection();
1068 
1069     /* Reset index to make read buffer empty */
1070     context->slaveRxBufferSize = 0UL;
1071 
1072     if ((context->useRxFifo) &&
1073         (0UL != (CY_SCB_I2C_SLAVE_WR_BUSY & context->slaveStatus)))
1074     {
1075         /* Configure to NACK when RX FIFO is full and disable RX level
1076         * interrupt sources to stop getting data from RX FIFO.
1077         */
1078         SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
1079         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1080     }
1081 
1082     Cy_SysLib_ExitCriticalSection(intrState);
1083 }
1084 
1085 
1086 /*******************************************************************************
1087 * Function Name: Cy_SCB_I2C_SlaveGetWriteTransferCount
1088 ****************************************************************************//**
1089 *
1090 * Returns the number of bytes written by the master since the last time
1091 * \ref Cy_SCB_I2C_SlaveConfigWriteBuf was called.
1092 *
1093 * \param base
1094 * The pointer to the I2C SCB instance.
1095 *
1096 * \param context
1097 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1098 * by the user. The structure is used during the I2C operation for internal
1099 * configuration and data retention. The user must not modify anything
1100 * in this structure.
1101 *
1102 * \return
1103 * Number of bytes written by the master.
1104 *
1105 * \note
1106 * * This function returns an invalid value if write transaction was
1107 *   aborted or any listed event occurs during the transaction:
1108 *   \ref CY_SCB_I2C_SLAVE_ARB_LOST, \ref CY_SCB_I2C_SLAVE_BUS_ERR.
1109 * * This number is updated only when the transaction completes, either through
1110 *   an error or successfully.
1111 *
1112 *******************************************************************************/
Cy_SCB_I2C_SlaveGetWriteTransferCount(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)1113 uint32_t Cy_SCB_I2C_SlaveGetWriteTransferCount(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
1114 {
1115     /* Suppress a compiler warning about unused variables */
1116     (void) base;
1117 
1118     return (context->slaveRxBufferIdx);
1119 }
1120 
1121 
1122 /*******************************************************************************
1123 * Function Name: Cy_SCB_I2C_SlaveClearWriteStatus
1124 ****************************************************************************//**
1125 *
1126 * Clears the write status flags and error condition flags and returns their
1127 * values.
1128 *
1129 * \param base
1130 * The pointer to the I2C SCB instance.
1131 *
1132 * \param context
1133 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1134 * by the user. The structure is used during the I2C operation for internal
1135 * configuration and data retention. The user must not modify anything
1136 * in this structure.
1137 *
1138 * \return
1139 * \ref group_scb_i2c_macros_slave_status.
1140 *
1141 * \note
1142 * The \ref CY_SCB_I2C_SLAVE_WR_BUSY flag is not cleared.
1143 *
1144 *******************************************************************************/
Cy_SCB_I2C_SlaveClearWriteStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t * context)1145 uint32_t Cy_SCB_I2C_SlaveClearWriteStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t *context)
1146 {
1147     uint32_t retStatus;
1148 
1149     /* Suppress a compiler warning about unused variables */
1150     (void) base;
1151 
1152     retStatus = (context->slaveStatus & CY_SCB_I2C_SLAVE_WR_CLEAR);
1153     context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_WR_CLEAR;
1154 
1155     return (retStatus);
1156 }
1157 
1158 
1159 /*******************************************************************************
1160 *                         I2C Master API: High level
1161 *******************************************************************************/
1162 
1163 /*******************************************************************************
1164 * Function Name: Cy_SCB_I2C_MasterGetStatus
1165 ****************************************************************************//**
1166 *
1167 * Returns the current I2C master status.
1168 * This status is a bit mask and the value returned may have multiple bits set.
1169 *
1170 * \param base
1171 * The pointer to the I2C SCB instance.
1172 *
1173 * \param context
1174 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1175 * by the user. The structure is used during the I2C operation for internal
1176 * configuration and data retention. The user must not modify anything
1177 * in this structure.
1178 *
1179 * \return
1180 * \ref group_scb_i2c_macros_master_status.
1181 * Note that not all I2C master statuses are returned by this function. Refer to
1182 * more details of each status.
1183 *
1184 * \note
1185 * Status is cleared by calling \ref Cy_SCB_I2C_MasterRead or
1186 * \ref Cy_SCB_I2C_MasterWrite.
1187 *
1188 *******************************************************************************/
Cy_SCB_I2C_MasterGetStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)1189 uint32_t Cy_SCB_I2C_MasterGetStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
1190 {
1191     /* Suppress a compiler warning about unused variables */
1192     (void) base;
1193 
1194     return (context->masterStatus);
1195 }
1196 
1197 
1198 /*******************************************************************************
1199 * Function Name: Cy_SCB_I2C_MasterRead
1200 ****************************************************************************//**
1201 *
1202 * This function configures the master to automatically read an entire buffer
1203 * of data from the slave device. After the transaction is initiated by this
1204 * function it returns and \ref Cy_SCB_I2C_Interrupt manages further data
1205 * transfer.
1206 *
1207 * When a read transaction is completed (requested number of bytes are read or
1208 * error occurred) the \ref CY_SCB_I2C_MASTER_BUSY status is cleared and
1209 * the \ref CY_SCB_I2C_MASTER_RD_CMPLT_EVENT event is generated.
1210 *
1211 * Note that the master must read at least one byte.
1212 *
1213 * \param base
1214 * The pointer to the I2C SCB instance.
1215 *
1216 * \param xferConfig
1217 * Master transfer configuration structure
1218 * \ref cy_stc_scb_i2c_master_xfer_config_t.
1219 *
1220 * \param context
1221 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1222 * by the user. The structure is used during the I2C operation for internal
1223 * configuration and data retention. The user must not modify anything
1224 * in this structure.
1225 *
1226 * \return
1227 * \ref cy_en_scb_i2c_status_t
1228 *
1229 * \note
1230 * * The buffer must not be modified and must stay allocated until read operation
1231 *   completion.
1232 *
1233 * * \ref Cy_SCB_I2C_MasterRead requests the SCB hardware to generate a start
1234 *   condition when there is no pending transfer and returns (does not wait
1235 *   until hardware generate a start condition). If the I2C bus is busy the
1236 *   hardware will not generate the until bus becomes free.
1237 *   The SCB hardware sets the busy status after the Start detection, and clears
1238 *   it on the Stop detection. Noise caused by the ESD or other events may cause
1239 *   an erroneous Start condition on the bus. Then, the master will never generate
1240 *   a Start condition because the hardware assumes the bus is busy. If this occurs,
1241 *   the \ref Cy_SCB_I2C_MasterGetStatus returns \ref CY_SCB_I2C_MASTER_BUSY
1242 *   status and the transaction will never finish. The option is to implement a
1243 *   timeout to detect the transfer completion. If the transfer never completes,
1244 *   the SCB needs a reset by calling the \ref Cy_SCB_I2C_Disable and
1245 *   \ref Cy_SCB_I2C_Enable functions. The \ref Cy_SCB_I2C_MasterAbortRead
1246 *   function will not work, the block must be reset.
1247 *
1248 *******************************************************************************/
Cy_SCB_I2C_MasterRead(CySCB_Type * base,cy_stc_scb_i2c_master_xfer_config_t * xferConfig,cy_stc_scb_i2c_context_t * context)1249 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterRead(CySCB_Type *base,
1250                             cy_stc_scb_i2c_master_xfer_config_t *xferConfig,
1251                             cy_stc_scb_i2c_context_t *context)
1252 {
1253     CY_ASSERT_L1(xferConfig != NULL);
1254     CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID  (xferConfig->buffer, xferConfig->bufferSize));
1255     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(xferConfig->slaveAddress));
1256 
1257     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1258 
1259     /* Disable I2C slave interrupt sources to protect state */
1260     Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1261 
1262     if (0UL != (CY_SCB_I2C_IDLE_MASK & context->state))
1263     {
1264         uint32_t intrState;
1265 
1266         /* Set address byte (bit0 = 1, read direction) */
1267         uint32_t address = _VAL2FLD(CY_SCB_I2C_ADDRESS, xferConfig->slaveAddress) |
1268                          (uint32_t) CY_SCB_I2C_READ_XFER;
1269 
1270         /* Setup context */
1271         context->masterStatus     = CY_SCB_I2C_MASTER_BUSY;
1272 
1273         context->masterBuffer     = xferConfig->buffer;
1274         context->masterBufferSize = xferConfig->bufferSize;
1275         context->masterBufferIdx  = 0UL;
1276         context->masterNumBytes   = 0UL;
1277         context->masterPause      = xferConfig->xferPending;
1278         context->masterRdDir      = true;
1279 
1280         /* Clean-up hardware before transfer. Note RX FIFO is empty at here. */
1281         Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
1282         Cy_SCB_ClearTxFifo(base);
1283 
1284         if (CY_SCB_I2C_IDLE == context->state)
1285         {
1286             /* Put the address in the TX FIFO, then generate a Start condition.
1287             * This sequence ensures that after the Start condition generation
1288             * the address is available to be sent onto the bus.
1289             */
1290             Cy_SCB_WriteTxFifo(base, address);
1291             SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
1292         }
1293         else
1294         {
1295             /* Generate a ReStart condition.
1296             * If the previous transfer was read, NACK is generated before
1297             * ReStart to complete the previous transfer.
1298             */
1299             SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_START_Msk | (_FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)) ?
1300                                   SCB_I2C_M_CMD_M_NACK_Msk : 0UL));
1301 
1302             /* Put address in TX FIFO */
1303             Cy_SCB_WriteTxFifo(base, address);
1304         }
1305 
1306         /* Configure interrupt for data reception */
1307         if ((context->useRxFifo) && (!context->masterPause) && (context->masterBufferSize >= 2UL))
1308         {
1309             uint32_t fifoSize = CY_SCB_I2C_FIFO_SIZE;
1310 
1311             /* Enable Auto data ACK */
1312             SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_M_READY_DATA_ACK_Msk;
1313 
1314             /* Adjust level in RX FIFO */
1315             Cy_SCB_SetRxFifoLevel(base, (context->masterBufferSize <= fifoSize) ?
1316                                         (context->masterBufferSize - 2UL) : ((fifoSize / 2UL) - 1UL));
1317 
1318             context->state = CY_SCB_I2C_MASTER_RX1;
1319         }
1320         else
1321         {
1322             /* Adjust level in RX FIFO */
1323             Cy_SCB_SetRxFifoLevel(base, 0UL);
1324 
1325             context->state = CY_SCB_I2C_MASTER_RX0;
1326         }
1327 
1328         /* Enable interrupt sources to continue transfer.
1329         * Requires critical section to not cause race condition between RX and Master
1330         * interrupt sources.
1331         */
1332         intrState = Cy_SysLib_EnterCriticalSection();
1333         Cy_SCB_SetRxInterruptMask    (base, CY_SCB_RX_INTR_LEVEL);
1334         Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1335         Cy_SysLib_ExitCriticalSection(intrState);
1336 
1337         retStatus = CY_SCB_I2C_SUCCESS;
1338     }
1339 
1340     /* Enable I2C slave interrupt sources */
1341     Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
1342 
1343     return (retStatus);
1344 }
1345 
1346 
1347 /*******************************************************************************
1348 * Function Name: Cy_SCB_I2C_MasterAbortRead
1349 ****************************************************************************//**
1350 *
1351 * This function requests master to abort read operation by NAKing the next byte
1352 * and generating a Stop condition. The function does not wait until these
1353 * actions are completed. Therefore the next operation can be initiated only
1354 * after the \ref CY_SCB_I2C_MASTER_BUSY is cleared.
1355 *
1356 * \param base
1357 * The pointer to the I2C SCB instance.
1358 *
1359 * \param context
1360 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1361 * by the user. The structure is used during the I2C operation for internal
1362 * configuration and data retention. The user must not modify anything
1363 * in this structure.
1364 *
1365 ******************************************************************************/
Cy_SCB_I2C_MasterAbortRead(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)1366 void Cy_SCB_I2C_MasterAbortRead(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
1367 {
1368     uint32_t intrState;
1369 
1370     intrState = Cy_SysLib_EnterCriticalSection();
1371 
1372     if (0UL != (CY_SCB_I2C_MASTER_BUSY & context->masterStatus))
1373     {
1374         /* Catch state to abort read operation */
1375         if ((CY_SCB_I2C_MASTER_RX0 == context->state) || (CY_SCB_I2C_MASTER_RX1 == context->state))
1376         {
1377             if (context->useRxFifo)
1378             {
1379                 /* Disable RX processing */
1380                 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1381 
1382                 /* Change state to request Stop generation */
1383                 context->state = CY_SCB_I2C_MASTER_STOP;
1384 
1385                 /* Enable ACK interrupt source to generate Stop after Start was generated */
1386                 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR_ALL);
1387             }
1388             else
1389             {
1390                 /* Reduce buffer size to minimum */
1391                 context->masterBufferSize = 1UL;
1392             }
1393 
1394             /* Cancel pending read operation if it was requested */
1395             context->masterPause = false;
1396         }
1397     }
1398     else
1399     {
1400         /* There are two possible states when master is not busy:
1401         * CY_SCB_I2C_MASTER_WAIT and CY_SCB_I2C_IDLE.
1402         * Do nothing for CY_SCB_I2C_IDLE.
1403         */
1404         if (CY_SCB_I2C_MASTER_WAIT == context->state)
1405         {
1406             /* Clear master previous transaction results:
1407             * - status to indicate that master is busy;
1408             * - number of bytes (only Stop is generated);
1409             * - cancel previous pending operation.
1410             */
1411             context->masterStatus   = CY_SCB_I2C_MASTER_BUSY;
1412             context->masterNumBytes = 0UL;
1413             context->masterPause    = false;
1414 
1415             /* Enable master interrupt sources to catch Stop condition */
1416             Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1417 
1418             /* Complete transaction generating Stop */
1419             SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
1420             context->state  = CY_SCB_I2C_MASTER_WAIT_STOP;
1421         }
1422     }
1423 
1424     Cy_SysLib_ExitCriticalSection(intrState);
1425 }
1426 
1427 
1428 /*******************************************************************************
1429 * Function Name: Cy_SCB_I2C_MasterWrite
1430 ****************************************************************************//**
1431 *
1432 * This function configures the master to automatically write an entire buffer
1433 * of data to a slave device. After the transaction is initiated by this
1434 * function it returns and \ref Cy_SCB_I2C_Interrupt manages further data
1435 * transfer.
1436 *
1437 * When a write transaction is completed (requested number of bytes are written
1438 * or error occurred) the \ref CY_SCB_I2C_MASTER_BUSY status is cleared and
1439 * the \ref CY_SCB_I2C_MASTER_WR_CMPLT_EVENT event is generated.
1440 *
1441 * \param base
1442 * The pointer to the I2C SCB instance.
1443 *
1444 * \param xferConfig
1445 * Master transfer configuration structure
1446 * \ref cy_stc_scb_i2c_master_xfer_config_t.
1447 *
1448 * \param context
1449 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1450 * by the user. The structure is used during the I2C operation for internal
1451 * configuration and data retention. The user must not modify anything
1452 * in this structure.
1453 *
1454 * \return
1455 * \ref cy_en_scb_i2c_status_t
1456 *
1457 * \note
1458 * * The buffer must not be modified and must stay allocated until data has been
1459 *   copied into the TX FIFO.
1460 *
1461 * * \ref Cy_SCB_I2C_MasterWrite requests the SCB hardware to generate a start
1462 *   condition when there is no pending transfer and returns (does not wait
1463 *   until hardware generate a start condition). If the I2C bus is busy the
1464 *   hardware will not generate the until bus becomes free.
1465 *   The SCB hardware sets the busy status after the Start detection, and clears
1466 *   it on the Stop detection. Noise caused by the ESD or other events may cause
1467 *   an erroneous Start condition on the bus. Then, the master will never generate
1468 *   a Start condition because the hardware assumes the bus is busy. If this occurs,
1469 *   the \ref Cy_SCB_I2C_MasterGetStatus returns \ref CY_SCB_I2C_MASTER_BUSY
1470 *   status and the transaction will never finish. The option is to implement a
1471 *   timeout to detect the transfer completion. If the transfer never completes,
1472 *   the SCB needs a reset by calling the \ref Cy_SCB_I2C_Disable and
1473 *   \ref Cy_SCB_I2C_Enable functions. The \ref Cy_SCB_I2C_MasterAbortWrite
1474 *   function will not work, the block must be reset.
1475 *
1476 *******************************************************************************/
Cy_SCB_I2C_MasterWrite(CySCB_Type * base,cy_stc_scb_i2c_master_xfer_config_t * xferConfig,cy_stc_scb_i2c_context_t * context)1477 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterWrite(CySCB_Type *base,
1478                              cy_stc_scb_i2c_master_xfer_config_t *xferConfig,
1479                              cy_stc_scb_i2c_context_t *context)
1480 {
1481     CY_ASSERT_L1(xferConfig != NULL);
1482     CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(xferConfig->buffer, xferConfig->bufferSize));
1483     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID  (xferConfig->slaveAddress));
1484 
1485     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1486 
1487     /* Disable I2C slave interrupt sources to protect state */
1488     Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1489 
1490     if (0UL != (CY_SCB_I2C_IDLE_MASK & context->state))
1491     {
1492         uint32_t intrState;
1493 
1494         /* Set address byte (bit0 = 0, write direction) */
1495         uint32_t address = _VAL2FLD(CY_SCB_I2C_ADDRESS, xferConfig->slaveAddress);
1496 
1497         /* Setup context */
1498         context->masterStatus     = CY_SCB_I2C_MASTER_BUSY;
1499 
1500         context->masterBuffer     = xferConfig->buffer;
1501         context->masterBufferSize = xferConfig->bufferSize;
1502         context->masterBufferIdx  = 0UL;
1503         context->masterNumBytes   = 0UL;
1504         context->masterPause      = xferConfig->xferPending;
1505         context->masterRdDir      = false;
1506 
1507         /* Clean-up hardware before transfer. Note RX FIFO is empty at here. */
1508         Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
1509         Cy_SCB_ClearTxFifo(base);
1510 
1511         if (CY_SCB_I2C_IDLE == context->state)
1512         {
1513             /* Put the address in the TX FIFO, then generate a Start condition.
1514             * This sequence ensures that after the Start condition generation
1515             * the address is available to be sent onto the bus.
1516             */
1517             Cy_SCB_WriteTxFifo     (base, address);
1518             Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
1519             SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
1520         }
1521         else
1522         {
1523             /* Generate a ReStart condition.
1524             * If the previous transfer was read, NACK is generated before
1525             * ReStart to complete the previous transfer.
1526             */
1527             SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_START_Msk | (_FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)) ?
1528                                SCB_I2C_M_CMD_M_NACK_Msk : 0UL));
1529 
1530             if (0U == context->masterBufferSize)
1531             {
1532                 /* The address is the last byte to transfer.
1533                 * Put the address byte in the TX FIFO and clear the TX
1534                 * Underflow interrupt source inside the critical section
1535                 * to ensure that the TX Underflow interrupt will trigger
1536                 * after the address byte is sent onto the bus.
1537                 */
1538                 intrState = Cy_SysLib_EnterCriticalSection();
1539 
1540                 /* Put address in TX FIFO */
1541                 Cy_SCB_WriteTxFifo     (base, address);
1542                 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
1543 
1544                 Cy_SysLib_ExitCriticalSection(intrState);
1545             }
1546             else
1547             {
1548                 /* Put address in TX FIFO */
1549                 Cy_SCB_WriteTxFifo(base, address);
1550             }
1551         }
1552 
1553         context->state = CY_SCB_I2C_MASTER_TX;
1554 
1555         /* TX FIFO is empty. Set level to start transfer */
1556         Cy_SCB_SetTxFifoLevel(base, (context->useTxFifo) ? CY_SCB_I2C_HALF_FIFO_SIZE : (1UL));
1557 
1558         /* Enable interrupt sources to continue transfer.
1559         * Requires critical section to not cause race condition between TX and Master
1560         * interrupt sources.
1561         */
1562         intrState = Cy_SysLib_EnterCriticalSection();
1563         Cy_SCB_SetTxInterruptMask    (base, CY_SCB_TX_INTR_LEVEL);
1564         Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1565         Cy_SysLib_ExitCriticalSection(intrState);
1566 
1567         retStatus = CY_SCB_I2C_SUCCESS;
1568     }
1569 
1570     /* Enable I2C slave interrupt sources */
1571     Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
1572 
1573     return (retStatus);
1574 }
1575 
1576 
1577 /*******************************************************************************
1578 * Function Name: Cy_SCB_I2C_MasterAbortWrite
1579 ****************************************************************************//**
1580 *
1581 * This function requests the master to abort write operation by generating a Stop
1582 * condition. The function does not wait until this action is completed.
1583 * Therefore next write operation can be initiated only after the
1584 * \ref CY_SCB_I2C_MASTER_BUSY is cleared.
1585 *
1586 * \param base
1587 * The pointer to the I2C SCB instance.
1588 *
1589 * \param context
1590 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1591 * by the user. The structure is used during the I2C operation for internal
1592 * configuration and data retention. The user must not modify anything
1593 * in this structure.
1594 *
1595 * \sideeffect
1596 * If the TX FIFO is used, it is cleared before Stop generation.
1597 * The TX FIFO clear operation also clears shift register. Thus, the shifter
1598 * could be cleared in the middle of a data element transfer, corrupting it.
1599 * The remaining bits to transfer within corrupted data element are
1600 * complemented with ones.\n
1601 * If the clear operation is requested while the master transmits the address,
1602 * the direction of transaction is changed to read and one byte is read
1603 * before Stop is issued. This byte is discarded.
1604 *
1605 *******************************************************************************/
Cy_SCB_I2C_MasterAbortWrite(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)1606 void Cy_SCB_I2C_MasterAbortWrite(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
1607 {
1608     uint32_t intrState;
1609 
1610     intrState = Cy_SysLib_EnterCriticalSection();
1611 
1612     if (0UL != (CY_SCB_I2C_MASTER_BUSY & context->masterStatus))
1613     {
1614         /* Disable TX processing */
1615         Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1616 
1617         if (context->useTxFifo)
1618         {
1619             /* Clear TX FIFO to allow Stop generation */
1620             Cy_SCB_ClearTxFifo(base);
1621         }
1622 
1623         if ((CY_SCB_I2C_MASTER_TX == context->state) || (CY_SCB_I2C_MASTER_TX_DONE == context->state))
1624         {
1625             /* Change state to request Stop generation */
1626             context->state = CY_SCB_I2C_MASTER_STOP;
1627 
1628             /* Enable ACK interrupt source to trigger Stop generation */
1629             Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR_ALL);
1630         }
1631 
1632         /* Cancel pending write operation if it was requested */
1633         context->masterPause = false;
1634     }
1635     else
1636     {
1637         /* There are two possible states when master is not busy:
1638         * CY_SCB_I2C_MASTER_WAIT and CY_SCB_I2C_IDLE.
1639         * Do nothing for CY_SCB_I2C_IDLE.
1640         */
1641         if (CY_SCB_I2C_MASTER_WAIT == context->state)
1642         {
1643             /* Clear master previous transaction results:
1644             * - status to indicate that master is busy;
1645             * - number of bytes (only Stop is generated);
1646             * - cancel previous pending operation.
1647             */
1648             context->masterStatus   = CY_SCB_I2C_MASTER_BUSY;
1649             context->masterNumBytes = 0UL;
1650             context->masterPause    = false;
1651 
1652             /* Enable master interrupt sources to catch Stop condition */
1653             Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1654 
1655             /* Complete transaction generating Stop */
1656             SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
1657             context->state  = CY_SCB_I2C_MASTER_WAIT_STOP;
1658         }
1659     }
1660 
1661     Cy_SysLib_ExitCriticalSection(intrState);
1662 }
1663 
1664 
1665 /*******************************************************************************
1666 * Function Name: Cy_SCB_I2C_MasterGetTransferCount
1667 ****************************************************************************//**
1668 *
1669 * Returns the number of bytes transferred since the last call of
1670 * \ref Cy_SCB_I2C_MasterWrite or \ref Cy_SCB_I2C_MasterRead function.
1671 *
1672 * \param base
1673 * The pointer to the I2C SCB instance.
1674 *
1675 * \param context
1676 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1677 * by the user. The structure is used during the I2C operation for internal
1678 * configuration and data retention. The user must not modify anything
1679 * in this structure.
1680 *
1681 * \return
1682 * Number of bytes read or written by the master.
1683 *
1684 * \note
1685 * * This function returns an invalid value if read or write transaction was
1686 *   aborted or any listed event occurs during the transaction:
1687 *   \ref CY_SCB_I2C_MASTER_ARB_LOST, \ref CY_SCB_I2C_MASTER_BUS_ERR or
1688 *   \ref CY_SCB_I2C_MASTER_ABORT_START.
1689 *
1690 * * This number is updated only when the transaction completes, either through
1691 *   an error or successfully.
1692 *
1693 *******************************************************************************/
Cy_SCB_I2C_MasterGetTransferCount(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)1694 uint32_t Cy_SCB_I2C_MasterGetTransferCount(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
1695 {
1696     /* Suppress a compiler warning about unused variables */
1697     (void) base;
1698 
1699     return (context->masterNumBytes);
1700 }
1701 
1702 
1703 /*******************************************************************************
1704 *                         I2C Master API: Low level
1705 *******************************************************************************/
1706 
1707 
1708 /*******************************************************************************
1709 * Function Name: Cy_SCB_I2C_MasterSendStart
1710 ****************************************************************************//**
1711 *
1712 * Generates a Start condition and sends a slave address with the Read/Write bit.
1713 * This function is blocking. It does not return until the Start condition
1714 * and address byte are sent and a ACK/NAK is received, or an error or timeout
1715 * occurs.
1716 *
1717 * \param base
1718 * The pointer to the I2C SCB instance.
1719 *
1720 * \param address
1721 * 7 bit right justified slave address.
1722 *
1723 * \param bitRnW
1724 * This sets the value of the Read/Write bit in the address, thus defining
1725 * the direction of the following transfer.
1726 * See \ref cy_en_scb_i2c_direction_t for the set of constants.
1727 *
1728 * \param timeoutMs
1729 * Defines in milliseconds the time for which this function can block.
1730 * If that time expires, the function returns. If a zero is passed,
1731 * the function waits forever for the action to complete. If a timeout occurs,
1732 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
1733 *
1734 * \param context
1735 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1736 * by the user. The structure is used during the I2C operation for internal
1737 * configuration and data retention. The user must not modify anything
1738 * in this structure.
1739 *
1740 * \return
1741 * \ref cy_en_scb_i2c_status_t
1742 *
1743 * \note
1744 * After a read transaction is initiated and the slave ACKs the address, at
1745 * least one byte must be read before completing the transaction or changing
1746 * its direction.
1747 *
1748 *******************************************************************************/
Cy_SCB_I2C_MasterSendStart(CySCB_Type * base,uint32_t address,cy_en_scb_i2c_direction_t bitRnW,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)1749 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendStart(CySCB_Type *base,
1750                             uint32_t address, cy_en_scb_i2c_direction_t bitRnW,
1751                             uint32_t timeoutMs,
1752                             cy_stc_scb_i2c_context_t *context)
1753 {
1754     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID   (address));
1755     CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
1756     CY_ASSERT_L3(CY_SCB_I2C_IS_RW_BIT_VALID (bitRnW));
1757 
1758     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1759 
1760     /* Disable the I2C slave interrupt sources to protect the state */
1761     Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1762 
1763     if (CY_SCB_I2C_IDLE == context->state)
1764     {
1765         uint32_t locStatus;
1766         uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
1767 
1768         /* Set the read or write direction */
1769         context->state       = CY_SCB_I2C_MASTER_ADDR;
1770         context->masterRdDir = (CY_SCB_I2C_READ_XFER == bitRnW);
1771 
1772         /* Clean up the hardware before a transfer. Note RX FIFO is empty at here */
1773         Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
1774         Cy_SCB_ClearRxInterrupt    (base, CY_SCB_RX_INTR_NOT_EMPTY);
1775         Cy_SCB_ClearTxFifo(base);
1776 
1777         /* Generate a Start and send address byte */
1778         Cy_SCB_WriteTxFifo(base, (_VAL2FLD(CY_SCB_I2C_ADDRESS, address) | (uint32_t) bitRnW));
1779         SCB_I2C_M_CMD(base)  = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
1780 
1781         /* Wait for a completion event from the master or slave */
1782         do
1783         {
1784             locStatus  = (CY_SCB_I2C_MASTER_TX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
1785             locStatus |= (CY_SCB_I2C_SLAVE_ADDR_DONE & Cy_SCB_GetSlaveInterruptStatus(base));
1786             locStatus |= WaitOneUnit(&timeout);
1787 
1788         } while (0UL == locStatus);
1789 
1790         /* Convert the status from register plus timeout to the return status */
1791         retStatus = HandleStatus(base, locStatus, context);
1792     }
1793 
1794     /* Enable I2C slave interrupt sources */
1795     Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
1796 
1797     return (retStatus);
1798 }
1799 
1800 
1801 /*******************************************************************************
1802 * Function Name: Cy_SCB_I2C_MasterSendReStart
1803 ****************************************************************************//**
1804 *
1805 * Generates a ReStart condition and sends a slave address with the Read/Write
1806 * bit.
1807 * This function is blocking. It does not return until the ReStart condition
1808 * and address byte are sent and an ACK/NAK is received, or an error or timeout
1809 * occurs.
1810 *
1811 * \param base
1812 * The pointer to the I2C SCB instance.
1813 *
1814 * \param address
1815 * A 7-bit right-justified slave address.
1816 *
1817 * \param bitRnW
1818 * This sets the value of the Read/Write bit in the address, thus defining
1819 * the direction of the following transfer.
1820 * See \ref cy_en_scb_i2c_direction_t for the set of constants.
1821 *
1822 * \param timeoutMs
1823 * Defines in milliseconds the time for which this function can block.
1824 * If that time expires, the function returns. If a zero is passed,
1825 * the function waits forever for the action to complete. If a timeout occurs,
1826 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
1827 *
1828 * \param context
1829 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1830 * by the user. The structure is used during the I2C operation for internal
1831 * configuration and data retention. The user must not modify anything
1832 * in this structure.
1833 *
1834 * \return
1835 * \ref cy_en_scb_i2c_status_t
1836 *
1837 * \note
1838 * * A successful transaction must be initiated by \ref Cy_SCB_I2C_MasterSendStart
1839 *   before calling this function. If this condition is not met, this function
1840 *   does nothing and returns \ref CY_SCB_I2C_MASTER_NOT_READY.
1841 * * After a read transaction is initiated and the slave ACKs the address,
1842 *   at least one byte must be read before completing the transaction or
1843 *   changing its direction.
1844 *
1845 *******************************************************************************/
Cy_SCB_I2C_MasterSendReStart(CySCB_Type * base,uint32_t address,cy_en_scb_i2c_direction_t bitRnW,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)1846 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendReStart(CySCB_Type *base,
1847                         uint32_t address, cy_en_scb_i2c_direction_t bitRnW,
1848                         uint32_t timeoutMs,
1849                         cy_stc_scb_i2c_context_t *context)
1850 {
1851     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID   (address));
1852     CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
1853     CY_ASSERT_L3(CY_SCB_I2C_IS_RW_BIT_VALID (bitRnW));
1854 
1855     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1856 
1857     if (0UL != (CY_SCB_I2C_MASTER_ACTIVE & context->state))
1858     {
1859         uint32_t locStatus = 0U;
1860         uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
1861 
1862         /* Set the read or write direction */
1863         context->state       = CY_SCB_I2C_MASTER_ADDR;
1864         context->masterRdDir = (CY_SCB_I2C_READ_XFER == bitRnW);
1865 
1866         /* Generate ReStart condition.
1867         * If previous transfer was read, NACK is generated before ReStart to
1868         * complete previous transfer.
1869         */
1870         SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_Msk | (_FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)) ?
1871                           SCB_I2C_M_CMD_M_NACK_Msk : 0UL);
1872 
1873         /* Previous transfer was a write */
1874         if (false == _FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)))
1875         {
1876             /* Cypress ID #295908: Wait until ReStart is generated to complete
1877             * the previous write transfer. This ensures that the address byte
1878             * will not be interpreted as the data byte of the previous
1879             * transfer.
1880             */
1881             while ((0U == locStatus) &&
1882                    (0U != (SCB_I2C_M_CMD_M_START_Msk & SCB_I2C_M_CMD(base))))
1883             {
1884                 locStatus = WaitOneUnit(&timeout);
1885             }
1886         }
1887 
1888         /* Check for timeout and continue */
1889         if (0U == locStatus)
1890         {
1891             /* Send the address byte */
1892             Cy_SCB_WriteTxFifo(base, (_VAL2FLD(CY_SCB_I2C_ADDRESS, address) | (uint32_t) bitRnW));
1893 
1894             /* Wait for a completion event from the or slave */
1895             do
1896             {
1897                 locStatus  = (CY_SCB_I2C_MASTER_TX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
1898                 locStatus |= WaitOneUnit(&timeout);
1899 
1900             } while (0UL == locStatus);
1901         }
1902 
1903         /* Convert the status from register plus timeout to the return status */
1904         retStatus = HandleStatus(base, locStatus, context);
1905     }
1906 
1907     return (retStatus);
1908 }
1909 
1910 
1911 /*******************************************************************************
1912 * Function Name: Cy_SCB_I2C_MasterSendStop
1913 ****************************************************************************//**
1914 *
1915 * Generates a Stop condition to complete the current transaction.
1916 * This function is blocking. It does not return until the Stop condition
1917 * is generated, or an error or timeout occurs.
1918 *
1919 * \param base
1920 * The pointer to the I2C SCB instance.
1921 *
1922 * \param timeoutMs
1923 * Defines in milliseconds the time for which this function can block.
1924 * If that time expires, the function returns. If a zero is passed,
1925 * the function waits forever for the action to complete. If a timeout occurs,
1926 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
1927 *
1928 * \param context
1929 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1930 * by the user. The structure is used during the I2C operation for internal
1931 * configuration and data retention. The user must not modify anything
1932 * in this structure.
1933 *
1934 * \return
1935 * \ref cy_en_scb_i2c_status_t
1936 *
1937 * \note
1938 * * A successful transaction must be initiated by
1939 *   \ref Cy_SCB_I2C_MasterSendStart or \ref Cy_SCB_I2C_MasterSendReStart
1940 *   before calling this function. If this condition is not met, this function
1941 *   does nothing and returns.
1942 *   \ref CY_SCB_I2C_MASTER_NOT_READY.
1943 * * Even after the slave NAKs the address, this function must be called
1944 *   to complete the transaction.
1945 *
1946 *******************************************************************************/
Cy_SCB_I2C_MasterSendStop(CySCB_Type * base,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)1947 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendStop(CySCB_Type *base,uint32_t timeoutMs,
1948                                 cy_stc_scb_i2c_context_t *context)
1949 {
1950     CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
1951 
1952     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1953 
1954     if (0UL != (CY_SCB_I2C_MASTER_ACTIVE & context->state))
1955     {
1956         uint32_t locStatus;
1957         uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
1958 
1959         /* Generate a stop (for Write direction) and NACK plus stop for the Read direction */
1960         SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
1961 
1962         /* Wait for a completion event from the master or slave */
1963         do
1964         {
1965             locStatus  = (CY_SCB_I2C_MASTER_STOP_DONE & Cy_SCB_GetMasterInterruptStatus(base));
1966             locStatus |= WaitOneUnit(&timeout);
1967 
1968         } while (0UL == locStatus);
1969 
1970         /* Convert the status from register plus timeout to the return status */
1971         retStatus = HandleStatus(base, locStatus, context);
1972     }
1973 
1974     return (retStatus);
1975 }
1976 
1977 
1978 /*******************************************************************************
1979 * Function Name: Cy_SCB_I2C_MasterReadByte
1980 ****************************************************************************//**
1981 *
1982 * Reads one byte from a slave and generates an ACK or prepares to generate
1983 * a NAK. The NAK will be generated before a Stop or ReStart condition by
1984 * \ref Cy_SCB_I2C_MasterSendStop or \ref Cy_SCB_I2C_MasterSendReStart function
1985 * appropriately.
1986 * This function is blocking. It does not return until a byte is
1987 * received, or an error or timeout occurs.
1988 *
1989 * \param base
1990 * The pointer to the I2C SCB instance.
1991 *
1992 * \param ackNack
1993 * A response to a received byte.
1994 * See \ref cy_en_scb_i2c_command_t for the set of constants.
1995 *
1996 * \param byte
1997 * The pointer to the location to store the Read byte.
1998 *
1999 * \param timeoutMs
2000 * Defines in milliseconds the time for which this function can block.
2001 * If that time expires, the function returns. If a zero is passed,
2002 * the function waits forever for the action to complete. If a timeout occurs,
2003 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
2004 *
2005 * \param context
2006 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2007 * by the user. The structure is used during the I2C operation for internal
2008 * configuration and data retention. The user must not modify anything
2009 * in this structure.
2010 *
2011 * \return
2012 * \ref cy_en_scb_i2c_status_t
2013 *
2014 * \note
2015 * A successful transaction must be initiated by \ref Cy_SCB_I2C_MasterSendStart
2016 * or \ref Cy_SCB_I2C_MasterSendReStart before calling this function. If this
2017 * condition is not met, this function does nothing and returns
2018 * \ref CY_SCB_I2C_MASTER_NOT_READY.
2019 *
2020 *******************************************************************************/
Cy_SCB_I2C_MasterReadByte(CySCB_Type * base,cy_en_scb_i2c_command_t ackNack,uint8_t * byte,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)2021 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterReadByte(CySCB_Type *base,
2022                             cy_en_scb_i2c_command_t ackNack, uint8_t *byte,
2023                             uint32_t timeoutMs,
2024                             cy_stc_scb_i2c_context_t *context)
2025 {
2026     CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID      (byte, 1UL));
2027     CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID (timeoutMs));
2028     CY_ASSERT_L3(CY_SCB_I2C_IS_RESPONSE_VALID(ackNack));
2029 
2030     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
2031 
2032     if (CY_SCB_I2C_MASTER_RX0 == context->state)
2033     {
2034         bool     rxNotEmpty;
2035         uint32_t locStatus;
2036         uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
2037 
2038         /* Wait for ACK/NAK transmission and data byte reception */
2039         do
2040         {
2041             rxNotEmpty = (0UL != (CY_SCB_RX_INTR_NOT_EMPTY & Cy_SCB_GetRxInterruptStatus(base)));
2042             locStatus  = (CY_SCB_I2C_MASTER_RX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
2043             locStatus |= WaitOneUnit(&timeout);
2044 
2045         } while ((!rxNotEmpty) && (0UL == locStatus));
2046 
2047 
2048         if (rxNotEmpty)
2049         {
2050             /* Get the received data byte */
2051             *byte = (uint8_t) Cy_SCB_ReadRxFifo(base);
2052 
2053             Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_NOT_EMPTY | CY_SCB_RX_INTR_LEVEL);
2054         }
2055 
2056         /* Convert the status from register plus timeout to the return status */
2057         retStatus = HandleStatus(base, locStatus, context);
2058 
2059         if (CY_SCB_I2C_SUCCESS == retStatus)
2060         {
2061             if (CY_SCB_I2C_ACK == ackNack)
2062             {
2063                 /* Generate ACK */
2064                 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_ACK_Msk;
2065             }
2066             else
2067             {
2068                 /* NAK is generated by SendStop() or SendReStart() */
2069             }
2070         }
2071     }
2072 
2073     return (retStatus);
2074 }
2075 
2076 
2077 /*******************************************************************************
2078 * Function Name: Cy_SCB_I2C_MasterWriteByte
2079 ****************************************************************************//**
2080 *
2081 * Sends one byte to a slave.
2082 * This function is blocking. It does not return until a byte is
2083 * transmitted, or an error or timeout occurs.
2084 *
2085 * \param base
2086 * The pointer to the I2C SCB instance.
2087 *
2088 * \param byte
2089 * The byte to write to a slave.
2090 *
2091 * \param timeoutMs
2092 * Defines in milliseconds the time for which this function can block.
2093 * If that time expires, the function returns. If a zero is passed,
2094 * the function waits forever for the action to complete. If a timeout occurs,
2095 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
2096 *
2097 * \param context
2098 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2099 * by the user. The structure is used during the I2C operation for internal
2100 * configuration and data retention. The user must not modify anything
2101 * in this structure.
2102 *
2103 * \return
2104 * \ref cy_en_scb_i2c_status_t
2105 *
2106 * \note
2107 * A successful transaction must be initiated by \ref Cy_SCB_I2C_MasterSendStart
2108 * or \ref Cy_SCB_I2C_MasterSendReStart before calling this function. If this
2109 * condition is not met, this function does nothing and returns
2110 * \ref CY_SCB_I2C_MASTER_NOT_READY.
2111 *
2112 *******************************************************************************/
Cy_SCB_I2C_MasterWriteByte(CySCB_Type * base,uint8_t byte,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)2113 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterWriteByte(CySCB_Type *base, uint8_t byte, uint32_t timeoutMs,
2114                                                   cy_stc_scb_i2c_context_t *context)
2115 {
2116     CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
2117 
2118     cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
2119 
2120     if (CY_SCB_I2C_MASTER_TX == context->state)
2121     {
2122         uint32_t locStatus;
2123         uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
2124 
2125         /* Send the data byte */
2126         Cy_SCB_WriteTxFifo(base, (uint32_t) byte);
2127 
2128         /* Wait for a completion event from the master or slave */
2129         do
2130         {
2131             locStatus  = (CY_SCB_I2C_MASTER_TX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
2132             locStatus |= WaitOneUnit(&timeout);
2133 
2134         } while (0UL == locStatus);
2135 
2136         /* Convert the status from register plus timeout to the API status */
2137         retStatus = HandleStatus(base, locStatus, context);
2138     }
2139 
2140     return (retStatus);
2141 }
2142 
2143 
2144 /*******************************************************************************
2145 * Function Name: Cy_SCB_I2C_Interrupt
2146 ****************************************************************************//**
2147 *
2148 * This is the interrupt function for the SCB configured in the I2C mode.
2149 * The interrupt is mandatory for I2C operation and this function must be called
2150 * inside the user-defined interrupt service. The exception is the I2C master,
2151 * which uses only the \ref group_scb_i2c_master_low_level_functions functions.
2152 * To reduce the flash consumed by the I2C driver call
2153 * \ref Cy_SCB_I2C_SlaveInterrupt when I2C mode is the slave and
2154 * \ref Cy_SCB_I2C_MasterInterrupt when I2C mode is the master.
2155 *
2156 * \param base
2157 * The pointer to the I2C SCB instance.
2158 *
2159 * \param context
2160 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2161 * by the user. The structure is used during the I2C operation for internal
2162 * configuration and data retention. The user must not modify anything
2163 * in this structure.
2164 *
2165 *******************************************************************************/
Cy_SCB_I2C_Interrupt(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2166 void Cy_SCB_I2C_Interrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2167 {
2168     if (0UL != (CY_SCB_I2C_MASTER_ACTIVE & context->state))
2169     {
2170         /* Execute a transfer as the master */
2171         Cy_SCB_I2C_MasterInterrupt(base, context);
2172     }
2173     else
2174     {
2175         /* Execute a transfer as the slave */
2176         Cy_SCB_I2C_SlaveInterrupt(base, context);
2177     }
2178 }
2179 
2180 
2181 /*******************************************************************************
2182 * Function Name: Cy_SCB_I2C_SlaveInterrupt
2183 ****************************************************************************//**
2184 *
2185 * This is the interrupt function for the SCB configured in I2C mode as the
2186 * slave. This function should be called inside the user-defined interrupt
2187 * service routine to make any of the slave functions to work.
2188 *
2189 * \param base
2190 * The pointer to the I2C SCB instance.
2191 *
2192 * \param context
2193 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2194 * by the user. The structure is used during the I2C operation for internal
2195 * configuration and data retention. The user must not modify anything
2196 * in this structure.
2197 *
2198 *******************************************************************************/
Cy_SCB_I2C_SlaveInterrupt(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2199 void Cy_SCB_I2C_SlaveInterrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2200 {
2201     uint32_t slaveIntrStatus;
2202 
2203     /* Handle an I2C wake-up event */
2204     if (0UL != (CY_SCB_I2C_INTR_WAKEUP & Cy_SCB_GetI2CInterruptStatusMasked(base)))
2205     {
2206         /* Move from IDLE state, the slave was addressed. Following address match
2207         * interrupt continue transfer.
2208         */
2209         context->state = CY_SCB_I2C_SLAVE_ACTIVE;
2210 
2211         Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
2212     }
2213 
2214     /* Handle the slave interrupt sources */
2215     slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
2216 
2217     /* Handle the error conditions */
2218     if (0UL != (CY_SCB_I2C_SLAVE_INTR_ERROR & slaveIntrStatus))
2219     {
2220         /* Update the status */
2221         context->slaveStatus |= (0UL != (CY_SCB_SLAVE_INTR_I2C_BUS_ERROR & slaveIntrStatus)) ?
2222                                             CY_SCB_I2C_SLAVE_BUS_ERR : CY_SCB_I2C_SLAVE_ARB_LOST;
2223 
2224         /* Disable the RX interrupt source to drop data into RX FIFO if any */
2225         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2226 
2227         /* Add the stop status to back into the default state and set completion statuses */
2228         slaveIntrStatus |= CY_SCB_SLAVE_INTR_I2C_STOP;
2229     }
2230     else
2231     {
2232         if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
2233         {
2234             /* Get data from the RX FIFO after a stop is generated if there is
2235             * space to store it.
2236             */
2237             if ((Cy_SCB_GetNumInRxFifo(base) > 0UL) && (context->slaveRxBufferSize > 0UL))
2238             {
2239                 Cy_SCB_SetRxInterrupt    (base, CY_SCB_RX_INTR_LEVEL);
2240                 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
2241             }
2242         }
2243     }
2244 
2245     /* Handle the receive direction (master writes data) */
2246     if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
2247     {
2248         SlaveHandleDataReceive(base, context);
2249 
2250         Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2251     }
2252 
2253     /* Handle the transfer completion */
2254     if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
2255     {
2256         SlaveHandleStop(base, context);
2257 
2258         Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);
2259 
2260         /* Update the slave interrupt status */
2261         slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
2262     }
2263 
2264     /* Handle the address reception */
2265     if (0UL != (CY_SCB_I2C_SLAVE_INTR_ADDR & slaveIntrStatus))
2266     {
2267         SlaveHandleAddress(base, context);
2268 
2269         Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
2270         Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_I2C_SLAVE_INTR_ADDR);
2271     }
2272 
2273     /* Handle the transmit direction (master reads data) */
2274     if (0UL != (CY_SCB_I2C_SLAVE_INTR_TX & Cy_SCB_GetTxInterruptStatusMasked(base)))
2275     {
2276         SlaveHandleDataTransmit(base, context);
2277 
2278         Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
2279     }
2280 }
2281 
2282 #if (((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=3)) || defined (CY_IP_MXS22SCB)) || defined (CY_DOXYGEN))
2283 /*******************************************************************************
2284 * Function Name: Cy_SCB_I2C_SetStretchThreshold
2285 ****************************************************************************//**
2286 *
2287 * Sets the stretch threshold value.
2288 *
2289 * \param base
2290 * The pointer to the I2C SCB instance.
2291 *
2292 * \param value
2293 * The stretch threshold value to be set.
2294 * Typically it is the SCL turaround delay (including IO cell delay, SCL rise time,
2295 * analog filter delay), in number of clk_scb cycles.
2296 *
2297 * \note
2298 * * The STRETCH_THRESHOLD value is 0 by default. If there is no device stretching
2299 *   the SCL bus, the delay between SCL output and input are reported in
2300 *   STRETCH_COUNT \ref Cy_SCB_I2C_GetStretchCount, in number of clk_scb cycles,
2301 *   which can then be set as the STRETCH_THRESHOLD value.
2302 * * The STRETCH_THRESHOLD value should be less than or equal to 0xFUL.
2303 * * When STRETCH_COUNT \ref Cy_SCB_I2C_GetStretchCount is higher than this
2304 *   STRETCH_THRESHOLD, STRETCH_DETECTED \ref Cy_SCB_I2C_IsStretchDetected
2305 *   will be set.
2306 *
2307 * \note
2308 * This API is available for CAT1B devices.
2309 *
2310 *******************************************************************************/
Cy_SCB_I2C_SetStretchThreshold(CySCB_Type const * base,uint32_t value)2311 void Cy_SCB_I2C_SetStretchThreshold(CySCB_Type const *base, uint32_t value)
2312 {
2313     CY_ASSERT_L2(CY_SCB_I2C_STRETCH_THRESHOLD_VALUE_VALID(value));
2314     SCB_I2C_STRETCH_CTRL(base) = _VAL2FLD(SCB_I2C_STRETCH_CTRL_STRETCH_THRESHOLD, value);
2315 }
2316 
2317 /*******************************************************************************
2318 * Function Name: Cy_SCB_I2C_GetStretchCount
2319 ****************************************************************************//**
2320 *
2321 * Provides the stretch count. The count is started when the I2C device begins to
2322 * drive high phase on internal SCL output signal and is stalled when it detects
2323 * high level on SCL input signal.
2324 *
2325 * \param base
2326 * The pointer to the I2C SCB instance.
2327 *
2328 * \return
2329 * The stretch count.
2330 *
2331 * \note
2332 * This API is available for CAT1B devices.
2333 *
2334 *******************************************************************************/
Cy_SCB_I2C_GetStretchCount(CySCB_Type const * base)2335 uint32_t Cy_SCB_I2C_GetStretchCount(CySCB_Type const *base)
2336 {
2337     return(_FLD2VAL(SCB_I2C_STRETCH_STATUS_STRETCH_COUNT, SCB_I2C_STRETCH_STATUS(base)));
2338 }
2339 
2340 /*******************************************************************************
2341 * Function Name: Cy_SCB_I2C_IsStretchDetected
2342 ****************************************************************************//**
2343 *
2344 * Checks if stretch is detected on I2C SCL.
2345 *
2346 * \param base
2347 * The pointer to the I2C SCB instance.
2348 *
2349 * \return
2350 * If true, stretch is detected; false otherwise.
2351 *
2352 * \note
2353 * This API is available for CAT1B devices.
2354 *
2355 *******************************************************************************/
Cy_SCB_I2C_IsStretchDetected(CySCB_Type const * base)2356 bool Cy_SCB_I2C_IsStretchDetected(CySCB_Type const *base)
2357 {
2358     return (1UL == (_FLD2VAL(SCB_I2C_STRETCH_STATUS_STRETCH_DETECTED, SCB_I2C_STRETCH_STATUS(base))));
2359 }
2360 
2361 /*******************************************************************************
2362 * Function Name: Cy_SCB_I2C_IsSyncDetected
2363 ****************************************************************************//**
2364 *
2365 * Checks if synchronization is detected on I2C SCL.
2366 *
2367 * \param base
2368 * The pointer to the I2C SCB instance.
2369 *
2370 * \return
2371 * If true, synchronization is detected; false otherwise.
2372 *
2373 * \note
2374 * This API is available for CAT1B devices.
2375 *
2376 *******************************************************************************/
Cy_SCB_I2C_IsSyncDetected(CySCB_Type const * base)2377 bool Cy_SCB_I2C_IsSyncDetected(CySCB_Type const *base)
2378 {
2379     return (1UL == (_FLD2VAL(SCB_I2C_STRETCH_STATUS_SYNC_DETECTED, SCB_I2C_STRETCH_STATUS(base))));
2380 }
2381 
2382 /*******************************************************************************
2383 * Function Name: Cy_SCB_I2C_IsStretching
2384 ****************************************************************************//**
2385 *
2386 * Checks if I2C SCL is stretched by the block.
2387 *
2388 * \param base
2389 * The pointer to the I2C SCB instance.
2390 *
2391 * \return
2392 * If true, I2C SCL is being stretch by the block, false otherwise.
2393 *
2394 * \note
2395 * This API is available for CAT1B devices.
2396 *
2397 *******************************************************************************/
Cy_SCB_I2C_IsStretching(CySCB_Type const * base)2398 bool Cy_SCB_I2C_IsStretching(CySCB_Type const *base)
2399 {
2400     return (1UL == (_FLD2VAL(SCB_I2C_STRETCH_STATUS_STRETCHING, SCB_I2C_STRETCH_STATUS(base))));
2401 }
2402 #endif /* CY_IP_MXSCB_VERSION */
2403 
2404 /*******************************************************************************
2405 * Function Name: SlaveHandleAddress
2406 ****************************************************************************//**
2407 *
2408 * Prepares the slave for the following Read or Write transfer after the
2409 * matched address was received.
2410 *
2411 * \param base
2412 * The pointer to the I2C SCB instance.
2413 *
2414 * \param context
2415 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2416 * by the user. The structure is used during the I2C operation for internal
2417 * configuration and data retention. The user must not modify anything
2418 * in this structure.
2419 *
2420 *******************************************************************************/
SlaveHandleAddress(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2421 static void SlaveHandleAddress(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2422 {
2423     /* The default command is the ACK address. It can be overridden in an address callback */
2424     cy_en_scb_i2c_command_t cmd = CY_SCB_I2C_ACK;
2425 
2426     /* The callback for the address in RX FIFO or a general call */
2427     if (NULL != context->cbAddr)
2428     {
2429         uint32_t events = 0UL;
2430 
2431         /* Set an address in the FIFO event if the address accept is enabled */
2432         if (_FLD2BOOL(SCB_CTRL_ADDR_ACCEPT, SCB_CTRL(base)))
2433         {
2434             events = (0UL != (CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH & Cy_SCB_GetSlaveInterruptStatusMasked(base))) ?
2435                               CY_SCB_I2C_ADDR_IN_FIFO_EVENT : 0UL;
2436         }
2437 
2438         /* Set a general call event if "ignore general call" is disabled */
2439         if (!_FLD2BOOL(SCB_I2C_CTRL_S_GENERAL_IGNORE, SCB_I2C_CTRL(base)))
2440         {
2441             events |= (0UL != (CY_SCB_SLAVE_INTR_I2C_GENERAL_ADDR & Cy_SCB_GetSlaveInterruptStatusMasked(base))) ?
2442                                CY_SCB_I2C_GENERAL_CALL_EVENT : 0UL;
2443         }
2444 
2445         /* Check presence of events before involve callback */
2446         if (0UL != events)
2447         {
2448             /* Involve a callback for the address phase and get the ACK/NACK command */
2449             cmd = context->cbAddr(events);
2450 
2451             /* Clear RX level interrupt after address reception */
2452             Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2453 
2454             if (cmd == CY_SCB_I2C_ACK)
2455             {
2456                 /* Clear the stall stop status and enable the stop interrupt source */
2457                 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);
2458                 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
2459             }
2460             else
2461             {
2462                 /* Disable the stop interrupt source */
2463                 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR_NO_STOP);
2464             }
2465         }
2466     }
2467 
2468     /* Clear the TX FIFO before continue the transaction */
2469     Cy_SCB_ClearTxFifo(base);
2470 
2471     /* Set the command to an ACK or NACK address */
2472     SCB_I2C_S_CMD(base) = (cmd == CY_SCB_I2C_ACK) ? SCB_I2C_S_CMD_S_ACK_Msk : SCB_I2C_S_CMD_S_NACK_Msk;
2473 
2474     if (cmd == CY_SCB_I2C_ACK)
2475     {
2476         bool readDirection = _FLD2BOOL(SCB_I2C_STATUS_S_READ,SCB_I2C_STATUS(base));
2477 
2478         /* Notify the user about start of transfer */
2479         if (NULL != context->cbEvents)
2480         {
2481             context->cbEvents(readDirection ? CY_SCB_I2C_SLAVE_READ_EVENT : CY_SCB_I2C_SLAVE_WRITE_EVENT);
2482         }
2483 
2484         /* Prepare for a transfer */
2485         if (readDirection)
2486         {
2487             context->state        = CY_SCB_I2C_SLAVE_TX;
2488             context->slaveStatus |= CY_SCB_I2C_SLAVE_RD_BUSY;
2489 
2490             /* Prepare to transmit data */
2491             context->slaveTxBufferIdx = context->slaveTxBufferCnt;
2492             context->slaveRdBufEmpty  = false;
2493             Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
2494         }
2495         else
2496         {
2497             uint32_t level = 0UL;
2498 
2499             context->state        = CY_SCB_I2C_SLAVE_RX;
2500             context->slaveStatus |= CY_SCB_I2C_SLAVE_WR_BUSY;
2501 
2502             /* Prepare to receive data */
2503             Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
2504 
2505             if (context->useRxFifo)
2506             {
2507                 if (context->slaveRxBufferSize > 0UL)
2508                 {
2509                     uint32_t fifoSize = CY_SCB_I2C_FIFO_SIZE;
2510 
2511                     /* ACK data automatically until RX FIFO is full */
2512                     SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_READY_DATA_ACK_Msk;
2513 
2514                     if (context->slaveRxBufferSize > fifoSize)
2515                     {
2516                         /* Set a level in RX FIFO to trigger the receive interrupt source */
2517                         level = (context->slaveRxBufferSize - fifoSize);
2518                         level = ((level > fifoSize) ? (fifoSize / 2UL) : level) - 1UL;
2519                     }
2520                     else
2521                     {
2522                         /* Set a level in RX FIFO to read the number of bytes */
2523                         level = (context->slaveRxBufferSize - 1UL);
2524 
2525                         /* NACK when RX FIFO becomes full */
2526                         SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
2527 
2528                         /* Disable the RX level interrupt and wait until RX FIFO is full or stops */
2529                         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2530                     }
2531                 }
2532             }
2533 
2534             Cy_SCB_SetRxFifoLevel(base, level);
2535         }
2536     }
2537 }
2538 
2539 
2540 /*******************************************************************************
2541 * Function Name: SlaveHandleDataReceive
2542 ****************************************************************************//**
2543 *
2544 * Reads data from RX FIFO into the buffer provided by
2545 * \ref Cy_SCB_I2C_SlaveConfigWriteBuf.
2546 *
2547 * \param base
2548 * The pointer to the I2C SCB instance.
2549 *
2550 * \param context
2551 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2552 * by the user. The structure is used during the I2C operation for internal
2553 * configuration and data retention. The user must not modify anything
2554 * in this structure.
2555 *
2556 *******************************************************************************/
SlaveHandleDataReceive(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2557 static void SlaveHandleDataReceive(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2558 {
2559     /* Check whether there is space to put data */
2560     if (context->slaveRxBufferSize > 0UL)
2561     {
2562         if (context->useRxFifo)
2563         {
2564             uint32_t level;
2565             uint32_t fifoSize = CY_SCB_I2C_FIFO_SIZE;
2566 
2567             /* Get the number of bytes to read from RX FIFO */
2568             uint32_t numToCopy = Cy_SCB_GetRxFifoLevel(base) + 1UL;
2569 
2570             /* Get data from RX FIFO */
2571             numToCopy = Cy_SCB_ReadArray(base, context->slaveRxBuffer, numToCopy);
2572             context->slaveRxBufferIdx  += numToCopy;
2573             context->slaveRxBufferSize -= numToCopy;
2574             context->slaveRxBuffer      = &context->slaveRxBuffer[numToCopy];
2575 
2576             /* Prepare to read a next chunk of data */
2577             if (context->slaveRxBufferSize > fifoSize)
2578             {
2579                 level = context->slaveRxBufferSize - fifoSize;
2580                 level = ((level > fifoSize) ? (fifoSize / 2UL) : level) - 1UL;
2581             }
2582             else
2583             {
2584                 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
2585 
2586                 level = (context->slaveRxBufferSize == 0UL) ? (0UL) : (context->slaveRxBufferSize - 1UL);
2587                 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2588             }
2589 
2590             /* Set the RX level to trigger an interrupt */
2591             Cy_SCB_SetRxFifoLevel(base, level);
2592         }
2593         else
2594         {
2595             /* Continue the transfer: send an ACK */
2596             SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_ACK_Msk;
2597 
2598             /* Put data into the RX buffer */
2599             context->slaveRxBuffer[context->slaveRxBufferIdx] = (uint8_t) Cy_SCB_ReadRxFifo(base);
2600             ++context->slaveRxBufferIdx;
2601             --context->slaveRxBufferSize;
2602         }
2603     }
2604     else
2605     {
2606         /* Finish a transfer: send a NACK and discard the received byte */
2607         SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_NACK_Msk;
2608         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2609     }
2610 }
2611 
2612 
2613 /*******************************************************************************
2614 * Function Name: SlaveHandleDataTransmit
2615 ****************************************************************************//**
2616 *
2617 * Loads TX FIFO with data provided by \ref Cy_SCB_I2C_SlaveConfigReadBuf.
2618 *
2619 * \param base
2620 * The pointer to the I2C SCB instance.
2621 *
2622 * \param context
2623 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2624 * by the user. The structure is used during the I2C operation for internal
2625 * configuration and data retention. The user must not modify anything
2626 * in this structure.
2627 *
2628 *******************************************************************************/
SlaveHandleDataTransmit(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2629 static void SlaveHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2630 {
2631     uint32_t numToCopy;
2632 
2633     /* Notify the user that there is no data to send to the master.
2634     * This event triggers once in scope of a transfer.
2635     */
2636     if ((!context->slaveRdBufEmpty) && (0UL == context->slaveTxBufferSize))
2637     {
2638         /* Involve a callback if registered: no data to send */
2639         if (NULL != context->cbEvents)
2640         {
2641             context->cbEvents(CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT);
2642         }
2643 
2644         /* Update the Read buffer empty status after a callback is involved */
2645         context->slaveRdBufEmpty = (0UL == context->slaveTxBufferSize);
2646 
2647         /* Enable the TX level interrupt source to continue sending data */
2648         Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
2649     }
2650 
2651     /* Check whether the Read buffer was updated in the callback */
2652     if (context->slaveRdBufEmpty)
2653     {
2654         /* The Read buffer is empty: copy CY_SCB_I2C_DEFAULT_TX into TX FIFO */
2655         numToCopy = (context->useTxFifo) ? Cy_SCB_GetFifoSize(base) : 1UL;
2656 
2657         numToCopy = Cy_SCB_WriteDefaultArray(base, CY_SCB_I2C_DEFAULT_TX, numToCopy);
2658         context->slaveTxBufferIdx += numToCopy;
2659 
2660         context->slaveStatus |= CY_SCB_I2C_SLAVE_RD_UNDRFL;
2661     }
2662     else
2663     {
2664         if (context->slaveTxBufferSize > 1UL)
2665         {
2666             /* Get the number of bytes to copy into TX FIFO */
2667             numToCopy = (context->useTxFifo) ? (context->slaveTxBufferSize - 1UL) : (1UL);
2668 
2669             /* Write data into TX FIFO */
2670             numToCopy = Cy_SCB_WriteArray(base, context->slaveTxBuffer, numToCopy);
2671             context->slaveTxBufferIdx  += numToCopy;
2672             context->slaveTxBufferSize -= numToCopy;
2673             context->slaveTxBuffer      = &context->slaveTxBuffer[numToCopy];
2674         }
2675 
2676         /* Put the last byte */
2677         if ((CY_SCB_I2C_FIFO_SIZE != Cy_SCB_GetNumInTxFifo(base)) && (1UL == context->slaveTxBufferSize))
2678         {
2679             uint32_t intrStatus;
2680 
2681              /* Put the last data byte in the TX FIFO and clear the TX Underflow
2682             * interrupt source inside the critical section to ensure that the
2683             * TX Underflow interrupt will trigger after all data bytes from the
2684             * TX FIFO are transferred onto the bus.
2685             */
2686             intrStatus = Cy_SysLib_EnterCriticalSection();
2687 
2688             Cy_SCB_WriteTxFifo     (base, (uint32_t) context->slaveTxBuffer[0UL]);
2689             Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
2690 
2691             Cy_SysLib_ExitCriticalSection(intrStatus);
2692 
2693             /* Move the pointers */
2694             ++context->slaveTxBufferIdx;
2695             context->slaveTxBufferSize = 0UL;
2696             context->slaveTxBuffer     = &context->slaveTxBuffer[1UL];
2697 
2698             /* Enable the TX underflow interrupt to catch when there is no data to send */
2699             Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_UNDERFLOW);
2700 
2701             if (context->useTxFifo)
2702             {
2703                 /* Data is copied into TX FIFO */
2704                 context->slaveStatus |= CY_SCB_I2C_SLAVE_RD_IN_FIFO;
2705 
2706                 /* Involve a callback if registered: data copied into TX FIFO */
2707                 if (NULL != context->cbEvents)
2708                 {
2709                     context->cbEvents(CY_SCB_I2C_SLAVE_RD_IN_FIFO_EVENT);
2710                 }
2711             }
2712         }
2713     }
2714 }
2715 
2716 
2717 /*******************************************************************************
2718 * Function Name: SlaveHandleStop
2719 ****************************************************************************//**
2720 *
2721 * Handles transfer completion. It is triggered by a stop or restart
2722 * condition on the bus.
2723 *
2724 * \param base
2725 * The pointer to the I2C SCB instance.
2726 *
2727 * \param context
2728 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2729 * by the user. The structure is used during the I2C operation for internal
2730 * configuration and data retention. The user must not modify anything
2731 * in this structure.
2732 *
2733 *******************************************************************************/
SlaveHandleStop(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2734 static void SlaveHandleStop(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2735 {
2736     uint32_t locEvents;
2737 
2738     if (CY_SCB_I2C_SLAVE_RX == context->state)
2739     {
2740         /* If any data is left in RX FIFO, this is an overflow */
2741         if (Cy_SCB_GetNumInRxFifo(base) > 0UL)
2742         {
2743             context->slaveStatus |= CY_SCB_I2C_SLAVE_WR_OVRFL;
2744 
2745             if (context->useRxFifo)
2746             {
2747                 Cy_SCB_ClearRxFifo(base);
2748             }
2749             else
2750             {
2751                 (void) Cy_SCB_ReadRxFifo(base);
2752             }
2753         }
2754 
2755         locEvents             = (uint32_t)  CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT;
2756         context->slaveStatus |= (uint32_t)  CY_SCB_I2C_SLAVE_WR_CMPLT;
2757         context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_WR_BUSY;
2758 
2759         /* Clean up the RX direction */
2760         SCB_I2C_CTRL(base) &= (uint32_t) ~(SCB_I2C_CTRL_S_READY_DATA_ACK_Msk |
2761                                           SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk);
2762 
2763         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2764         Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2765     }
2766     else
2767     {
2768         /* The number of bytes left in TX FIFO */
2769         uint32_t size = Cy_SCB_GetNumInTxFifo(base) + Cy_SCB_GetTxSrValid(base);
2770 
2771         /* Get the number of bytes transferred from the read buffer */
2772         context->slaveTxBufferCnt = (context->slaveTxBufferIdx - size);
2773 
2774         /* Update buffer pointer and its size if there is no overflow */
2775         if (0UL == (CY_SCB_I2C_SLAVE_RD_UNDRFL & context->slaveStatus))
2776         {
2777             context->slaveTxBufferSize += size;
2778             context->slaveTxBuffer     -= size;
2779         }
2780 
2781         locEvents             = (uint32_t)  CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT;
2782         context->slaveStatus |= (uint32_t)  CY_SCB_I2C_SLAVE_RD_CMPLT;
2783         context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_RD_BUSY;
2784 
2785         /* Clean up the TX direction */
2786         Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2787     }
2788 
2789     /* Return scb into the known state after an error */
2790     if (0UL != (CY_SCB_I2C_SLAVE_INTR_ERROR & Cy_SCB_GetSlaveInterruptStatusMasked(base)))
2791     {
2792         /* After scb IP is reset, the interrupt statuses are cleared */
2793         Cy_SCB_FwBlockReset(base);
2794 
2795         locEvents |= CY_SCB_I2C_SLAVE_ERR_EVENT;
2796     }
2797 
2798     /* After a stop or error, set the state to idle */
2799     context->state = CY_SCB_I2C_IDLE;
2800 
2801     /* Call a completion callback if registered */
2802     if (NULL != context->cbEvents)
2803     {
2804         context->cbEvents(locEvents);
2805     }
2806 }
2807 
2808 
2809 /*******************************************************************************
2810 * Function Name: Cy_SCB_I2C_MasterInterrupt
2811 ****************************************************************************//**
2812 *
2813 * This is the interrupt function for the SCB configured in I2C mode as the
2814 * master. This function should be called inside the user-defined interrupt
2815 * service routine to make \ref group_scb_i2c_master_high_level_functions
2816 * functions to work.
2817 *
2818 * \param base
2819 * The pointer to the I2C SCB instance.
2820 *
2821 * \param context
2822 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2823 * by the user. The structure is used during the I2C operation for internal
2824 * configuration and data retention. The user must not modify anything
2825 * in this structure.
2826 *
2827 *******************************************************************************/
Cy_SCB_I2C_MasterInterrupt(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2828 void Cy_SCB_I2C_MasterInterrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2829 {
2830     uint32_t intrCause = Cy_SCB_GetInterruptCause(base);
2831 
2832     /* Check whether the slave is active. It can be addressed during the master set-up transfer */
2833     if (0UL != (CY_SCB_SLAVE_INTR & intrCause))
2834     {
2835         /* Abort the transfer due to slave operation */
2836         if (0UL != SCB_I2C_M_CMD(base))
2837         {
2838             SCB_I2C_M_CMD(base) = 0UL;
2839 
2840             context->masterStatus |= CY_SCB_I2C_MASTER_ABORT_START;
2841         }
2842 
2843         context->state = CY_SCB_I2C_MASTER_CMPLT;
2844     }
2845 
2846     /* Check for master error conditions */
2847     if (0UL != (CY_SCB_MASTER_INTR & intrCause))
2848     {
2849         MasterHandleEvents(base, context);
2850 
2851         /* Any master event does not require further TX processing */
2852         intrCause &= (uint32_t) ~CY_SCB_TX_INTR;
2853     }
2854 
2855     if (0UL != (CY_SCB_RX_INTR & intrCause))
2856     {
2857         MasterHandleDataReceive(base, context);
2858 
2859         Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2860     }
2861 
2862     if (0UL != (CY_SCB_TX_INTR & intrCause))
2863     {
2864         MasterHandleDataTransmit(base, context);
2865 
2866         Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
2867     }
2868 
2869     /* Complete the transfer */
2870     if (CY_SCB_I2C_MASTER_CMPLT == context->state)
2871     {
2872         MasterHandleComplete(base, context);
2873     }
2874 
2875     /* Generate stop to complete transfer */
2876     if (CY_SCB_I2C_MASTER_STOP == context->state)
2877     {
2878         MasterHandleStop(base, context);
2879     }
2880 }
2881 
2882 
2883 /*******************************************************************************
2884 * Function Name: MasterHandleMasterEvents
2885 ****************************************************************************//**
2886 *
2887 * Reads data from RX FIFO into the buffer provided by \ref Cy_SCB_I2C_MasterRead.
2888 *
2889 * \param base
2890 * The pointer to the I2C SCB instance.
2891 *
2892 * \param context
2893 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2894 * by the user. The structure is used during the I2C operation for internal
2895 * configuration and data retention. The user must not modify anything
2896 * in this structure.
2897 *
2898 * \note
2899 * The master CY_SCB_MASTER_INTR_I2C_ACK interrupt source is used for Stop
2900 * generation or request to abort transfer.
2901 *
2902 *******************************************************************************/
MasterHandleEvents(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2903 static void MasterHandleEvents(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2904 {
2905     uint32_t masterIntrStatus = Cy_SCB_GetMasterInterruptStatusMasked(base);
2906 
2907     /* The master has not received the acknowledgment for slave */
2908     if (0UL != (CY_SCB_MASTER_INTR_I2C_NACK & masterIntrStatus))
2909     {
2910         /* Clear NAK interrupt source */
2911         Cy_SCB_ClearMasterInterrupt(base, CY_SCB_MASTER_INTR_I2C_NACK);
2912 
2913         /* Update status to indicate address or data was NACKed */
2914         context->masterStatus |= (0UL != (CY_SCB_MASTER_INTR_I2C_ACK & Cy_SCB_GetMasterInterruptStatus(base))) ?
2915                                             CY_SCB_I2C_MASTER_DATA_NAK : CY_SCB_I2C_MASTER_ADDR_NAK;
2916 
2917         /* Check whether Stop generation was requested before */
2918         if (CY_SCB_I2C_MASTER_WAIT_STOP != context->state)
2919         {
2920             context->state = (context->masterPause) ? CY_SCB_I2C_MASTER_CMPLT : CY_SCB_I2C_MASTER_STOP;
2921         }
2922     }
2923 
2924     /* The master detected a bus error condition */
2925     if (0UL != (CY_SCB_MASTER_INTR_I2C_BUS_ERROR & masterIntrStatus))
2926     {
2927         context->masterStatus |= CY_SCB_I2C_MASTER_BUS_ERR;
2928     }
2929 
2930     /* The master detected an arbitration lost condition */
2931     if (0UL != (CY_SCB_MASTER_INTR_I2C_ARB_LOST & masterIntrStatus))
2932     {
2933         context->masterStatus |= CY_SCB_I2C_MASTER_ARB_LOST;
2934     }
2935 
2936     /* Complete the transfer: stop, bus error or arbitration lost */
2937     if (0UL != (CY_SCB_I2C_MASTER_INTR_CMPLT & masterIntrStatus))
2938     {
2939         context->state = CY_SCB_I2C_MASTER_CMPLT;
2940     }
2941 }
2942 
2943 
2944 /*******************************************************************************
2945 * Function Name: MasterHandleDataReceive
2946 ****************************************************************************//**
2947 *
2948 * Reads data from RX FIFO into the buffer provided by \ref Cy_SCB_I2C_MasterRead.
2949 *
2950 * \param base
2951 * The pointer to the I2C SCB instance.
2952 *
2953 * \param context
2954 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2955 * by the user. The structure is used during the I2C operation for internal
2956 * configuration and data retention. The user must not modify anything
2957 * in this structure.
2958 *
2959 *******************************************************************************/
MasterHandleDataReceive(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2960 static void MasterHandleDataReceive(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2961 {
2962     switch (context->state)
2963     {
2964         case CY_SCB_I2C_MASTER_RX0:
2965         {
2966             /* Put data into the component buffer */
2967             context->masterBuffer[0UL] = (uint8_t) Cy_SCB_ReadRxFifo(base);
2968 
2969             ++context->masterBufferIdx;
2970             --context->masterBufferSize;
2971 
2972             if (context->masterBufferSize > 0UL)
2973             {
2974                 /* Continue the transaction: move pointer send an ACK */
2975                 context->masterBuffer = &context->masterBuffer[1UL];
2976                 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_ACK_Msk;
2977             }
2978             else
2979             {
2980                 /* Complete the transaction */
2981                 context->state = (context->masterPause) ? CY_SCB_I2C_MASTER_CMPLT : CY_SCB_I2C_MASTER_STOP;
2982             }
2983         }
2984         break;
2985 
2986         case CY_SCB_I2C_MASTER_RX1:
2987         {
2988             uint32_t numToCopied;
2989 
2990             /* Get data from RX FIFO */
2991             numToCopied = Cy_SCB_ReadArray(base, context->masterBuffer, context->masterBufferSize);
2992             context->masterBufferIdx  += numToCopied;
2993             context->masterBufferSize -= numToCopied;
2994             context->masterBuffer      = &context->masterBuffer[numToCopied];
2995 
2996             if (context->masterBufferSize < 2UL)
2997             {
2998                 /* Stop ACKing data */
2999                 SCB_I2C_CTRL(base) &= (uint32_t) ~SCB_I2C_CTRL_M_READY_DATA_ACK_Msk;
3000 
3001                 if (1UL == context->masterBufferSize)
3002                 {
3003                     /* Catch the last byte */
3004                     Cy_SCB_SetRxFifoLevel(base, 0UL);
3005 
3006                     context->state = CY_SCB_I2C_MASTER_RX0;
3007                 }
3008                 else
3009                 {
3010                     /* Stop RX processing */
3011                     Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3012 
3013                     context->state = CY_SCB_I2C_MASTER_STOP;
3014                 }
3015             }
3016             else
3017             {
3018                 uint32_t halfFifoSize = CY_SCB_I2C_HALF_FIFO_SIZE;
3019 
3020                 /* Continue the transfer: Adjust the level in RX FIFO */
3021                 Cy_SCB_SetRxFifoLevel(base, (context->masterBufferSize <= halfFifoSize) ?
3022                                             (context->masterBufferSize - 2UL) : (halfFifoSize - 1UL));
3023             }
3024         }
3025         break;
3026 
3027         default:
3028             /* Do nothing: drop data into RX FIFO */
3029         break;
3030     }
3031 }
3032 
3033 
3034 /*******************************************************************************
3035 * Function Name: MasterHandleDataTransmit
3036 ****************************************************************************//**
3037 *
3038 * Loads TX FIFO with data provided by \ref Cy_SCB_I2C_MasterWrite.
3039 *
3040 * \param base
3041 * The pointer to the I2C SCB instance.
3042 *
3043 * \param context
3044 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3045 * by the user. The structure is used during the I2C operation for internal
3046 * configuration and data retention. The user must not modify anything
3047 * in this structure.
3048 *
3049 *******************************************************************************/
MasterHandleDataTransmit(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)3050 static void MasterHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
3051 {
3052     if (CY_SCB_I2C_MASTER_TX_DONE == context->state)
3053     {
3054         context->state = CY_SCB_I2C_MASTER_CMPLT;
3055     }
3056     else if (CY_SCB_I2C_MASTER_TX == context->state)
3057     {
3058         if (context->masterBufferSize > 1UL)
3059         {
3060             /* Get the number of bytes to copy into TX FIFO */
3061             uint32_t NumToCopy = (context->useTxFifo) ? (context->masterBufferSize - 1UL) : (1UL);
3062 
3063             /* Write data into TX FIFO */
3064             NumToCopy = Cy_SCB_WriteArray(base, context->masterBuffer, NumToCopy);
3065             context->masterBufferIdx  += NumToCopy;
3066             context->masterBufferSize -= NumToCopy;
3067             context->masterBuffer      = &context->masterBuffer[NumToCopy];
3068         }
3069 
3070         /* Put the last byte */
3071         if ((CY_SCB_I2C_FIFO_SIZE != Cy_SCB_GetNumInTxFifo(base)) && (1UL == context->masterBufferSize))
3072         {
3073             uint32_t intrStatus;
3074 
3075             /* Put the last data byte in the TX FIFO and clear the TX Underflow
3076             * interrupt source inside the critical section to ensure that the
3077             * TX Underflow interrupt will trigger after all data bytes from the
3078             * TX FIFO are transferred onto the bus.
3079             */
3080             intrStatus = Cy_SysLib_EnterCriticalSection();
3081 
3082             Cy_SCB_WriteTxFifo     (base, (uint32_t) context->masterBuffer[0UL]);
3083             Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
3084 
3085             Cy_SysLib_ExitCriticalSection(intrStatus);
3086 
3087             ++context->masterBufferIdx;
3088             context->masterBufferSize = 0UL;
3089         }
3090 
3091         /* Complete the transfer */
3092         if (0UL == context->masterBufferSize)
3093         {
3094             if (context->masterPause)
3095             {
3096                 /* Wait until data is transferred onto the bus */
3097                 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_UNDERFLOW);
3098 
3099                 context->state = CY_SCB_I2C_MASTER_TX_DONE;
3100             }
3101             else
3102             {
3103                 /* Disable TX processing */
3104                 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3105 
3106                 /* Request Stop generation */
3107                 context->state = CY_SCB_I2C_MASTER_STOP;
3108             }
3109 
3110             if (context->useTxFifo)
3111             {
3112                 /* Notify the user that data is in TX FIFO */
3113                 context->masterStatus |= CY_SCB_I2C_MASTER_WR_IN_FIFO;
3114 
3115                 if (NULL != context->cbEvents)
3116                 {
3117                     context->cbEvents(CY_SCB_I2C_MASTER_WR_IN_FIFO_EVENT);
3118                 }
3119             }
3120         }
3121     }
3122     else
3123     {
3124         /* Do nothing */
3125     }
3126 }
3127 
3128 
3129 /*******************************************************************************
3130 * Function Name: MasterHandleStop
3131 ****************************************************************************//**
3132 *
3133 * Handles the stop condition generation
3134 *
3135 * \param base
3136 * The pointer to the I2C SCB instance.
3137 *
3138 * \param context
3139 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3140 * by the user. The structure is used during the I2C operation for internal
3141 * configuration and data retention. The user must not modify anything
3142 * in this structure.
3143 *
3144 *******************************************************************************/
MasterHandleStop(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)3145 static void MasterHandleStop(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
3146 {
3147     /* Stop RX and TX processing */
3148     Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3149     Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3150 
3151     if (0UL != SCB_I2C_M_CMD(base))
3152     {
3153         /* Enable ACK interrupt source: it triggers after ACK response to
3154         * address was received.
3155         */
3156         Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR_ALL);
3157     }
3158     else
3159     {
3160         /* Disable ACK interrupt source */
3161         Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
3162 
3163         /* Complete transaction generating Stop */
3164         SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
3165         context->state  = CY_SCB_I2C_MASTER_WAIT_STOP;
3166     }
3167 }
3168 
3169 
3170 /*******************************************************************************
3171 * Function Name: MasterHandleComplete
3172 ****************************************************************************//**
3173 *
3174 * Handles the transfer completion on a stop or restart - the normal case or
3175 * completion due to an error on the bus or lost arbitration.
3176 *
3177 * \param base
3178 * The pointer to the I2C SCB instance.
3179 *
3180 * \param context
3181 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3182 * by the user. The structure is used during the I2C operation for internal
3183 * configuration and data retention. The user must not modify anything
3184 * in this structure.
3185 *
3186 *******************************************************************************/
MasterHandleComplete(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)3187 static void MasterHandleComplete(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
3188 {
3189     uint32_t masterIntrStatus = Cy_SCB_GetMasterInterruptStatusMasked(base);
3190 
3191     /* Clean-up hardware */
3192 
3193     /* Disable auto data ACK option */
3194     SCB_I2C_CTRL(base) &= (uint32_t) ~SCB_I2C_CTRL_M_READY_DATA_ACK_Msk;
3195 
3196     /* Disable the interrupt source for master operation */
3197     Cy_SCB_SetRxInterruptMask    (base, CY_SCB_CLEAR_ALL_INTR_SRC);
3198     Cy_SCB_SetTxInterruptMask    (base, CY_SCB_CLEAR_ALL_INTR_SRC);
3199     Cy_SCB_SetMasterInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3200 
3201     Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
3202 
3203     /* Operation complete - master is not busy anymore */
3204     context->masterStatus &= (uint32_t) ~CY_SCB_I2C_MASTER_BUSY;
3205 
3206     /* Get number of byte transferred on the bus */
3207     if (context->masterRdDir)
3208     {
3209         context->masterNumBytes = context->masterBufferIdx;
3210     }
3211     else
3212     {
3213         context->masterNumBytes = context->masterBufferIdx -
3214                     (Cy_SCB_GetNumInTxFifo(base) + Cy_SCB_GetTxSrValid(base));
3215     }
3216 
3217     /* Clean up after a not completed transfer */
3218     if (0UL != (CY_SCB_I2C_MASTER_INTR_ERR & masterIntrStatus))
3219     {
3220         /* Reset the scb IP block when:
3221         *  1. Master mode: Reset IP when arbitration is lost or a bus error occurs.
3222         *  2. Master-Slave mode: Reset IP if it is not the address phase (ACK is 0).
3223         *  Otherwise, reset only on a bus error. If "lost arbitration" happens, the slave
3224         *  can be addressed, so let the slave accept the address.
3225         */
3226 
3227         bool resetIp = true;
3228 
3229         /* Check the Master-Slave address an ACK/NACK */
3230         if (((uint32_t) CY_SCB_I2C_MASTER_SLAVE) == _FLD2VAL(CY_SCB_I2C_CTRL_MODE, SCB_I2C_CTRL(base)))
3231         {
3232             resetIp = ((0UL != (CY_SCB_MASTER_INTR_I2C_ACK & masterIntrStatus)) ? true :
3233                             ((0UL != (CY_SCB_MASTER_INTR_I2C_BUS_ERROR & masterIntrStatus)) ? true : false));
3234         }
3235 
3236         if (resetIp)
3237         {
3238             /* Reset to get it back in an known state */
3239             Cy_SCB_FwBlockReset(base);
3240         }
3241 
3242         /* Back to the idle state. The master is not active anymore */
3243         context->state = CY_SCB_I2C_IDLE;
3244     }
3245     else
3246     {
3247         if (context->useRxFifo)
3248         {
3249             /* Clear RX FIFO from remaining data and level interrupt source */
3250             Cy_SCB_ClearRxFifo(base);
3251             Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
3252         }
3253 
3254         context->state = (context->masterPause) ? CY_SCB_I2C_MASTER_WAIT : CY_SCB_I2C_IDLE;
3255     }
3256 
3257     /* An operation completion callback */
3258     if (NULL != context->cbEvents)
3259     {
3260         /* Get completion events based on the hardware status */
3261         uint32_t locEvents = context->masterRdDir ? CY_SCB_I2C_MASTER_RD_CMPLT_EVENT : CY_SCB_I2C_MASTER_WR_CMPLT_EVENT;
3262 
3263         /* Add errors if any */
3264         locEvents |= (0UL != (CY_SCB_I2C_MASTER_ERR & context->masterStatus)) ? CY_SCB_I2C_MASTER_ERR_EVENT : 0UL;
3265 
3266         context->cbEvents(locEvents);
3267     }
3268 }
3269 
3270 
3271 
3272 /******************************************************************************
3273 * Function Name: WaitOneUnit
3274 ****************************************************************************//**
3275 *
3276 * Waits for one unit before unblock code execution.
3277 * Note that if a timeout value is 0, this function does nothing and returns 0.
3278 *
3279 * \param timeout
3280 * The pointer to a timeout value.
3281 *
3282 * \return
3283 * Returns 0 if a timeout does not expire or the timeout mask.
3284 *
3285 *******************************************************************************/
WaitOneUnit(uint32_t * timeout)3286 static uint32_t WaitOneUnit(uint32_t *timeout)
3287 {
3288     uint32_t status = 0UL;
3289 
3290     /* If the timeout equal to 0. Ignore the timeout */
3291     if (*timeout > 0UL)
3292     {
3293         Cy_SysLib_DelayUs(CY_SCB_WAIT_1_UNIT);
3294         --(*timeout);
3295 
3296         if (0UL == *timeout)
3297         {
3298             status = CY_SCB_I2C_MASTER_TIMEOUT_DONE;
3299         }
3300     }
3301 
3302     return (status);
3303 }
3304 
3305 
3306 /******************************************************************************
3307 * Function Name: HandleStatus
3308 ****************************************************************************//**
3309 *
3310 * Converts passed status into the cy_en_scb_i2c_status_t.
3311 *
3312 * \param base
3313 * The pointer to the I2C SCB instance.
3314 *
3315 * \param status
3316 * The status to covert.
3317 *
3318 * \param context
3319 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3320 * by the user. The structure is used during the I2C operation for internal
3321 * configuration and data retention. The user must not modify anything
3322 * in this structure.
3323 *
3324 * \return
3325 * \ref cy_en_scb_i2c_status_t
3326 *
3327 *******************************************************************************/
HandleStatus(CySCB_Type * base,uint32_t status,cy_stc_scb_i2c_context_t * context)3328 static cy_en_scb_i2c_status_t HandleStatus(CySCB_Type *base, uint32_t status, cy_stc_scb_i2c_context_t *context)
3329 {
3330     cy_en_scb_i2c_status_t retStatus;
3331     bool resetBlock = false;
3332 
3333     /* Convert the master status to the API status */
3334     if (0UL != (CY_SCB_I2C_MASTER_TIMEOUT_DONE & status))
3335     {
3336         retStatus  = CY_SCB_I2C_MASTER_MANUAL_TIMEOUT;
3337         resetBlock = true;
3338     }
3339     else if (0UL != (CY_SCB_I2C_SLAVE_ADDR_DONE & status))
3340     {
3341         /* Abort the master operation, the slave was addressed first */
3342         retStatus = CY_SCB_I2C_MASTER_MANUAL_ABORT_START;
3343 
3344         SCB_I2C_M_CMD(base) = 0UL;
3345         context->state = CY_SCB_I2C_IDLE;
3346     }
3347     else if (0UL != (CY_SCB_MASTER_INTR_I2C_BUS_ERROR & status))
3348     {
3349         retStatus = CY_SCB_I2C_MASTER_MANUAL_BUS_ERR;
3350         resetBlock = true;
3351     }
3352     else if (0UL != (CY_SCB_MASTER_INTR_I2C_ARB_LOST & status))
3353     {
3354         retStatus = CY_SCB_I2C_MASTER_MANUAL_ARB_LOST;
3355 
3356         if (CY_SCB_I2C_MASTER_ADDR == context->state)
3357         {
3358             /* This is the address phase:
3359             *  1. Master mode: Reset IP when "arbitration lost" occurs.
3360             *  2. Master-Slave mode: If "lost arbitration" occurs, the slave
3361             *  can be addressed to let the slave accept the address; do not
3362             *  reset IP.
3363             */
3364             resetBlock = !_FLD2BOOL(SCB_I2C_CTRL_SLAVE_MODE, SCB_I2C_CTRL(base));
3365 
3366             context->state = CY_SCB_I2C_IDLE;
3367         }
3368         else
3369         {
3370             resetBlock = true;
3371         }
3372     }
3373     else if (0UL != (CY_SCB_MASTER_INTR_I2C_NACK & status))
3374     {
3375         /* An address or data was NAKed */
3376         retStatus = (CY_SCB_I2C_MASTER_ADDR == context->state) ?
3377                      CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK : CY_SCB_I2C_MASTER_MANUAL_NAK;
3378     }
3379     else
3380     {
3381         retStatus = CY_SCB_I2C_SUCCESS;
3382 
3383         if (0UL != (CY_SCB_MASTER_INTR_I2C_STOP & status))
3384         {
3385             /* End of transaction, go to idle state */
3386             context->state = CY_SCB_I2C_IDLE;
3387         }
3388         else
3389         {
3390             /* Continue transaction */
3391             if (CY_SCB_I2C_MASTER_ADDR == context->state)
3392             {
3393                 /* Switch from address to data state */
3394                 context->state = (context->masterRdDir) ?
3395                                     CY_SCB_I2C_MASTER_RX0 : CY_SCB_I2C_MASTER_TX;
3396             }
3397         }
3398     }
3399 
3400     if (resetBlock)
3401     {
3402         /* Back block into default state */
3403         Cy_SCB_FwBlockReset(base);
3404 
3405         context->state = CY_SCB_I2C_IDLE;
3406     }
3407     else
3408     {
3409         Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
3410     }
3411 
3412     return (retStatus);
3413 }
3414 
3415 
3416 #if defined(__cplusplus)
3417 }
3418 #endif
3419 
3420 #endif /* (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB)) */
3421 
3422 /* [] END OF FILE */
3423