1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_i2s.h"
10 #include "fsl_flexcomm.h"
11 #include <string.h>
12 
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2s"
20 #endif
21 
22 /* TODO - absent in device header files, should be there */
23 #define I2S_FIFOCFG_TXI2SE0_MASK  (0x4U)
24 #define I2S_FIFOCFG_TXI2SE0_SHIFT (2U)
25 #define I2S_FIFOCFG_TXI2SE0(x)    (((uint32_t)(((uint32_t)(x)) << I2S_FIFOCFG_TXI2SE0_SHIFT)) & I2S_FIFOCFG_TXI2SE0_MASK)
26 #define I2S_FIFOCFG_PACK48_MASK   (0x8U)
27 #define I2S_FIFOCFG_PACK48_SHIFT  (3U)
28 #define I2S_FIFOCFG_PACK48(x)     (((uint32_t)(((uint32_t)(x)) << I2S_FIFOCFG_PACK48_SHIFT)) & I2S_FIFOCFG_PACK48_MASK)
29 /*! @brief i2s empty tx fifo timeout value */
30 #define I2S_FIFO_DEPTH                   (8U)
31 #define I2S_TX_ONE_SAMPLE_MAX_TIMEOUT    (125U) /* 8K/8bit one sample need 125us*/
32 #define I2S_TX_FIFO_EMPTY_TIMEOUT(count) (count) * I2S_TX_ONE_SAMPLE_MAX_TIMEOUT
33 /*! @brief _i2s_state I2S states. */
34 enum
35 {
36     kI2S_StateIdle = 0x0,             /*!< Not performing transfer */
37     kI2S_StateTx,                     /*!< Performing transmit */
38     kI2S_StateTxWaitToWriteDummyData, /*!< Wait on FIFO in order to write final dummy data there */
39     kI2S_StateTxWaitForEmptyFifo,     /*!< Wait for FIFO to be flushed */
40     kI2S_StateRx,                     /*!< Performing receive */
41 };
42 
43 /*******************************************************************************
44  * Prototypes
45  ******************************************************************************/
46 
47 static void I2S_Config(I2S_Type *base, const i2s_config_t *config);
48 static void I2S_TxEnable(I2S_Type *base, bool enable);
49 static void I2S_RxEnable(I2S_Type *base, bool enable);
50 static status_t I2S_ValidateBuffer(i2s_handle_t *handle, i2s_transfer_t *transfer);
51 
52 /*******************************************************************************
53  * Variables
54  ******************************************************************************/
55 
56 /*! @brief Array to map i2c instance number to base address. */
57 static const uint32_t s_i2sBaseAddrs[] = I2S_BASE_ADDRS;
58 
59 /*! @brief IRQ name array */
60 static const IRQn_Type s_i2sIRQ[] = I2S_IRQS;
61 
62 /*******************************************************************************
63  * Code
64  ******************************************************************************/
65 /*!
66  * @brief Returns an instance number given a base address.
67  *
68  * If an invalid base address is passed, debug builds will assert. Release builds will just return
69  * instance number 0.
70  *
71  * @param base The I2S peripheral base address.
72  * @return I2S instance number starting from 0.
73  */
I2S_GetInstance(I2S_Type * base)74 static uint32_t I2S_GetInstance(I2S_Type *base)
75 {
76     uint32_t i;
77     for (i = 0; i < (uint32_t)ARRAY_SIZE(s_i2sBaseAddrs); i++)
78     {
79         if ((uint32_t)base == s_i2sBaseAddrs[i])
80         {
81             return i;
82         }
83     }
84     assert(false);
85     return 0;
86 }
87 
88 /*!
89  * brief Transmitter bit clock rate configurations.
90  *
91  * param base SAI base pointer.
92  * param sourceClockHz, bit clock source frequency.
93  * param sampleRate audio data sample rate.
94  * param bitWidth, audio data bitWidth.
95  * param channelNumbers, audio channel numbers.
96  */
I2S_SetBitClockRate(I2S_Type * base,uint32_t sourceClockHz,uint32_t sampleRate,uint32_t bitWidth,uint32_t channelNumbers)97 void I2S_SetBitClockRate(
98     I2S_Type *base, uint32_t sourceClockHz, uint32_t sampleRate, uint32_t bitWidth, uint32_t channelNumbers)
99 {
100     uint32_t bitClockDivider = sourceClockHz / sampleRate / bitWidth / channelNumbers;
101 
102     assert(bitClockDivider >= 1U);
103     base->DIV = I2S_DIV_DIV(bitClockDivider - 1U);
104 }
105 
106 /*!
107  * brief Initializes the FLEXCOMM peripheral for I2S transmit functionality.
108  *
109  * Ungates the FLEXCOMM clock and configures the module
110  * for I2S transmission using a configuration structure.
111  * The configuration structure can be custom filled or set with default values by
112  * I2S_TxGetDefaultConfig().
113  *
114  * note This API should be called at the beginning of the application to use
115  * the I2S driver.
116  *
117  * param base I2S base pointer.
118  * param config pointer to I2S configuration structure.
119  */
I2S_TxInit(I2S_Type * base,const i2s_config_t * config)120 void I2S_TxInit(I2S_Type *base, const i2s_config_t *config)
121 {
122     uint32_t cfg  = 0U;
123     uint32_t trig = 0U;
124 
125     (void)FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2S_TX);
126     I2S_Config(base, config);
127 
128     /* Configure FIFO */
129 
130     cfg |= I2S_FIFOCFG_ENABLETX(1U);                 /* enable TX FIFO */
131     cfg |= I2S_FIFOCFG_EMPTYTX(1U);                  /* empty TX FIFO */
132     cfg |= I2S_FIFOCFG_TXI2SE0(config->txEmptyZero); /* transmit zero when buffer becomes empty or last item */
133     cfg |= I2S_FIFOCFG_PACK48(config->pack48);       /* set pack 48-bit format or not */
134     trig |= I2S_FIFOTRIG_TXLVLENA(1U);               /* enable TX FIFO trigger */
135     trig |= I2S_FIFOTRIG_TXLVL(config->watermark);   /* set TX FIFO trigger level */
136 
137     base->FIFOCFG  = cfg;
138     base->FIFOTRIG = trig;
139 }
140 
141 /*!
142  * brief Initializes the FLEXCOMM peripheral for I2S receive functionality.
143  *
144  * Ungates the FLEXCOMM clock and configures the module
145  * for I2S receive using a configuration structure.
146  * The configuration structure can be custom filled or set with default values by
147  * I2S_RxGetDefaultConfig().
148  *
149  * note This API should be called at the beginning of the application to use
150  * the I2S driver.
151  *
152  * param base I2S base pointer.
153  * param config pointer to I2S configuration structure.
154  */
I2S_RxInit(I2S_Type * base,const i2s_config_t * config)155 void I2S_RxInit(I2S_Type *base, const i2s_config_t *config)
156 {
157     uint32_t cfg  = 0U;
158     uint32_t trig = 0U;
159 
160     (void)FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2S_RX);
161     I2S_Config(base, config);
162 
163     /* Configure FIFO */
164 
165     cfg |= I2S_FIFOCFG_ENABLERX(1U);               /* enable RX FIFO */
166     cfg |= I2S_FIFOCFG_EMPTYRX(1U);                /* empty RX FIFO */
167     cfg |= I2S_FIFOCFG_PACK48(config->pack48);     /* set pack 48-bit format or not */
168     trig |= I2S_FIFOTRIG_RXLVLENA(1U);             /* enable RX FIFO trigger */
169     trig |= I2S_FIFOTRIG_RXLVL(config->watermark); /* set RX FIFO trigger level */
170 
171     base->FIFOCFG  = cfg;
172     base->FIFOTRIG = trig;
173 }
174 
175 /*!
176  * brief Flush the valid data in TX fifo.
177  *
178  * param base I2S base pointer.
179  * return kStatus_Fail empty TX fifo failed, kStatus_Success empty tx fifo success.
180  */
I2S_EmptyTxFifo(I2S_Type * base)181 status_t I2S_EmptyTxFifo(I2S_Type *base)
182 {
183     uint32_t timeout = I2S_TX_FIFO_EMPTY_TIMEOUT(I2S_FIFO_DEPTH);
184 
185     while (((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U) && (timeout != 0U))
186     {
187         timeout -= I2S_TX_ONE_SAMPLE_MAX_TIMEOUT;
188         SDK_DelayAtLeastUs(I2S_TX_ONE_SAMPLE_MAX_TIMEOUT, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
189     }
190 
191     /* The last piece of valid data can be still being transmitted from I2S at this moment */
192     timeout = I2S_TX_ONE_SAMPLE_MAX_TIMEOUT;
193     /* Write additional data to FIFO */
194     base->FIFOWR = 0U;
195     while (((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U) && (timeout != 0U))
196     {
197         timeout -= I2S_TX_ONE_SAMPLE_MAX_TIMEOUT;
198         SDK_DelayAtLeastUs(I2S_TX_ONE_SAMPLE_MAX_TIMEOUT, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
199     }
200 
201     return ((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U) ? kStatus_Fail : kStatus_Success;
202 }
203 
204 /*!
205  * brief Sets the I2S Tx configuration structure to default values.
206  *
207  * This API initializes the configuration structure for use in I2S_TxInit().
208  * The initialized structure can remain unchanged in I2S_TxInit(), or it can be modified
209  * before calling I2S_TxInit().
210  * Example:
211    code
212    i2s_config_t config;
213    I2S_TxGetDefaultConfig(&config);
214    endcode
215  *
216  * Default values:
217  * code
218  *   config->masterSlave = kI2S_MasterSlaveNormalMaster;
219  *   config->mode = kI2S_ModeI2sClassic;
220  *   config->rightLow = false;
221  *   config->leftJust = false;
222  *   config->pdmData = false;
223  *   config->sckPol = false;
224  *   config->wsPol = false;
225  *   config->divider = 1;
226  *   config->oneChannel = false;
227  *   config->dataLength = 16;
228  *   config->frameLength = 32;
229  *   config->position = 0;
230  *   config->watermark = 4;
231  *   config->txEmptyZero = true;
232  *   config->pack48 = false;
233  * endcode
234  *
235  * param config pointer to I2S configuration structure.
236  */
I2S_TxGetDefaultConfig(i2s_config_t * config)237 void I2S_TxGetDefaultConfig(i2s_config_t *config)
238 {
239     config->masterSlave = kI2S_MasterSlaveNormalMaster;
240     config->mode        = kI2S_ModeI2sClassic;
241     config->rightLow    = false;
242     config->leftJust    = false;
243 #if (defined(FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION) && FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION)
244     config->pdmData = false;
245 #endif
246     config->sckPol      = false;
247     config->wsPol       = false;
248     config->divider     = 1U;
249     config->oneChannel  = false;
250     config->dataLength  = 16U;
251     config->frameLength = 32U;
252     config->position    = 0U;
253     config->watermark   = 4U;
254     config->txEmptyZero = true;
255     config->pack48      = false;
256 }
257 
258 /*!
259  * brief Sets the I2S Rx configuration structure to default values.
260  *
261  * This API initializes the configuration structure for use in I2S_RxInit().
262  * The initialized structure can remain unchanged in I2S_RxInit(), or it can be modified
263  * before calling I2S_RxInit().
264  * Example:
265    code
266    i2s_config_t config;
267    I2S_RxGetDefaultConfig(&config);
268    endcode
269  *
270  * Default values:
271  * code
272  *   config->masterSlave = kI2S_MasterSlaveNormalSlave;
273  *   config->mode = kI2S_ModeI2sClassic;
274  *   config->rightLow = false;
275  *   config->leftJust = false;
276  *   config->pdmData = false;
277  *   config->sckPol = false;
278  *   config->wsPol = false;
279  *   config->divider = 1;
280  *   config->oneChannel = false;
281  *   config->dataLength = 16;
282  *   config->frameLength = 32;
283  *   config->position = 0;
284  *   config->watermark = 4;
285  *   config->txEmptyZero = false;
286  *   config->pack48 = false;
287  * endcode
288  *
289  * param config pointer to I2S configuration structure.
290  */
I2S_RxGetDefaultConfig(i2s_config_t * config)291 void I2S_RxGetDefaultConfig(i2s_config_t *config)
292 {
293     config->masterSlave = kI2S_MasterSlaveNormalSlave;
294     config->mode        = kI2S_ModeI2sClassic;
295     config->rightLow    = false;
296     config->leftJust    = false;
297 #if (defined(FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION) && FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION)
298     config->pdmData = false;
299 #endif
300     config->sckPol      = false;
301     config->wsPol       = false;
302     config->divider     = 1U;
303     config->oneChannel  = false;
304     config->dataLength  = 16U;
305     config->frameLength = 32U;
306     config->position    = 0U;
307     config->watermark   = 4U;
308     config->txEmptyZero = false;
309     config->pack48      = false;
310 }
311 
I2S_Config(I2S_Type * base,const i2s_config_t * config)312 static void I2S_Config(I2S_Type *base, const i2s_config_t *config)
313 {
314     assert(config != NULL);
315 
316     uint32_t cfg1 = 0U;
317     uint32_t cfg2 = 0U;
318 
319     /* set master/slave configuration */
320     cfg1 |= I2S_CFG1_MSTSLVCFG(config->masterSlave);
321 
322     /* set I2S mode */
323     cfg1 |= I2S_CFG1_MODE(config->mode);
324 
325     /* set right low (channel swap) */
326     cfg1 |= I2S_CFG1_RIGHTLOW(config->rightLow);
327 
328     /* set data justification */
329     cfg1 |= I2S_CFG1_LEFTJUST(config->leftJust);
330 
331 #if (defined(FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION) && FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION)
332     if (FSL_FEATURE_FLEXCOMM_INSTANCE_I2S_HAS_DMIC_INTERCONNECTIONn((FLEXCOMM_Type *)(uint32_t)base) > 0)
333     {
334         /* set source to PDM dmic */
335         cfg1 |= I2S_CFG1_PDMDATA(config->pdmData);
336     }
337 #endif
338 
339     /* set SCLK polarity */
340     cfg1 |= I2S_CFG1_SCK_POL(config->sckPol);
341 
342     /* set WS polarity */
343     cfg1 |= I2S_CFG1_WS_POL(config->wsPol);
344 
345     /* set mono mode */
346     cfg1 |= I2S_CFG1_ONECHANNEL(config->oneChannel);
347 
348     /* set data length */
349     cfg1 |= I2S_CFG1_DATALEN(config->dataLength - 1UL);
350 
351     /* set frame length */
352     cfg2 |= I2S_CFG2_FRAMELEN(config->frameLength - 1UL);
353 
354     /* set data position of this channel pair within the frame */
355     cfg2 |= I2S_CFG2_POSITION(config->position);
356 
357     /* write to registers */
358     base->CFG1 = cfg1;
359     base->CFG2 = cfg2;
360 
361     /* set the clock divider */
362     base->DIV = I2S_DIV_DIV(config->divider - 1UL);
363 }
364 
365 /*!
366  * brief De-initializes the I2S peripheral.
367  *
368  * This API gates the FLEXCOMM clock. The I2S module can't operate unless I2S_TxInit
369  * or I2S_RxInit is called to enable the clock.
370  *
371  * param base I2S base pointer.
372  */
I2S_Deinit(I2S_Type * base)373 void I2S_Deinit(I2S_Type *base)
374 {
375     /* TODO gate FLEXCOMM clock via FLEXCOMM driver */
376 }
377 
I2S_TxEnable(I2S_Type * base,bool enable)378 static void I2S_TxEnable(I2S_Type *base, bool enable)
379 {
380     if (enable)
381     {
382         I2S_Enable(base);
383         I2S_EnableInterrupts(base, (uint32_t)kI2S_TxErrorFlag | (uint32_t)kI2S_TxLevelFlag);
384     }
385     else
386     {
387         I2S_DisableInterrupts(base, (uint32_t)kI2S_TxErrorFlag | (uint32_t)kI2S_TxLevelFlag);
388         I2S_Disable(base);
389         base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
390     }
391 }
392 
I2S_RxEnable(I2S_Type * base,bool enable)393 static void I2S_RxEnable(I2S_Type *base, bool enable)
394 {
395     if (enable)
396     {
397         I2S_Enable(base);
398         I2S_EnableInterrupts(base, (uint32_t)kI2S_RxErrorFlag | (uint32_t)kI2S_RxLevelFlag);
399     }
400     else
401     {
402         I2S_DisableInterrupts(base, (uint32_t)kI2S_RxErrorFlag | (uint32_t)kI2S_RxLevelFlag);
403         I2S_Disable(base);
404         base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
405     }
406 }
407 
I2S_ValidateBuffer(i2s_handle_t * handle,i2s_transfer_t * transfer)408 static status_t I2S_ValidateBuffer(i2s_handle_t *handle, i2s_transfer_t *transfer)
409 {
410     assert(transfer->data != NULL);
411 
412     if (transfer->data == NULL)
413     {
414         return kStatus_InvalidArgument;
415     }
416 
417     assert(transfer->dataSize > 0U);
418     if (transfer->dataSize <= 0U)
419     {
420         return kStatus_InvalidArgument;
421     }
422 
423     if (handle->dataLength == 4U)
424     {
425         /* No alignment and data length requirements */
426     }
427     else if ((handle->dataLength >= 5U) && (handle->dataLength <= 8U))
428     {
429         assert((((uint32_t)transfer->data) % 2U) == 0U);
430         if ((((uint32_t)transfer->data) % 2U) != 0U)
431         {
432             /* Data not 2-bytes aligned */
433             return kStatus_InvalidArgument;
434         }
435 
436         assert((transfer->dataSize % 2U) == 0U);
437         if ((transfer->dataSize % 2U) != 0U)
438         {
439             /* Data not in pairs of left/right channel bytes */
440             return kStatus_InvalidArgument;
441         }
442     }
443     else if ((handle->dataLength >= 9U) && (handle->dataLength <= 16U))
444     {
445         assert((((uint32_t)transfer->data) % 4U) == 0U);
446         if ((((uint32_t)transfer->data) % 4U) != 0U)
447         {
448             /* Data not 4-bytes aligned */
449             return kStatus_InvalidArgument;
450         }
451 
452         assert((transfer->dataSize % 4U) == 0U);
453         if ((transfer->dataSize % 4U) != 0U)
454         {
455             /* Data lenght not multiply of 4 */
456             return kStatus_InvalidArgument;
457         }
458     }
459     else if ((handle->dataLength >= 17U) && (handle->dataLength <= 24U))
460     {
461         assert((transfer->dataSize % 6U) == 0U);
462         if ((transfer->dataSize % 6U) != 0U)
463         {
464             /* Data lenght not multiply of 6 */
465             return kStatus_InvalidArgument;
466         }
467 
468         assert(!((handle->pack48) && ((((uint32_t)transfer->data) % 4U) != 0U)));
469         if ((handle->pack48) && ((((uint32_t)transfer->data) % 4U) != 0U))
470         {
471             /* Data not 4-bytes aligned */
472             return kStatus_InvalidArgument;
473         }
474     }
475     else /* if (handle->dataLength >= 25U) */
476     {
477         assert((((uint32_t)transfer->data) % 4U) == 0U);
478         if ((((uint32_t)transfer->data) % 4U) != 0U)
479         {
480             /* Data not 4-bytes aligned */
481             return kStatus_InvalidArgument;
482         }
483 
484         if (handle->oneChannel)
485         {
486             assert((transfer->dataSize % 4U) == 0U);
487             if ((transfer->dataSize % 4U) != 0U)
488             {
489                 /* Data lenght not multiply of 4 */
490                 return kStatus_InvalidArgument;
491             }
492         }
493         else
494         {
495             assert((transfer->dataSize % 8U) == 0U);
496             if ((transfer->dataSize % 8U) != 0U)
497             {
498                 /* Data lenght not multiply of 8 */
499                 return kStatus_InvalidArgument;
500             }
501         }
502     }
503 
504     return kStatus_Success;
505 }
506 
507 #if (defined(FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL) && FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL)
508 /*!
509  * brief Enables I2S secondary channel.
510  *
511  * param base I2S      base pointer.
512  * param channel       seondary channel channel number, reference _i2s_secondary_channel.
513  * param oneChannel    true is treated as single channel, functionality left channel for this pair.
514  * param position      define the location within the frame of the data, should not bigger than 0x1FFU.
515  */
I2S_EnableSecondaryChannel(I2S_Type * base,uint32_t channel,bool oneChannel,uint32_t position)516 void I2S_EnableSecondaryChannel(I2S_Type *base, uint32_t channel, bool oneChannel, uint32_t position)
517 {
518     assert(channel <= (uint32_t)kI2S_SecondaryChannel3);
519 #if defined FSL_FEATURE_FLEXCOMM_INSTANCE_I2S_SUPPORT_SECONDARY_CHANNELn
520     assert(FSL_FEATURE_FLEXCOMM_INSTANCE_I2S_SUPPORT_SECONDARY_CHANNELn((FLEXCOMM_Type *)(uint32_t)base) == 1);
521 #endif
522 
523     uint32_t pcfg1 = base->SECCHANNEL[channel].PCFG1;
524     uint32_t pcfg2 = base->SECCHANNEL[channel].PCFG2;
525 
526     pcfg1 &= ~I2S_CFG1_ONECHANNEL_MASK;
527     pcfg1 |= I2S_CFG1_MAINENABLE_MASK | I2S_CFG1_ONECHANNEL(oneChannel);
528 
529     pcfg2 &= ~I2S_CFG2_POSITION_MASK;
530     pcfg2 |= I2S_CFG2_POSITION(position);
531 
532     base->SECCHANNEL[channel].PCFG1 = pcfg1;
533     base->SECCHANNEL[channel].PCFG2 = pcfg2;
534 }
535 #endif
536 
537 /*!
538  * brief Initializes handle for transfer of audio data.
539  *
540  * param base I2S base pointer.
541  * param handle pointer to handle structure.
542  * param callback function to be called back when transfer is done or fails.
543  * param userData pointer to data passed to callback.
544  */
I2S_TxTransferCreateHandle(I2S_Type * base,i2s_handle_t * handle,i2s_transfer_callback_t callback,void * userData)545 void I2S_TxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData)
546 {
547     assert(handle != NULL);
548 
549     uint32_t instance;
550 
551     /* Clear out the handle */
552     (void)memset(handle, 0, sizeof(*handle));
553 
554     /* Look up instance number */
555     instance = I2S_GetInstance(base);
556 
557     /* Save callback and user data */
558     handle->completionCallback = callback;
559     handle->userData           = userData;
560 
561     /* Remember some items set previously by configuration */
562     handle->watermark  = (uint8_t)((base->FIFOTRIG & I2S_FIFOTRIG_TXLVL_MASK) >> I2S_FIFOTRIG_TXLVL_SHIFT);
563     handle->oneChannel = ((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) >> I2S_CFG1_ONECHANNEL_SHIFT) != 0U ? true : false;
564     handle->dataLength = (uint8_t)((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U;
565     handle->pack48     = ((base->FIFOCFG & I2S_FIFOCFG_PACK48_MASK) >> I2S_FIFOCFG_PACK48_SHIFT) != 0u ? true : false;
566 
567     handle->useFifo48H = false;
568 
569     /* Register IRQ handling */
570     FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)I2S_TxHandleIRQ, handle);
571     /* Clear internal IRQ enables and enable NVIC IRQ. */
572     I2S_DisableInterrupts(base, (uint32_t)kI2S_TxErrorFlag | (uint32_t)kI2S_TxLevelFlag);
573     (void)EnableIRQ(s_i2sIRQ[instance]);
574 }
575 
576 /*!
577  * brief Begins or queue sending of the given data.
578  *
579  * param base I2S base pointer.
580  * param handle pointer to handle structure.
581  * param transfer data buffer.
582  *
583  * retval kStatus_Success
584  * retval kStatus_I2S_Busy if all queue slots are occupied with unsent buffers.
585  */
I2S_TxTransferNonBlocking(I2S_Type * base,i2s_handle_t * handle,i2s_transfer_t transfer)586 status_t I2S_TxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer)
587 {
588     assert(handle != NULL);
589 
590     status_t result;
591 
592     if (handle == NULL)
593     {
594         return kStatus_InvalidArgument;
595     }
596 
597     result = I2S_ValidateBuffer(handle, &transfer);
598     if (result != kStatus_Success)
599     {
600         return result;
601     }
602 
603     if (handle->i2sQueue[handle->queueUser].dataSize != 0UL)
604     {
605         /* Previously prepared buffers not processed yet */
606         return kStatus_I2S_Busy;
607     }
608 
609     handle->i2sQueue[handle->queueUser].data     = transfer.data;
610     handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
611     handle->queueUser                            = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
612 
613     base->FIFOTRIG = (base->FIFOTRIG & (~I2S_FIFOTRIG_TXLVL_MASK)) | I2S_FIFOTRIG_TXLVL(handle->watermark);
614     I2S_TxEnable(base, true);
615 
616     return kStatus_Success;
617 }
618 
619 /*!
620  * brief Aborts sending of data.
621  *
622  * param base I2S base pointer.
623  * param handle pointer to handle structure.
624  */
I2S_TxTransferAbort(I2S_Type * base,i2s_handle_t * handle)625 void I2S_TxTransferAbort(I2S_Type *base, i2s_handle_t *handle)
626 {
627     assert(handle != NULL);
628 
629     /* Disable I2S operation and interrupts */
630     I2S_TxEnable(base, false);
631 
632     /* Reset state */
633     handle->state = (uint32_t)kI2S_StateIdle;
634 
635     /* Clear transfer queue */
636     (void)memset((void *)&handle->i2sQueue, 0, sizeof(i2s_transfer_t) * I2S_NUM_BUFFERS);
637     handle->queueDriver = 0U;
638     handle->queueUser   = 0U;
639 }
640 
641 /*!
642  * brief Initializes handle for reception of audio data.
643  *
644  * param base I2S base pointer.
645  * param handle pointer to handle structure.
646  * param callback function to be called back when transfer is done or fails.
647  * param userData pointer to data passed to callback.
648  */
I2S_RxTransferCreateHandle(I2S_Type * base,i2s_handle_t * handle,i2s_transfer_callback_t callback,void * userData)649 void I2S_RxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData)
650 {
651     assert(handle != NULL);
652 
653     uint32_t instance;
654 
655     /* Clear out the handle */
656     (void)memset(handle, 0, sizeof(*handle));
657 
658     /* Look up instance number */
659     instance = I2S_GetInstance(base);
660 
661     /* Save callback and user data */
662     handle->completionCallback = callback;
663     handle->userData           = userData;
664 
665     /* Remember some items set previously by configuration */
666     handle->watermark  = (uint8_t)((base->FIFOTRIG & I2S_FIFOTRIG_RXLVL_MASK) >> I2S_FIFOTRIG_RXLVL_SHIFT);
667     handle->oneChannel = ((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) >> I2S_CFG1_ONECHANNEL_SHIFT) != 0UL ? true : false;
668     handle->dataLength = (uint8_t)((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U;
669     handle->pack48     = ((base->FIFOCFG & I2S_FIFOCFG_PACK48_MASK) >> I2S_FIFOCFG_PACK48_SHIFT) != 0UL ? true : false;
670 
671     handle->useFifo48H = false;
672 
673     /* Register IRQ handling */
674     FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)I2S_RxHandleIRQ, handle);
675     /* Clear internal IRQ enables and enable NVIC IRQ. */
676     I2S_DisableInterrupts(base, (uint32_t)kI2S_RxErrorFlag | (uint32_t)kI2S_RxLevelFlag);
677 
678     (void)EnableIRQ(s_i2sIRQ[instance]);
679 }
680 
681 /*!
682  * brief Begins or queue reception of data into given buffer.
683  *
684  * param base I2S base pointer.
685  * param handle pointer to handle structure.
686  * param transfer data buffer.
687  *
688  * retval kStatus_Success
689  * retval kStatus_I2S_Busy if all queue slots are occupied with buffers which are not full.
690  */
I2S_RxTransferNonBlocking(I2S_Type * base,i2s_handle_t * handle,i2s_transfer_t transfer)691 status_t I2S_RxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer)
692 {
693     assert(handle != NULL);
694 
695     status_t result;
696 
697     if (NULL == handle)
698     {
699         return kStatus_InvalidArgument;
700     }
701 
702     result = I2S_ValidateBuffer(handle, &transfer);
703     if (result != kStatus_Success)
704     {
705         return result;
706     }
707 
708     if (handle->i2sQueue[handle->queueUser].dataSize != 0UL)
709     {
710         /* Previously prepared buffers not processed yet */
711         return kStatus_I2S_Busy;
712     }
713 
714     handle->i2sQueue[handle->queueUser].data     = transfer.data;
715     handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
716     handle->queueUser                            = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
717 
718     base->FIFOTRIG = (base->FIFOTRIG & (~I2S_FIFOTRIG_RXLVL_MASK)) | I2S_FIFOTRIG_RXLVL(handle->watermark);
719     I2S_RxEnable(base, true);
720 
721     return kStatus_Success;
722 }
723 
724 /*!
725  * brief Aborts receiving of data.
726  *
727  * param base I2S base pointer.
728  * param handle pointer to handle structure.
729  */
I2S_RxTransferAbort(I2S_Type * base,i2s_handle_t * handle)730 void I2S_RxTransferAbort(I2S_Type *base, i2s_handle_t *handle)
731 {
732     assert(handle != NULL);
733 
734     /* Disable I2S operation and interrupts */
735     I2S_RxEnable(base, false);
736 
737     /* Reset state */
738     handle->state = (uint32_t)kI2S_StateIdle;
739 
740     /* Clear transfer queue */
741     (void)memset((void *)&handle->i2sQueue, 0, sizeof(i2s_transfer_t) * I2S_NUM_BUFFERS);
742     handle->queueDriver = 0U;
743     handle->queueUser   = 0U;
744 }
745 
746 /*!
747  * brief Returns number of bytes transferred so far.
748  *
749  * param base I2S base pointer.
750  * param handle pointer to handle structure.
751  * param[out] count number of bytes transferred so far by the non-blocking transaction.
752  *
753  * retval kStatus_Success
754  * retval kStatus_NoTransferInProgress there is no non-blocking transaction currently in progress.
755  */
I2S_TransferGetCount(I2S_Type * base,i2s_handle_t * handle,size_t * count)756 status_t I2S_TransferGetCount(I2S_Type *base, i2s_handle_t *handle, size_t *count)
757 {
758     assert(handle != NULL);
759     assert(count != NULL);
760 
761     if (NULL == handle)
762     {
763         return kStatus_InvalidArgument;
764     }
765 
766     if (NULL == count)
767     {
768         return kStatus_InvalidArgument;
769     }
770 
771     if (handle->state == (uint32_t)kI2S_StateIdle)
772     {
773         return kStatus_NoTransferInProgress;
774     }
775 
776     *count = handle->transferCount;
777 
778     return kStatus_Success;
779 }
780 
781 /*!
782  * brief Returns number of buffer underruns or overruns.
783  *
784  * param base I2S base pointer.
785  * param handle pointer to handle structure.
786  * param[out] count number of transmit errors encountered so far by the non-blocking transaction.
787  *
788  * retval kStatus_Success
789  * retval kStatus_NoTransferInProgress there is no non-blocking transaction currently in progress.
790  */
I2S_TransferGetErrorCount(I2S_Type * base,i2s_handle_t * handle,size_t * count)791 status_t I2S_TransferGetErrorCount(I2S_Type *base, i2s_handle_t *handle, size_t *count)
792 {
793     assert(handle != NULL);
794     assert(count != NULL);
795 
796     if (NULL == handle)
797     {
798         return kStatus_InvalidArgument;
799     }
800 
801     if (NULL == count)
802     {
803         return kStatus_InvalidArgument;
804     }
805 
806     if (handle->state == (uint32_t)kI2S_StateIdle)
807     {
808         return kStatus_NoTransferInProgress;
809     }
810 
811     *count = handle->errorCount;
812 
813     return kStatus_Success;
814 }
815 
816 /*!
817  * brief Invoked from interrupt handler when transmit FIFO level decreases.
818  *
819  * param base I2S base pointer.
820  * param handle pointer to handle structure.
821  */
I2S_TxHandleIRQ(I2S_Type * base,i2s_handle_t * handle)822 void I2S_TxHandleIRQ(I2S_Type *base, i2s_handle_t *handle)
823 {
824     uint32_t intstat = base->FIFOINTSTAT;
825     uint32_t data;
826     uint8_t queueDriverIndex = handle->queueDriver;
827     uint32_t dataAddr        = (uint32_t)handle->i2sQueue[queueDriverIndex].data;
828     uint32_t dataSize        = handle->i2sQueue[queueDriverIndex].dataSize;
829 
830     if ((intstat & I2S_FIFOINTSTAT_TXERR_MASK) != 0UL)
831     {
832         handle->errorCount++;
833 
834         /* Clear TX error interrupt flag */
835         base->FIFOSTAT = I2S_FIFOSTAT_TXERR(1U);
836     }
837 
838     if ((intstat & I2S_FIFOINTSTAT_TXLVL_MASK) != 0UL)
839     {
840         if ((handle->state != (uint32_t)kI2S_StateTx) && (dataSize != 0U) && (dataAddr != 0U))
841         {
842             handle->state = (uint32_t)kI2S_StateTx;
843         }
844 
845         if (handle->state == (uint32_t)kI2S_StateTx)
846         {
847             /* Send data */
848 
849             while (((base->FIFOSTAT & I2S_FIFOSTAT_TXNOTFULL_MASK) != 0UL) && (dataSize > 0U))
850             {
851                 /* Write output data */
852                 if (handle->dataLength == 4U)
853                 {
854                     data         = *((uint8_t *)dataAddr);
855                     base->FIFOWR = ((data & 0xF0U) << 12U) | (data & 0xFU);
856                     dataAddr++;
857                     handle->transferCount++;
858                     dataSize--;
859                 }
860                 else if (handle->dataLength <= 8U)
861                 {
862                     data = *((volatile uint16_t *)dataAddr);
863                     if (handle->oneChannel)
864                     {
865                         base->FIFOWR = (data & 0xFFU);
866                         dataAddr += sizeof(uint8_t);
867                         handle->transferCount += sizeof(uint8_t);
868                         dataSize -= sizeof(uint8_t);
869                     }
870                     else
871                     {
872                         base->FIFOWR = ((data & 0xFF00U) << 8U) | (data & 0xFFU);
873                         dataAddr += sizeof(uint16_t);
874                         handle->transferCount += sizeof(uint16_t);
875                         dataSize -= sizeof(uint16_t);
876                     }
877                 }
878                 else if (handle->dataLength <= 16U)
879                 {
880                     data = *((volatile uint32_t *)(dataAddr));
881                     if (handle->oneChannel)
882                     {
883                         base->FIFOWR = data & 0xFFFFU;
884                         dataAddr += sizeof(uint16_t);
885                         handle->transferCount += sizeof(uint16_t);
886                         dataSize -= sizeof(uint16_t);
887                     }
888                     else
889                     {
890                         base->FIFOWR = data;
891                         dataAddr += sizeof(uint32_t);
892                         handle->transferCount += sizeof(uint32_t);
893                         dataSize -= sizeof(uint32_t);
894                     }
895                 }
896                 else if (handle->dataLength <= 24U)
897                 {
898                     if (handle->pack48)
899                     {
900                         if (handle->useFifo48H)
901                         {
902                             base->FIFOWR48H = *((volatile uint16_t *)(dataAddr));
903                             dataAddr += sizeof(uint16_t);
904                             handle->transferCount += sizeof(uint16_t);
905                             dataSize -= sizeof(uint16_t);
906                             handle->useFifo48H = false;
907                         }
908                         else
909                         {
910                             base->FIFOWR = *((volatile uint32_t *)(dataAddr));
911                             dataAddr += sizeof(uint32_t);
912                             handle->transferCount += sizeof(uint32_t);
913                             dataSize -= sizeof(uint32_t);
914                             handle->useFifo48H = true;
915                         }
916                     }
917                     else
918                     {
919                         data = (uint32_t)(*(uint8_t *)(dataAddr++));
920                         data |= ((uint32_t)(*(uint8_t *)(dataAddr++))) << 8U;
921                         data |= ((uint32_t)(*(uint8_t *)(dataAddr++))) << 16U;
922                         if ((handle->useFifo48H) && (handle->oneChannel == false))
923                         {
924                             base->FIFOWR48H    = data;
925                             handle->useFifo48H = false;
926                         }
927                         else
928                         {
929                             base->FIFOWR       = data;
930                             handle->useFifo48H = true;
931                         }
932                         handle->transferCount += 3U;
933                         dataSize -= 3U;
934                     }
935                 }
936                 else /* if (handle->dataLength <= 32U) */
937                 {
938                     base->FIFOWR = *((volatile uint32_t *)(dataAddr));
939                     dataAddr += sizeof(uint32_t);
940                     handle->transferCount += sizeof(uint32_t);
941                     dataSize -= sizeof(uint32_t);
942                 }
943 
944                 if (dataSize == 0U)
945                 {
946                     handle->i2sQueue[queueDriverIndex].dataSize = 0U;
947                     /* Actual data buffer sent out, switch to a next one */
948                     handle->queueDriver = (queueDriverIndex + 1U) % I2S_NUM_BUFFERS;
949 
950                     /* Notify user */
951                     if (handle->completionCallback != NULL)
952                     {
953                         handle->completionCallback(base, handle, kStatus_I2S_BufferComplete, handle->userData);
954                     }
955 
956                     /* Check if the next buffer contains anything to send */
957                     if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
958                     {
959                         /* Everything has been written to FIFO */
960                         handle->state = kI2S_StateTxWaitToWriteDummyData;
961                         break;
962                     }
963                 }
964                 else
965                 {
966                     handle->i2sQueue[queueDriverIndex].dataSize = dataSize;
967                     handle->i2sQueue[queueDriverIndex].data     = (uint8_t *)dataAddr;
968                 }
969             }
970         }
971         else if (handle->state == (uint32_t)kI2S_StateTxWaitToWriteDummyData)
972         {
973             /* Write dummy data */
974             if ((handle->dataLength > 16U) && (handle->dataLength < 25U))
975             {
976                 if (handle->useFifo48H)
977                 {
978                     base->FIFOWR48H    = 0U;
979                     handle->useFifo48H = false;
980                 }
981                 else
982                 {
983                     base->FIFOWR    = 0U;
984                     base->FIFOWR48H = 0U;
985                 }
986             }
987             else
988             {
989                 base->FIFOWR = 0U;
990             }
991 
992             /* Next time invoke this handler when FIFO becomes empty (TX level 0) */
993             base->FIFOTRIG &= ~I2S_FIFOTRIG_TXLVL_MASK;
994             handle->state = (uint32_t)kI2S_StateTxWaitForEmptyFifo;
995         }
996         else if (handle->state == (uint32_t)kI2S_StateTxWaitForEmptyFifo)
997         {
998             /* FIFO, including additional dummy data, has been emptied now,
999              * all relevant data should have been output from peripheral */
1000 
1001             /* Stop transfer */
1002             I2S_Disable(base);
1003             I2S_DisableInterrupts(base, (uint32_t)kI2S_TxErrorFlag | (uint32_t)kI2S_TxLevelFlag);
1004             base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
1005 
1006             /* Reset state */
1007             handle->state = (uint32_t)kI2S_StateIdle;
1008 
1009             /* Notify user */
1010             if (handle->completionCallback != NULL)
1011             {
1012                 handle->completionCallback(base, handle, kStatus_I2S_Done, handle->userData);
1013             }
1014         }
1015         else
1016         {
1017             /* Do nothing */
1018         }
1019 
1020         /* Clear TX level interrupt flag */
1021         base->FIFOSTAT = I2S_FIFOSTAT_TXLVL(1U);
1022     }
1023 }
1024 
1025 /*!
1026  * brief Invoked from interrupt handler when receive FIFO level decreases.
1027  *
1028  * param base I2S base pointer.
1029  * param handle pointer to handle structure.
1030  */
I2S_RxHandleIRQ(I2S_Type * base,i2s_handle_t * handle)1031 void I2S_RxHandleIRQ(I2S_Type *base, i2s_handle_t *handle)
1032 {
1033     uint32_t intstat = base->FIFOINTSTAT;
1034     uint32_t data;
1035     uint8_t queueDriverIndex = handle->queueDriver;
1036     uint32_t dataAddr        = (uint32_t)handle->i2sQueue[queueDriverIndex].data;
1037     uint32_t dataSize        = handle->i2sQueue[queueDriverIndex].dataSize;
1038 
1039     if ((intstat & I2S_FIFOINTSTAT_RXERR_MASK) != 0UL)
1040     {
1041         handle->errorCount++;
1042 
1043         /* Clear RX error interrupt flag */
1044         base->FIFOSTAT = I2S_FIFOSTAT_RXERR(1U);
1045     }
1046 
1047     if ((intstat & I2S_FIFOINTSTAT_RXLVL_MASK) != 0UL)
1048     {
1049         while (((base->FIFOSTAT & I2S_FIFOSTAT_RXNOTEMPTY_MASK) != 0UL) && (dataSize > 0U))
1050         {
1051             /* Read input data */
1052             if (handle->dataLength == 4U)
1053             {
1054                 data                   = base->FIFORD;
1055                 *((uint8_t *)dataAddr) = (uint8_t)(((data & 0x000F0000U) >> 12U) | (data & 0x0000000FU));
1056                 dataAddr++;
1057                 handle->transferCount++;
1058                 dataSize--;
1059             }
1060             else if (handle->dataLength <= 8U)
1061             {
1062                 data = base->FIFORD;
1063 
1064                 if (handle->oneChannel)
1065                 {
1066                     *((volatile uint8_t *)dataAddr) = (uint8_t)(data & 0xFFU);
1067                     dataAddr += sizeof(uint8_t);
1068                     handle->transferCount += sizeof(uint8_t);
1069                     dataSize -= sizeof(uint8_t);
1070                 }
1071                 else
1072                 {
1073                     *((volatile uint16_t *)dataAddr) = (uint16_t)(((data >> 8U) & 0xFF00U) | (data & 0xFFU));
1074                     dataAddr += sizeof(uint16_t);
1075                     handle->transferCount += sizeof(uint16_t);
1076                     dataSize -= sizeof(uint16_t);
1077                 }
1078             }
1079             else if (handle->dataLength <= 16U)
1080             {
1081                 data = base->FIFORD;
1082 
1083                 if (handle->oneChannel)
1084                 {
1085                     *((volatile uint16_t *)dataAddr) = (uint16_t)(data & 0xFFFFU);
1086                     dataAddr += sizeof(uint16_t);
1087                     handle->transferCount += sizeof(uint16_t);
1088                     dataSize -= sizeof(uint16_t);
1089                 }
1090                 else
1091                 {
1092                     *((volatile uint32_t *)dataAddr) = data;
1093                     dataAddr += sizeof(uint32_t);
1094                     handle->transferCount += sizeof(uint32_t);
1095                     dataSize -= sizeof(uint32_t);
1096                 }
1097             }
1098             else if (handle->dataLength <= 24U)
1099             {
1100                 if (handle->pack48)
1101                 {
1102                     if (handle->useFifo48H)
1103                     {
1104                         data               = base->FIFORD48H;
1105                         handle->useFifo48H = false;
1106 
1107                         *((volatile uint16_t *)dataAddr) = (uint16_t)data;
1108                         dataAddr += sizeof(uint16_t);
1109                         handle->transferCount += sizeof(uint16_t);
1110                         dataSize -= sizeof(uint16_t);
1111                     }
1112                     else
1113                     {
1114                         data               = base->FIFORD;
1115                         handle->useFifo48H = true;
1116 
1117                         *((volatile uint32_t *)dataAddr) = data;
1118                         dataAddr += sizeof(uint32_t);
1119                         handle->transferCount += sizeof(uint32_t);
1120                         dataSize -= sizeof(uint32_t);
1121                     }
1122                 }
1123                 else
1124                 {
1125                     if (handle->useFifo48H)
1126                     {
1127                         data               = base->FIFORD48H;
1128                         handle->useFifo48H = false;
1129                     }
1130                     else
1131                     {
1132                         data               = base->FIFORD;
1133                         handle->useFifo48H = true;
1134                     }
1135 
1136                     *(uint8_t *)(dataAddr++) = (uint8_t)(data & 0xFFU);
1137                     *(uint8_t *)(dataAddr++) = (uint8_t)((data >> 8U) & 0xFFU);
1138                     *(uint8_t *)(dataAddr++) = (uint8_t)((data >> 16U) & 0xFFU);
1139                     handle->transferCount += 3U;
1140                     dataSize -= 3U;
1141                 }
1142             }
1143             else /* if (handle->dataLength <= 32U) */
1144             {
1145                 data                             = base->FIFORD;
1146                 *((volatile uint32_t *)dataAddr) = data;
1147                 dataAddr += sizeof(uint32_t);
1148                 handle->transferCount += sizeof(uint32_t);
1149                 dataSize -= sizeof(uint32_t);
1150             }
1151 
1152             if (dataSize == 0U)
1153             {
1154                 handle->i2sQueue[queueDriverIndex].dataSize = 0U;
1155                 /* Actual data buffer filled with input data, switch to a next one */
1156                 handle->queueDriver = (queueDriverIndex + 1U) % I2S_NUM_BUFFERS;
1157 
1158                 /* Notify user */
1159                 if (handle->completionCallback != NULL)
1160                 {
1161                     handle->completionCallback(base, handle, kStatus_I2S_BufferComplete, handle->userData);
1162                 }
1163 
1164                 if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
1165                 {
1166                     /* No other buffer prepared to receive data into */
1167 
1168                     /* Disable I2S operation and interrupts */
1169                     I2S_Disable(base);
1170                     I2S_DisableInterrupts(base, (uint32_t)kI2S_RxErrorFlag | (uint32_t)kI2S_RxLevelFlag);
1171                     base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
1172 
1173                     /* Reset state */
1174                     handle->state = (uint32_t)kI2S_StateIdle;
1175 
1176                     /* Notify user */
1177                     if (handle->completionCallback != NULL)
1178                     {
1179                         handle->completionCallback(base, handle, kStatus_I2S_Done, handle->userData);
1180                     }
1181 
1182                     /* Clear RX level interrupt flag */
1183                     base->FIFOSTAT = I2S_FIFOSTAT_RXLVL(1U);
1184 
1185                     return;
1186                 }
1187             }
1188             else
1189             {
1190                 handle->i2sQueue[queueDriverIndex].dataSize = dataSize;
1191                 handle->i2sQueue[queueDriverIndex].data     = (uint8_t *)dataAddr;
1192             }
1193         }
1194 
1195         /* Clear RX level interrupt flag */
1196         base->FIFOSTAT = I2S_FIFOSTAT_RXLVL(1U);
1197     }
1198 }
1199