1 /***************************************************************************//**
2 * \file cy_scb_ezi2c.c
3 * \version 3.10
4 *
5 * Provides EZI2C 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_ezi2c.h"
30 
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34 
35 
36 /***************************************
37 *        Function Prototypes
38 ***************************************/
39 
40 static void HandleErrors      (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
41 static void HandleAddress     (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
42 static void UpdateRxFifoLevel (CySCB_Type *base, uint32_t bufSize);
43 static void HandleDataReceive (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
44 static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
45 static void HandleStop        (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
46 static void UpdateAddressMask (CySCB_Type *base, cy_stc_scb_ezi2c_context_t const *context);
47 
48 
49 /*******************************************************************************
50 * Function Name: Cy_SCB_EZI2C_Init
51 ****************************************************************************//**
52 *
53 * Initializes the SCB for the EZI2C operation.
54 *
55 * \param base
56 * The pointer to the EZI2C SCB instance.
57 *
58 * \param config
59 * The pointer to the configuration structure \ref cy_stc_scb_ezi2c_config_t.
60 *
61 * \param context
62 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
63 * allocated by the user. The structure is used during the EZI2C operation for
64 * internal configuration and data retention. The user must not modify anything
65 * in this structure.
66 *
67 * \return
68 * \ref cy_en_scb_ezi2c_status_t
69 *
70 * \note
71 * Ensure that the SCB block is disabled before calling this function.
72 *
73 *******************************************************************************/
Cy_SCB_EZI2C_Init(CySCB_Type * base,cy_stc_scb_ezi2c_config_t const * config,cy_stc_scb_ezi2c_context_t * context)74 cy_en_scb_ezi2c_status_t Cy_SCB_EZI2C_Init(CySCB_Type *base, cy_stc_scb_ezi2c_config_t const *config,
75                                            cy_stc_scb_ezi2c_context_t *context)
76 {
77     /* Input parameters verification */
78     if ((NULL == base) || (NULL == config) || (NULL == context))
79     {
80         return CY_SCB_EZI2C_BAD_PARAM;
81     }
82 
83     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(config->slaveAddress1));
84     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(config->slaveAddress2));
85     CY_ASSERT_L2(config->slaveAddress1 != config->slaveAddress2);
86     CY_ASSERT_L3(CY_SCB_EZI2C_IS_NUM_OF_ADDR_VALID  (config->numberOfAddresses));
87     CY_ASSERT_L3(CY_SCB_EZI2C_IS_SUB_ADDR_SIZE_VALID(config->subAddressSize));
88 
89     /* Configure the EZI2C interface */
90     SCB_CTRL(base) = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, (config->numberOfAddresses == CY_SCB_EZI2C_TWO_ADDRESSES)) |
91                  _BOOL2FLD(SCB_CTRL_EC_AM_MODE, config->enableWakeFromSleep);
92 #if ((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
93     SCB_CTRL(base) |= SCB_CTRL_BYTE_MODE_Msk;
94 #endif /* CY_IP_MXSCB_VERSION */
95     SCB_I2C_CTRL(base) = CY_SCB_EZI2C_I2C_CTRL;
96 
97     /* Configure the RX direction */
98     SCB_RX_CTRL(base)      = CY_SCB_EZI2C_RX_CTRL;
99     SCB_RX_FIFO_CTRL(base) = 0UL;
100 
101     /* Set the default address and mask */
102     if (config->numberOfAddresses == CY_SCB_EZI2C_ONE_ADDRESS)
103     {
104         context->address2 = 0U;
105         Cy_SCB_EZI2C_SetAddress1(base, config->slaveAddress1, context);
106     }
107     else
108     {
109         Cy_SCB_EZI2C_SetAddress1(base, config->slaveAddress1, context);
110         Cy_SCB_EZI2C_SetAddress2(base, config->slaveAddress2, context);
111     }
112 
113     /* Configure the TX direction */
114     SCB_TX_CTRL(base)      = CY_SCB_EZI2C_TX_CTRL;
115     SCB_TX_FIFO_CTRL(base) = CY_SCB_EZI2C_HALF_FIFO_SIZE;
116 
117     /* Configure the interrupt sources */
118     SCB_INTR_SPI_EC_MASK(base) = 0UL;
119     SCB_INTR_I2C_EC_MASK(base) = 0UL;
120     SCB_INTR_RX_MASK(base)     = 0UL;
121     SCB_INTR_TX_MASK(base)     = 0UL;
122     SCB_INTR_M_MASK(base)      = 0UL;
123     SCB_INTR_S_MASK(base)      = CY_SCB_EZI2C_SLAVE_INTR;
124 
125     /* Initialize the context */
126     context->status = 0UL;
127     context->state  = CY_SCB_EZI2C_STATE_IDLE;
128 
129     context->subAddrSize = config->subAddressSize;
130 
131     context->buf1Size      = 0UL;
132     context->buf1rwBondary = 0UL;
133     context->baseAddr1     = 0UL;
134 
135     context->buf2Size      = 0UL;
136     context->buf2rwBondary = 0UL;
137     context->baseAddr2     = 0UL;
138 
139     return CY_SCB_EZI2C_SUCCESS;
140 }
141 
142 
143 /*******************************************************************************
144 *  Function Name: Cy_SCB_EZI2C_DeInit
145 ****************************************************************************//**
146 *
147 * De-initializes the SCB block, returns the register values to default.
148 *
149 * \param base
150 * The pointer to the EZI2C SCB instance.
151 *
152 * \note
153 * Ensure that the SCB block is disabled before calling this function.
154 *
155 *******************************************************************************/
Cy_SCB_EZI2C_DeInit(CySCB_Type * base)156 void Cy_SCB_EZI2C_DeInit(CySCB_Type *base)
157 {
158     /* Return the block registers into the default state */
159     SCB_CTRL(base)     = CY_SCB_CTRL_DEF_VAL;
160     SCB_I2C_CTRL(base) = CY_SCB_I2C_CTRL_DEF_VAL;
161 
162     SCB_RX_CTRL(base)      = CY_SCB_RX_CTRL_DEF_VAL;
163     SCB_RX_FIFO_CTRL(base) = 0UL;
164     SCB_RX_MATCH(base)     = 0UL;
165 
166     SCB_TX_CTRL(base)      = CY_SCB_TX_CTRL_DEF_VAL;
167     SCB_TX_FIFO_CTRL(base) = 0UL;
168 
169     SCB_INTR_SPI_EC_MASK(base) = 0UL;
170     SCB_INTR_I2C_EC_MASK(base) = 0UL;
171     SCB_INTR_RX_MASK(base)     = 0UL;
172     SCB_INTR_TX_MASK(base)     = 0UL;
173     SCB_INTR_M_MASK(base)      = 0UL;
174     SCB_INTR_S_MASK(base)      = 0UL;
175 }
176 
177 
178 /*******************************************************************************
179 * Function Name: Cy_SCB_EZI2C_Disable
180 ****************************************************************************//**
181 *
182 * Disables the SCB block and clears the context statuses.
183 * Note that after the block is disabled, the TX and RX FIFOs and hardware
184 * statuses are cleared. Also, the hardware stops driving the output and
185 * ignores the input.
186 *
187 * \param base
188 * The pointer to the EZI2C SCB instance.
189 *
190 * \param context
191 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
192 * allocated by the user. The structure is used during the EZI2C operation for
193 * internal configuration and data retention. The user must not modify anything
194 * in this structure.
195 *
196 * \note
197 * Calling this function while EZI2C is busy (the slave has been addressed and is
198 * communicating with the master), may cause transaction corruption because
199 * the hardware stops driving the output and ignores the input. Ensure that
200 * the EZI2C slave is not busy before calling this function.
201 *
202 *******************************************************************************/
Cy_SCB_EZI2C_Disable(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)203 void Cy_SCB_EZI2C_Disable(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
204 {
205     SCB_CTRL(base) &= (uint32_t) ~SCB_CTRL_ENABLED_Msk;
206 
207     /* Set the state to default and clear the statuses */
208     context->status = 0UL;
209     context->state  = CY_SCB_EZI2C_STATE_IDLE;
210 }
211 
212 
213 /*******************************************************************************
214 * Function Name: Cy_SCB_EZI2C_DeepSleepCallback
215 ****************************************************************************//**
216 *
217 * This function handles the transition of the EZI2C SCB into and out of
218 * Deep Sleep mode. It prevents the device from entering Deep Sleep mode if
219 * the EZI2C slave is actively communicating.
220 * The following behavior of the EZI2C depends on whether the SCB block is
221 * wakeup-capable:
222 * * <b>Wakeup-capable</b>: on the incoming EZI2C slave address, the slave
223 *   receives the address and stretches the clock until the device is woken from
224 *   Deep Sleep mode. If the slave address occurs before the device enters
225 *   Deep Sleep mode, the device will not enter Deep Sleep mode.
226 * * <b>Not wakeup-capable</b>: the EZI2C is disabled. It is enabled
227 *   when the device fails to enter Deep Sleep mode or it is woken from Deep Sleep
228 *   mode. While the EZI2C is disabled, it stops driving the outputs and
229 *   ignores the input lines. The slave NACKs all incoming addresses.
230 *
231 * This function must be called during execution of \ref Cy_SysPm_CpuEnterDeepSleep.
232 * To do this, register this function as a callback before calling
233 * \ref Cy_SysPm_CpuEnterDeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
234 * type and call \ref Cy_SysPm_RegisterCallback.
235 *
236 * \param callbackParams
237 * The pointer to the callback parameters structure.
238 * \ref cy_stc_syspm_callback_params_t.
239 *
240 * \param mode
241 * Callback mode, see \ref cy_en_syspm_callback_mode_t
242 *
243 * \return
244 * \ref cy_en_syspm_status_t
245 *
246 * \note
247 * Only applicable for <b>rev-08 of the CY8CKIT-062-BLE</b>.
248 * For proper operation, when the EZI2C slave is configured to be a wakeup source
249 * from Deep Sleep mode, this function must be copied and modified by the user.
250 * The EZI2C clock disable code must be inserted in the
251 * \ref CY_SYSPM_BEFORE_TRANSITION and clock enable code in the
252 * \ref CY_SYSPM_AFTER_TRANSITION mode processing.
253 *
254 *******************************************************************************/
Cy_SCB_EZI2C_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)255 cy_en_syspm_status_t Cy_SCB_EZI2C_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
256 {
257     CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
258     cy_stc_scb_ezi2c_context_t *locContext = (cy_stc_scb_ezi2c_context_t *) callbackParams->context;
259 
260     cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
261 
262     switch (mode)
263     {
264         case CY_SYSPM_CHECK_READY:
265         {
266             /* Disable the slave interrupt sources to protect the state */
267             Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
268 
269             /* If the EZI2C is in the IDLE state, it is ready for Deep Sleep
270             *  mode. Otherwise, it returns fail and restores the slave interrupt
271             * sources.
272             */
273             if (CY_SCB_EZI2C_STATE_IDLE == locContext->state)
274             {
275                 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
276                 {
277                     /* The SCB is wakeup-capable: do not restore the address
278                     * match interrupt source. The next transaction intended
279                     * for the slave will be paused (the SCL is stretched) before
280                     * the address is ACKed because the corresponding interrupt
281                     * source is disabled.
282                     */
283                     Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR_NO_ADDR);
284                 }
285                 else
286                 {
287                     /* The SCB is NOT wakeup-capable: disable the EZI2C.
288                     * The slave stops responding to the master until the
289                     * EZI2C is enabled. This happens when the device fails
290                     * to enter Deep Sleep mode or it is woken from Deep Sleep
291                     * mode.
292                     */
293                     Cy_SCB_EZI2C_Disable(locBase, locContext);
294                     Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
295                 }
296 
297                 retStatus = CY_SYSPM_SUCCESS;
298             }
299             else
300             {
301                 /* Restore the slave interrupt sources */
302                 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
303             }
304         }
305         break;
306 
307         case CY_SYSPM_CHECK_FAIL:
308         {
309             /* The other driver is not ready for Deep Sleep mode. Restore
310             * Active mode configuration.
311             */
312 
313             if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
314             {
315                 /* The SCB is wakeup-capable: restore the slave interrupt
316                 * sources.
317                 */
318                 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
319             }
320             else
321             {
322                 /* The SCB is NOT wakeup-capable: enable the slave to operate. */
323                 Cy_SCB_EZI2C_Enable(locBase);
324             }
325 
326             retStatus = CY_SYSPM_SUCCESS;
327         }
328         break;
329 
330         case CY_SYSPM_BEFORE_TRANSITION:
331         {
332             /* This code executes inside the critical section and enabling the
333             * active interrupt source makes the interrupt pending in the NVIC.
334             * However, the interrupt processing is delayed until the code exists
335             * the critical section. The pending interrupt force WFI instruction
336             * does nothing and the device remains in Active mode.
337             */
338 
339             if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
340             {
341                 /* The SCB is wakeup-capable: enable the I2C wakeup interrupt
342                 * source. If any transaction was paused the the EZI2C interrupt
343                 * becomes pending and prevents entering Deep Sleep mode.
344                 * The transaction continues as soon as the global interrupts
345                 * are enabled.
346                 */
347                 Cy_SCB_SetI2CInterruptMask(locBase, CY_SCB_I2C_INTR_WAKEUP);
348 
349                 /* Disable SCB clock */
350                 SCB_I2C_CFG(locBase) &= (uint32_t) ~CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
351 
352                 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
353                 * for proper entering Deep Sleep mode the I2C clock must be disabled.
354                 * This code must be inserted by the user because the driver
355                 * does not have access to the clock.
356                 */
357             }
358 
359             retStatus = CY_SYSPM_SUCCESS;
360         }
361         break;
362 
363         case CY_SYSPM_AFTER_TRANSITION:
364         {
365             if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
366             {
367                 /* Enable SCB clock */
368                 SCB_I2C_CFG(locBase) |= CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
369 
370                 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
371                 * for proper exiting Deep Sleep mode, the I2C clock must be enabled.
372                 * This code must be inserted by the user because the driver
373                 * does not have access to the clock.
374                 */
375 
376                 /* The SCB is wakeup-capable: disable the I2C wakeup interrupt
377                 * source and restore slave interrupt sources.
378                 */
379                 Cy_SCB_SetI2CInterruptMask  (locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
380                 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
381             }
382             else
383             {
384                 /* The SCB is NOT wakeup-capable: enable the slave to operate */
385                 Cy_SCB_EZI2C_Enable(locBase);
386             }
387 
388             retStatus = CY_SYSPM_SUCCESS;
389         }
390         break;
391 
392         default:
393             /* Unknown state */
394             break;
395     }
396 
397     return (retStatus);
398 }
399 
400 
401 /*******************************************************************************
402 * Function Name: Cy_SCB_EZI2C_HibernateCallback
403 ****************************************************************************//**
404 *
405 * This function handles the transition of the EZI2C SCB block into Hibernate
406 * mode. It prevents the device from entering Hibernate mode if the EZI2C slave
407 * is actively communicating.
408 * If the EZI2C is ready to enter Hibernate mode, it is disabled. If the device
409 * fails to enter Hibernate mode, the EZI2C is enabled. While the EZI2C
410 * is disabled, it stops driving the output and ignores the inputs.
411 * The slave NACKs all incoming addresses.
412 *
413 * This function must be called during execution of \ref Cy_SysPm_SystemEnterHibernate.
414 * To do this, register this function as a callback before calling
415 * \ref Cy_SysPm_SystemEnterHibernate : specify \ref CY_SYSPM_HIBERNATE as the callback
416 * type and call \ref Cy_SysPm_RegisterCallback.
417 *
418 * \param callbackParams
419 * The pointer to the callback parameters structure
420 * \ref cy_stc_syspm_callback_params_t.
421 *
422 * \param mode
423 * Callback mode, see \ref cy_en_syspm_callback_mode_t
424 *
425 * \return
426 * \ref cy_en_syspm_status_t
427 *
428 *******************************************************************************/
Cy_SCB_EZI2C_HibernateCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)429 cy_en_syspm_status_t Cy_SCB_EZI2C_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
430 {
431     CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
432     cy_stc_scb_ezi2c_context_t *locContext = (cy_stc_scb_ezi2c_context_t *) callbackParams->context;
433 
434     cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
435 
436     switch (mode)
437     {
438         case CY_SYSPM_CHECK_READY:
439         {
440             /* Disable the slave interrupt sources to protect the state */
441             Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
442 
443             /* If the EZI2C is in the IDLE state, it is ready for Hibernate mode.
444             * Otherwise, returns fail and restores the slave interrupt sources.
445             */
446             if (CY_SCB_EZI2C_STATE_IDLE == locContext->state)
447             {
448                 /* Disable the EZI2C. It stops responding to the master until
449                 * the EZI2C is enabled. This happens if the device fails to
450                 * enter Hibernate mode.
451                 */
452                 Cy_SCB_EZI2C_Disable(locBase, locContext);
453 
454                 retStatus = CY_SYSPM_SUCCESS;
455             }
456 
457             /* Restore the slave interrupt sources */
458             Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
459         }
460         break;
461 
462         case CY_SYSPM_CHECK_FAIL:
463         {
464             /* The other driver is not ready for Hibernate mode. Restore the
465             * Active mode configuration.
466             */
467 
468             /* Enable the slave to operate */
469             Cy_SCB_EZI2C_Enable(locBase);
470 
471             retStatus = CY_SYSPM_SUCCESS;
472         }
473         break;
474 
475         case CY_SYSPM_BEFORE_TRANSITION:
476         case CY_SYSPM_AFTER_TRANSITION:
477         {
478             /* The SCB is not capable of waking up from Hibernate mode: do nothing */
479             retStatus = CY_SYSPM_SUCCESS;
480         }
481         break;
482 
483         default:
484         /* Unknown state */
485         break;
486     }
487 
488     return (retStatus);
489 }
490 
491 
492 /*******************************************************************************
493 * Function Name: Cy_SCB_EZI2C_GetActivity
494 ****************************************************************************//**
495 *
496 * Returns a non-zero value if an I2C Read or Write cycle has occurred since the
497 * last time this function was called. All flags are reset to zero at the end of
498 * this function call, except the \ref CY_SCB_EZI2C_STATUS_BUSY.
499 *
500 * \param base
501 * The pointer to the EZI2C SCB instance.
502 *
503 * \param context
504 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
505 * allocated by the user. The structure is used during the EZI2C operation for
506 * internal configuration and data retention. The user must not modify anything
507 * in this structure.
508 *
509 * \return
510 * \ref group_scb_ezi2c_macros_get_activity.
511 *
512 *******************************************************************************/
Cy_SCB_EZI2C_GetActivity(CySCB_Type const * base,cy_stc_scb_ezi2c_context_t * context)513 uint32_t Cy_SCB_EZI2C_GetActivity(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t *context)
514 {
515     uint32_t intrState;
516     uint32_t retStatus;
517 
518     /* Suppress a compiler warning about unused variables */
519     (void) base;
520 
521     intrState = Cy_SysLib_EnterCriticalSection();
522 
523     retStatus = context->status;
524     context->status &= CY_SCB_EZI2C_STATUS_BUSY;
525 
526     Cy_SysLib_ExitCriticalSection(intrState);
527 
528     return (retStatus);
529 }
530 
531 
532 /*******************************************************************************
533 * Function Name: Cy_SCB_EZI2C_SetAddress1
534 ****************************************************************************//**
535 *
536 * Sets the primary EZI2C slave address.
537 *
538 * \param base
539 * The pointer to the EZI2C SCB instance.
540 *
541 * \param addr
542 * The 7-bit right justified slave address.
543 *
544 * \param context
545 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
546 * allocated by the user. The structure is used during the EZI2C operation for
547 * internal configuration and data retention. The user must not modify anything
548 * in this structure.
549 *
550 *******************************************************************************/
Cy_SCB_EZI2C_SetAddress1(CySCB_Type * base,uint8_t addr,cy_stc_scb_ezi2c_context_t * context)551 void Cy_SCB_EZI2C_SetAddress1(CySCB_Type *base, uint8_t addr, cy_stc_scb_ezi2c_context_t *context)
552 {
553     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(addr));
554     CY_ASSERT_L2(addr != context->address2);
555 
556     context->address1 = addr;
557 
558     CY_REG32_CLR_SET(SCB_RX_MATCH(base), SCB_RX_MATCH_ADDR, ((uint32_t)((uint32_t) addr << 1UL)));
559 
560     UpdateAddressMask(base, context);
561 }
562 
563 
564 /*******************************************************************************
565 * Function Name: Cy_SCB_EZI2C_GetAddress1
566 ****************************************************************************//**
567 *
568 * Returns the primary the EZI2C slave address.
569 *
570 * \param base
571 * The pointer to the EZI2C SCB instance.
572 *
573 * * \param context
574 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
575 * allocated by the user. The structure is used during the EZI2C operation for
576 * internal configuration and data retention. The user must not modify anything
577 * in this structure.
578 *
579 * \return
580 * The 7-bit right justified slave address.
581 *
582 *******************************************************************************/
Cy_SCB_EZI2C_GetAddress1(CySCB_Type const * base,cy_stc_scb_ezi2c_context_t const * context)583 uint32_t Cy_SCB_EZI2C_GetAddress1(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t const *context)
584 {
585     /* Suppress a compiler warning about unused variables */
586     (void) base;
587 
588     return ((uint32_t) context->address1);
589 }
590 
591 
592 /*******************************************************************************
593 * Function Name: Cy_SCB_EZI2C_SetBuffer1
594 ****************************************************************************//**
595 *
596 * Sets up the data buffer to be exposed to the I2C master on the primary slave
597 * address request.
598 *
599 * \param base
600 * The pointer to the EZI2C SCB instance.
601 *
602 * \param buffer
603 * The pointer to the data buffer.
604 *
605 * \param size
606 * The size of the buffer in bytes.
607 *
608 * \param rwBoundary
609 * The number of data bytes starting from the beginning of the buffer with Read and
610 * Write access. The data bytes located at rwBoundary or greater are read only.
611 *
612 * \param context
613 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
614 * allocated by the user. The structure is used during the EZI2C operation for
615 * internal configuration and data retention. The user must not modify anything
616 * in this structure.
617 *
618 * \note
619 * * This function is not interrupt-protected and to prevent a race condition,
620 *   it must be protected from the EZI2C interruption in the place where it
621 *   is called.
622 * * Calling this function in the middle of a transaction intended for the
623 *   secondary slave address leads to unexpected behavior.
624 *
625 *******************************************************************************/
Cy_SCB_EZI2C_SetBuffer1(CySCB_Type const * base,uint8_t * buffer,uint32_t size,uint32_t rwBoundary,cy_stc_scb_ezi2c_context_t * context)626 void Cy_SCB_EZI2C_SetBuffer1(CySCB_Type const *base, uint8_t *buffer, uint32_t size, uint32_t rwBoundary,
627                              cy_stc_scb_ezi2c_context_t *context)
628 {
629     CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
630     CY_ASSERT_L2(rwBoundary <= size);
631 
632     /* Suppress a compiler warning about unused variables */
633     (void) base;
634 
635     context->buf1          = buffer;
636     context->buf1Size      = size;
637     context->buf1rwBondary = rwBoundary;
638 }
639 
640 
641 /*******************************************************************************
642 * Function Name: Cy_SCB_EZI2C_SetAddress2
643 ****************************************************************************//**
644 *
645 * Sets the secondary EZI2C slave address.
646 *
647 * \param base
648 * The pointer to the EZI2C SCB instance.
649 *
650 * \param addr
651 * The 7-bit right justified slave address.
652 *
653 * \param context
654 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
655 * allocated by the user. The structure is used during the EZI2C operation for
656 * internal configuration and data retention. The user must not modify anything
657 * in this structure.
658 *
659 * \note
660 * Calling this function when the EZI2C slave is configured for one-address
661 * operation leads to unexpected behavior because it updates the address mask.
662 *
663 *******************************************************************************/
Cy_SCB_EZI2C_SetAddress2(CySCB_Type * base,uint8_t addr,cy_stc_scb_ezi2c_context_t * context)664 void Cy_SCB_EZI2C_SetAddress2(CySCB_Type *base, uint8_t addr, cy_stc_scb_ezi2c_context_t *context)
665 {
666     CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(addr));
667     CY_ASSERT_L2(addr != context->address1);
668 
669     context->address2 = addr;
670 
671     UpdateAddressMask(base, context);
672 }
673 
674 
675 /*******************************************************************************
676 * Function Name: Cy_SCB_EZI2C_GetAddress2
677 ****************************************************************************//**
678 *
679 * Returns the secondary EZI2C slave address.
680 *
681 * \param base
682 * The pointer to the EZI2C SCB instance.
683 *
684 * \param context
685 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
686 * allocated by the user. The structure is used during the EZI2C operation for
687 * internal configuration and data retention. The user must not modify anything
688 * in this structure.
689 *
690 * \return
691 * The 7-bit right justified slave address.
692 *
693 *******************************************************************************/
Cy_SCB_EZI2C_GetAddress2(CySCB_Type const * base,cy_stc_scb_ezi2c_context_t const * context)694 uint32_t Cy_SCB_EZI2C_GetAddress2(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t const *context)
695 {
696     /* Suppress a compiler warning about unused variables */
697     (void) base;
698 
699     return ((uint32_t) context->address2);
700 }
701 
702 
703 /*******************************************************************************
704 * Function Name: Cy_SCB_EZI2C_SetBuffer2
705 ****************************************************************************//**
706 *
707 * Sets up the data buffer to be exposed to the I2C master on the secondary
708 * slave address request.
709 *
710 * \param base
711 * The pointer to the EZI2C SCB instance.
712 *
713 * \param buffer
714 * The pointer to the data buffer.
715 *
716 * \param size
717 * The size of the buffer in bytes.
718 *
719 * \param rwBoundary
720 * The number of data bytes starting from the beginning of the buffer with Read and
721 * Write access. The data bytes located at rwBoundary or greater are read only.
722 *
723 * \param context
724 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
725 * allocated by the user. The structure is used during the EZI2C operation for
726 * internal configuration and data retention. The user must not modify anything
727 * in this structure.
728 *
729 * \note
730 * * This function is not interrupt-protected. To prevent a race condition,
731 *   it must be protected from the EZI2C interruption in the place where it
732 *   is called.
733 * * Calling this function in the middle of a transaction intended for the
734 *   secondary slave address leads to unexpected behavior.
735 *
736 *******************************************************************************/
Cy_SCB_EZI2C_SetBuffer2(CySCB_Type const * base,uint8_t * buffer,uint32_t size,uint32_t rwBoundary,cy_stc_scb_ezi2c_context_t * context)737 void Cy_SCB_EZI2C_SetBuffer2(CySCB_Type const *base, uint8_t *buffer, uint32_t size, uint32_t rwBoundary,
738                              cy_stc_scb_ezi2c_context_t *context)
739 {
740     CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
741     CY_ASSERT_L2(rwBoundary <= size);
742 
743     /* Suppress a compiler warning about unused variables */
744     (void) base;
745 
746     context->buf2          = buffer;
747     context->buf2Size      = size;
748     context->buf2rwBondary = rwBoundary;
749 }
750 
751 
752 /*******************************************************************************
753 * Function Name: Cy_SCB_EZI2C_Interrupt
754 ****************************************************************************//**
755 *
756 * This is the interrupt function for the SCB configured in the EZI2C mode.
757 * This function must be called inside the user-defined interrupt service
758 * routine to make the EZI2C slave work.
759 *
760 * \param base
761 * The pointer to the EZI2C SCB instance.
762 *
763 * \param context
764 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
765 * by the user. The structure is used during the EZI2C operation for internal
766 * configuration and data retention. The user must not modify anything
767 * in this structure.
768 *
769 *******************************************************************************/
Cy_SCB_EZI2C_Interrupt(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)770 void Cy_SCB_EZI2C_Interrupt(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
771 {
772     uint32_t slaveIntrStatus;
773 
774     /* Handle an I2C wake-up event */
775     if (0UL != (CY_SCB_I2C_INTR_WAKEUP & Cy_SCB_GetI2CInterruptStatusMasked(base)))
776     {
777         /* Move from IDLE state, the slave was addressed. Following address match
778         * interrupt continue transfer.
779         */
780         context->state = CY_SCB_EZI2C_STATE_ADDR;
781 
782         Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
783     }
784 
785     /* Get the slave interrupt sources */
786     slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
787 
788     /* Handle the error conditions */
789     if (0UL != (CY_SCB_EZI2C_SLAVE_INTR_ERROR & slaveIntrStatus))
790     {
791         HandleErrors(base, context);
792 
793         Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_EZI2C_SLAVE_INTR_ERROR);
794 
795         /* Trigger the stop handling to complete the transaction */
796         slaveIntrStatus |= CY_SCB_SLAVE_INTR_I2C_STOP;
797     }
798     else
799     {
800         if ((CY_SCB_EZI2C_STATE_RX_DATA1 == context->state) &&
801             (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus)))
802         {
803             /* Get data from the RX FIFO after Stop is generated */
804             Cy_SCB_SetRxInterrupt    (base, CY_SCB_RX_INTR_LEVEL);
805             Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
806         }
807     }
808 
809     /* Handle the receive direction (master writes data) */
810     if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
811     {
812         HandleDataReceive(base, context);
813 
814         Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
815     }
816 
817     /* Handle the transaction completion */
818     if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
819     {
820         HandleStop(base, context);
821 
822         Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);
823 
824         /* Update the slave interrupt status */
825         slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
826     }
827 
828     /* Handle the address byte */
829     if (0UL != (CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH & slaveIntrStatus))
830     {
831         HandleAddress(base, context);
832 
833         Cy_SCB_ClearI2CInterrupt  (base, CY_SCB_I2C_INTR_WAKEUP);
834         Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH);
835     }
836 
837     /* Handle the transmit direction (master reads data) */
838     if (0UL != (CY_SCB_TX_INTR_LEVEL & Cy_SCB_GetTxInterruptStatusMasked(base)))
839     {
840         HandleDataTransmit(base, context);
841 
842         Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
843     }
844 }
845 
846 
847 
848 /*******************************************************************************
849 * Function Name: HandleErrors
850 ****************************************************************************//**
851 *
852 * Handles an error conditions.
853 *
854 * \param base
855 * The pointer to the EZI2C SCB instance.
856 *
857 * \param context
858 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
859 * by the user. The structure is used during the EZI2C operation for internal
860 * configuration and data retention. The user must not modify anything
861 * in this structure.
862 *
863 *******************************************************************************/
HandleErrors(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)864 static void HandleErrors(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
865 {
866     context->status |= CY_SCB_EZI2C_STATUS_ERR;
867 
868     /* Drop any data available in the RX FIFO */
869     Cy_SCB_ClearRxFifo(base);
870 
871     /* Stop the TX and RX processing */
872     Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
873     Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
874 }
875 
876 
877 /*******************************************************************************
878 * Function Name: HandleAddress
879 ****************************************************************************//**
880 *
881 * Prepares the EZI2C slave for the following read or write transfer after the
882 * matched address was received.
883 *
884 * \param base
885 * The pointer to the EZI2C SCB instance.
886 *
887 * \param context
888 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
889 * by the user. The structure is used during the EZI2C operation for internal
890 * configuration and data retention. The user must not modify anything
891 * in this structure.
892 *
893 *******************************************************************************/
HandleAddress(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)894 static void HandleAddress(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
895 {
896     /* Default actions: ACK address 1 */
897     uint32_t cmd = SCB_I2C_S_CMD_S_ACK_Msk;
898     context->addr1Active = true;
899 
900     if (0U != context->address2)
901     {
902         /* Get an address from the RX FIFO and make it a 7-bit address */
903         uint32_t address = (Cy_SCB_ReadRxFifo(base) >> 1UL);
904         Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
905 
906         /* Decide whether the address matches */
907         if ((address == context->address1) || (address == context->address2))
908         {
909             /* ACK the address */
910             if (address == context->address2)
911             {
912                 context->addr1Active = false;
913             }
914 
915             /* Clear and enable the stop interrupt source */
916             Cy_SCB_ClearSlaveInterrupt  (base, CY_SCB_SLAVE_INTR_I2C_STOP);
917             Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_EZI2C_SLAVE_INTR);
918         }
919         else
920         {
921             /* NACK the address */
922             cmd = SCB_I2C_S_CMD_S_NACK_Msk;
923 
924             /* Disable the stop interrupt source */
925             Cy_SCB_SetI2CInterruptMask(base, CY_SCB_EZI2C_SLAVE_INTR_NO_STOP);
926         }
927     }
928 
929     /* Clear the TX FIFO before continuing the transaction */
930     Cy_SCB_ClearTxFifo(base);
931 
932     /* Set the command to an ACK or NACK address */
933     SCB_I2C_S_CMD(base) = cmd;
934 
935     if (cmd == SCB_I2C_S_CMD_S_ACK_Msk)
936     {
937         context->status |= CY_SCB_EZI2C_STATUS_BUSY;
938 
939         /* Prepare for a transaction */
940         if (_FLD2BOOL(SCB_I2C_STATUS_S_READ, SCB_I2C_STATUS(base)))
941         {
942             /* The master reads data from the slave */
943             context->state = CY_SCB_EZI2C_STATE_TX_DATA;
944 
945             /* Prepare the buffer for transmit */
946             if (context->addr1Active)
947             {
948                 context->curBuf  = &context->buf1[context->baseAddr1];
949                 context->bufSize = context->buf1Size - context->baseAddr1;
950             }
951             else
952             {
953                 context->curBuf  = &context->buf2[context->baseAddr2];
954                 context->bufSize = context->buf2Size - context->baseAddr2;
955             }
956 
957             Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
958         }
959         else
960         {
961             /* The master writes data into the slave */
962             context->state = CY_SCB_EZI2C_STATE_RX_OFFSET_MSB;
963 
964             context->bufSize = ((context->addr1Active) ? context->buf1Size : context->buf2Size);
965 
966             Cy_SCB_SetRxFifoLevel    (base, 0UL);
967             Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
968         }
969     }
970 }
971 
972 
973 /*******************************************************************************
974 * Function Name: HandleDataReceive
975 ****************************************************************************//**
976 *
977 * Updates the RX FIFO level to trigger the next read from it. It also manages
978 * the auto-data NACK feature.
979 *
980 * \param base
981 * The pointer to the EZI2C SCB instance.
982 *
983 * \param bufSize
984 * The size of the buffer in bytes.
985 *
986 *******************************************************************************/
UpdateRxFifoLevel(CySCB_Type * base,uint32_t bufSize)987 static void UpdateRxFifoLevel(CySCB_Type *base, uint32_t bufSize)
988 {
989     uint32_t level;
990     uint32_t fifoSize = CY_SCB_EZI2C_FIFO_SIZE;
991 
992     if (bufSize > fifoSize)
993     {
994         /* Continue the transaction: there is space in the buffer */
995         level = (bufSize - fifoSize);
996         level = ((level > fifoSize) ? (fifoSize / 2UL) : level) - 1UL;
997     }
998     else
999     {
1000         /* Prepare to end the transaction: after the FIFO becomes full, NACK the next byte.
1001         * The NACKed byte is dropped by the hardware.
1002         */
1003         SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
1004 
1005         level = ((bufSize == 0UL) ? (0UL) : (bufSize - 1UL));
1006         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1007     }
1008 
1009     Cy_SCB_SetRxFifoLevel(base, level);
1010 }
1011 
1012 
1013 /*******************************************************************************
1014 * Function Name: HandleDataReceive
1015 ****************************************************************************//**
1016 *
1017 * Handles the data read from the RX FIFO.
1018 *
1019 * \param base
1020 * The pointer to the EZI2C SCB instance.
1021 *
1022 * \param context
1023 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1024 * by the user. The structure is used during the EZI2C operation for internal
1025 * configuration and data retention. The user must not modify anything
1026 * in this structure.
1027 *
1028 *******************************************************************************/
HandleDataReceive(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)1029 static void HandleDataReceive(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
1030 {
1031     switch(context->state)
1032     {
1033         case CY_SCB_EZI2C_STATE_RX_OFFSET_MSB:
1034         case CY_SCB_EZI2C_STATE_RX_OFFSET_LSB:
1035         {
1036             /* Default actions: compare the base address and ACK it */
1037             bool checkBaseAddr = true;
1038 
1039             /* Get the base address from the RX FIFO */
1040             uint32_t baseAddr = Cy_SCB_ReadRxFifo(base);
1041 
1042             if (context->subAddrSize == CY_SCB_EZI2C_SUB_ADDR16_BITS)
1043             {
1044                 if (context->state == CY_SCB_EZI2C_STATE_RX_OFFSET_MSB)
1045                 {
1046                     /* ACK base address MSB */
1047                     SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_ACK_Msk;
1048 
1049                     /* Temporary store base address MSB */
1050                     context->idx = (uint32_t) (baseAddr << 8UL);
1051 
1052                     /* Do not compare until 16 bits are received */
1053                     checkBaseAddr = false;
1054                     context->state = CY_SCB_EZI2C_STATE_RX_OFFSET_LSB;
1055                 }
1056                 else
1057                 {
1058                     /* Get the base address (MSB | LSB) */
1059                     baseAddr |= context->idx;
1060                 }
1061             }
1062 
1063             /* Check whether the received base address is valid */
1064             if (checkBaseAddr)
1065             {
1066                 uint32_t cmd = SCB_I2C_S_CMD_S_ACK_Msk;
1067 
1068                 /* Decide whether the base address within the buffer range */
1069                 if (baseAddr < context->bufSize)
1070                 {
1071                     /* Accept the new base address */
1072                     if (context->addr1Active)
1073                     {
1074                         context->baseAddr1 = baseAddr;
1075                     }
1076                     else
1077                     {
1078                         context->baseAddr2 = baseAddr;
1079                     }
1080 
1081                     /* Store the base address to use it later */
1082                     context->idx = baseAddr;
1083                 }
1084                 else
1085                 {
1086                     /* Restore the valid base address */
1087                     context->idx = ((context->addr1Active) ? context->baseAddr1 : context->baseAddr2);
1088 
1089                     /* The base address is out of range - NACK it */
1090                     cmd = SCB_I2C_S_CMD_S_NACK_Msk;
1091                 }
1092 
1093                 /* Set the command to an ACK or NACK address */
1094                 SCB_I2C_S_CMD(base) = cmd;
1095 
1096                 if (cmd == SCB_I2C_S_CMD_S_ACK_Msk)
1097                 {
1098                     /* Prepare the buffer for a write */
1099                     if (context->addr1Active)
1100                     {
1101                         context->curBuf  = &context->buf1[context->baseAddr1];
1102                         context->bufSize = ((context->baseAddr1 < context->buf1rwBondary) ?
1103                                                     (context->buf1rwBondary - context->baseAddr1) : (0UL));
1104                     }
1105                     else
1106                     {
1107                         context->curBuf  = &context->buf2[context->baseAddr2];
1108                         context->bufSize = ((context->baseAddr2 < context->buf2rwBondary) ?
1109                                                     (context->buf2rwBondary - context->baseAddr2) : (0UL));
1110                     }
1111 
1112                     /* Choice receive scheme  */
1113                     if ((0U != context->address2) || (context->bufSize < CY_SCB_EZI2C_FIFO_SIZE))
1114                     {
1115                         /* Handle each byte separately */
1116                         context->state = CY_SCB_EZI2C_STATE_RX_DATA0;
1117                     }
1118                     else
1119                     {
1120                         /* Use the RX FIFO and the auto-ACK/NACK features */
1121                         SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_READY_DATA_ACK_Msk;
1122                         UpdateRxFifoLevel(base, context->bufSize);
1123 
1124                         context->state = CY_SCB_EZI2C_STATE_RX_DATA1;
1125                     }
1126                 }
1127             }
1128         }
1129         break;
1130 
1131         case CY_SCB_EZI2C_STATE_RX_DATA0:
1132         {
1133             uint32_t byte = Cy_SCB_ReadRxFifo(base);
1134 
1135             /* Check whether there is space to store the byte */
1136             if (context->bufSize > 0UL)
1137             {
1138                 /* Continue the transfer: send an ACK */
1139                 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_ACK_Msk;
1140 
1141                 /* Store the byte in the buffer */
1142                 context->curBuf[0UL] = (uint8_t) byte;
1143                 context->bufSize--;
1144                 context->curBuf++;
1145 
1146                 /* Update the base address to notice that the buffer is modified */
1147                 context->idx++;
1148             }
1149             else
1150             {
1151                 /* Finish the transfer: send a NACK. Drop the received byte */
1152                 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_NACK_Msk;
1153                 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1154             }
1155         }
1156         break;
1157 
1158         case CY_SCB_EZI2C_STATE_RX_DATA1:
1159         {
1160             /* Get the number of bytes to read from the RX FIFO */
1161             uint32_t numToCopy = Cy_SCB_GetRxFifoLevel(base) + 1UL;
1162 
1163             /* Get data from the RX FIFO */
1164             numToCopy = Cy_SCB_ReadArray(base, context->curBuf, numToCopy);
1165             context->bufSize -= numToCopy;
1166             context->curBuf  += numToCopy;
1167 
1168             /* Configure the next RX FIFO read event */
1169             UpdateRxFifoLevel(base, context->bufSize);
1170 
1171             /* Update the base address to notice that the buffer is modified */
1172             context->idx++;
1173         }
1174         break;
1175 
1176         default:
1177         /* Unknown state */
1178         break;
1179     }
1180 }
1181 
1182 
1183 /*******************************************************************************
1184 * Function Name: HandleDataTransmit
1185 ****************************************************************************//**
1186 *
1187 * Loads the TX FIFO with data from the buffer.
1188 *
1189 * \param base
1190 * The pointer to the EZI2C SCB instance.
1191 *
1192 * \param context
1193 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1194 * by the user. The structure is used during the EZI2C operation for internal
1195 * configuration and data retention. The user must not modify anything
1196 * in this structure.
1197 *
1198 *******************************************************************************/
HandleDataTransmit(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)1199 static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
1200 {
1201     if (context->bufSize > 0UL)
1202     {
1203         /* Write data into the TX FIFO from the buffer */
1204         uint32_t numToCopy = Cy_SCB_WriteArray(base, context->curBuf, context->bufSize);
1205         context->bufSize  -= numToCopy;
1206         context->curBuf   += numToCopy;
1207     }
1208 
1209     if (0UL == context->bufSize)
1210     {
1211         /* Write the default bytes into the TX FIFO */
1212         (void) Cy_SCB_WriteDefaultArray(base, CY_SCB_EZI2C_DEFAULT_TX, CY_SCB_EZI2C_FIFO_SIZE);
1213     }
1214 }
1215 
1216 
1217 /*******************************************************************************
1218 * Function Name: HandleStop
1219 ****************************************************************************//**
1220 *
1221 * Handles the transfer completion.
1222 * It is triggered by a Stop or Restart condition on the bus.
1223 *
1224 * \param base
1225 * The pointer to the EZI2C SCB instance.
1226 *
1227 * \param context
1228 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1229 * by the user. The structure is used during the EZI2C operation for internal
1230 * configuration and data retention. The user must not modify anything
1231 * in this structure.
1232 *
1233 *******************************************************************************/
HandleStop(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)1234 static void HandleStop(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
1235 {
1236     /* Check for errors */
1237     if (0UL != (CY_SCB_EZI2C_STATUS_ERR & context->status))
1238     {
1239         /* Re-enable the SCB to recover from errors */
1240         Cy_SCB_FwBlockReset(base);
1241     }
1242 
1243     /* Clean up the hardware to be ready for the next transaction */
1244     if (CY_SCB_EZI2C_STATE_TX_DATA == context->state)
1245     {
1246         Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1247     }
1248     else
1249     {
1250         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1251 
1252         SCB_I2C_CTRL(base) &= (uint32_t) ~(SCB_I2C_CTRL_S_READY_DATA_ACK_Msk |
1253                                            SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk);
1254     }
1255 
1256     /* Update the statuses */
1257     context->status &= (uint32_t) ~CY_SCB_EZI2C_STATUS_BUSY;
1258 
1259     if (context->addr1Active)
1260     {
1261         context->status |= ((CY_SCB_EZI2C_STATE_TX_DATA == context->state) ? CY_SCB_EZI2C_STATUS_READ1 :
1262                              ((context->baseAddr1 != context->idx) ?  CY_SCB_EZI2C_STATUS_WRITE1 : 0UL));
1263     }
1264     else
1265     {
1266         context->status |= ((CY_SCB_EZI2C_STATE_TX_DATA == context->state) ? CY_SCB_EZI2C_STATUS_READ2 :
1267                              ((context->baseAddr2 != context->idx) ? CY_SCB_EZI2C_STATUS_WRITE2 : 0UL));
1268     }
1269 
1270     /* Back to the idle state */
1271     context->state = CY_SCB_EZI2C_STATE_IDLE;
1272 }
1273 
1274 
1275 /*******************************************************************************
1276 * Function Name: UpdateAddressMask
1277 ****************************************************************************//**
1278 *
1279 * Updates the slave address mask to enable the SCB hardware to receive matching
1280 * slave addresses.
1281 *
1282 * \param base
1283 * The pointer to the EZI2C SCB instance.
1284 *
1285 * \param context
1286 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1287 * by the user. The structure is used during the EZI2C operation for internal
1288 * configuration and data retention. The user must not modify anything
1289 * in this structure.
1290 *
1291 *******************************************************************************/
UpdateAddressMask(CySCB_Type * base,cy_stc_scb_ezi2c_context_t const * context)1292 static void UpdateAddressMask(CySCB_Type *base, cy_stc_scb_ezi2c_context_t const *context)
1293 {
1294     uint32_t addrMask;
1295 
1296     /* Check how many addresses are used: */
1297     if (0U != context->address2)
1298     {
1299         /* If (addr1 and addr2) bits match - mask bit equals 1; otherwise 0 */
1300         addrMask  = (uint32_t) ~((uint32_t) context->address1 ^ (uint32_t) context->address2);
1301     }
1302     else
1303     {
1304         addrMask = CY_SCB_EZI2C_ONE_ADDRESS_MASK;
1305     }
1306 
1307     /* Update the hardware address match */
1308     CY_REG32_CLR_SET(SCB_RX_MATCH(base), SCB_RX_MATCH_MASK, ((uint32_t) addrMask << 1UL));
1309 }
1310 
1311 
1312 #if defined(__cplusplus)
1313 }
1314 #endif
1315 
1316 #endif /* (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB)) */
1317 
1318 /* [] END OF FILE */
1319