1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_esai.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.esai"
14 #endif
15 
16 /*******************************************************************************
17  * Definitations
18  ******************************************************************************/
19 /*!@brief _esai_transfer_state */
20 enum
21 {
22     kESAI_Busy = 0x0U, /*!< ESAI is busy */
23     kESAI_Idle,        /*!< Transfer is done. */
24     kESAI_Error        /*!< Transfer error occurred. */
25 };
26 
27 /*! @brief Typedef for esai tx interrupt handler. */
28 typedef void (*esai_tx_isr_t)(ESAI_Type *base, esai_handle_t *esaiHandle);
29 
30 /*! @brief Typedef for esai rx interrupt handler. */
31 typedef void (*esai_rx_isr_t)(ESAI_Type *base, esai_handle_t *esaiHandle);
32 
33 /*! @brief Slot number to slot mask number */
34 #define SLOT_TO_MASK(slot) ((1UL << (slot)) - 1U)
35 
36 /*******************************************************************************
37  * Prototypes
38  ******************************************************************************/
39 
40 /*!
41  * @brief Set customer defined audio protocol for tx section.
42  *
43  * This API sets the audio protocol defined by users.
44  *
45  * @param base ESAI base pointer.
46  * @param protocol ESAI protocol define structure pointer.
47  */
48 static void ESAI_SetCustomerProtocol(ESAI_Type *base,
49                                      esai_protocol_t fmt,
50                                      esai_customer_protocol_t *protocol,
51                                      bool isTx);
52 
53 /*!
54  * @brief sends a piece of data in non-blocking way.
55  *
56  * @param base ESAI base pointer
57  * @param channel Data channel used.
58  * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
59  * @param buffer Pointer to the data to be written.
60  * @param size Bytes to be written.
61  */
62 static void ESAI_WriteNonBlocking(ESAI_Type *base, uint32_t bitWidth, uint8_t *buffer, uint32_t size);
63 
64 /*!
65  * @brief Receive a piece of data in non-blocking way.
66  *
67  * @param base ESAI base pointer
68  * @param channel Data channel used.
69  * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
70  * @param buffer Pointer to the data to be read.
71  * @param size Bytes to be read.
72  */
73 static void ESAI_ReadNonBlocking(ESAI_Type *base, uint32_t bitWidth, uint8_t *buffer, uint32_t size);
74 /*******************************************************************************
75  * Variables
76  ******************************************************************************/
77 /*!@brief ESAI handle pointer */
78 static esai_handle_t *s_esaiHandle[FSL_FEATURE_SOC_ESAI_COUNT][2];
79 /* Base pointer array */
80 static ESAI_Type *const s_esaiBases[] = ESAI_BASE_PTRS;
81 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
82 /* Clock name array */
83 static const clock_ip_name_t s_esaiClock[] = ESAI_CLOCKS;
84 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
85 /* IRQ number array */
86 static const IRQn_Type s_esaiTxIRQ[] = ESAI_IRQS;
87 static const IRQn_Type s_esaiRxIRQ[] = ESAI_IRQS;
88 /*! @brief Pointer to tx IRQ handler for each instance. */
89 static esai_tx_isr_t s_esaiTxIsr;
90 /*! @brief Pointer to tx IRQ handler for each instance. */
91 static esai_rx_isr_t s_esaiRxIsr;
92 
93 /*******************************************************************************
94  * Code
95  ******************************************************************************/
ESAI_SetCustomerProtocol(ESAI_Type * base,esai_protocol_t fmt,esai_customer_protocol_t * protocol,bool isTx)96 static void ESAI_SetCustomerProtocol(ESAI_Type *base,
97                                      esai_protocol_t fmt,
98                                      esai_customer_protocol_t *protocol,
99                                      bool isTx)
100 {
101     switch (fmt)
102     {
103         case kESAI_BusLeftJustified:
104             protocol->mode           = kESAI_NetworkMode;
105             protocol->dataAlign      = false;
106             protocol->fsEarly        = false;
107             protocol->shiftDirection = kESAI_ShifterMSB;
108             protocol->fsOneBit       = false;
109             protocol->ifZeroPading   = true;
110             protocol->slotNum        = 2;
111             break;
112         case kESAI_BusRightJustified:
113             protocol->mode           = kESAI_NetworkMode;
114             protocol->dataAlign      = true;
115             protocol->fsEarly        = false;
116             protocol->shiftDirection = kESAI_ShifterMSB;
117             protocol->fsOneBit       = false;
118             protocol->ifZeroPading   = true;
119             protocol->slotNum        = 2;
120             break;
121         case kESAI_BusI2S:
122             protocol->mode           = kESAI_NetworkMode;
123             protocol->dataAlign      = false;
124             protocol->fsEarly        = true;
125             protocol->shiftDirection = kESAI_ShifterMSB;
126             protocol->fsOneBit       = false;
127             protocol->ifZeroPading   = true;
128             protocol->slotNum        = 2;
129             break;
130         case kESAI_BusPCMA:
131             protocol->mode           = kESAI_NetworkMode;
132             protocol->dataAlign      = false;
133             protocol->fsEarly        = true;
134             protocol->shiftDirection = kESAI_ShifterMSB;
135             protocol->fsOneBit       = false;
136             protocol->ifZeroPading   = true;
137             protocol->slotNum        = 2;
138             break;
139         case kESAI_BusPCMB:
140             protocol->mode           = kESAI_NetworkMode;
141             protocol->dataAlign      = false;
142             protocol->fsEarly        = false;
143             protocol->shiftDirection = kESAI_ShifterMSB;
144             protocol->fsOneBit       = false;
145             protocol->ifZeroPading   = true;
146             protocol->slotNum        = 2;
147             break;
148         case kESAI_BusTDM:
149             protocol->mode           = kESAI_NetworkMode;
150             protocol->dataAlign      = false;
151             protocol->fsEarly        = true;
152             protocol->shiftDirection = kESAI_ShifterMSB;
153             protocol->fsOneBit       = false;
154             protocol->ifZeroPading   = true;
155             break;
156         default:
157             assert(false);
158             break;
159     }
160 
161     if (isTx)
162     {
163         base->TCR &= ~(ESAI_TCR_PADC_MASK | ESAI_TCR_TFSR_MASK | ESAI_TCR_TFSL_MASK | ESAI_TCR_TWA_MASK |
164                        ESAI_TCR_TMOD_MASK | ESAI_TCR_TSHFD_MASK);
165         /* Set the direction for shifter */
166         base->TCR |= ESAI_TCR_PADC(protocol->ifZeroPading) | ESAI_TCR_TFSR(protocol->fsEarly) |
167                      ESAI_TCR_TFSL(protocol->fsOneBit) | ESAI_TCR_TWA(protocol->dataAlign) |
168                      ESAI_TCR_TMOD(protocol->mode) | ESAI_TCR_TSHFD(protocol->shiftDirection);
169 
170         base->TCCR &= ~ESAI_TCCR_TDC_MASK;
171         base->TCCR |= ESAI_TCCR_TDC((uint32_t)protocol->slotNum - 1U);
172 
173         /* Set slot mask */
174         ESAI_TxSetSlotMask(base, SLOT_TO_MASK(protocol->slotNum));
175     }
176     else
177     {
178         base->RCR &=
179             ~(ESAI_RCR_RFSR_MASK | ESAI_RCR_RFSL_MASK | ESAI_RCR_RWA_MASK | ESAI_RCR_RMOD_MASK | ESAI_RCR_RSHFD_MASK);
180         /* Set the direction for shifter */
181         base->RCR |= ESAI_RCR_RFSR(protocol->fsEarly) | ESAI_RCR_RFSL(protocol->fsOneBit) |
182                      ESAI_RCR_RWA(protocol->dataAlign) | ESAI_RCR_RMOD(protocol->mode) |
183                      ESAI_RCR_RSHFD(protocol->shiftDirection);
184 
185         base->RCCR &= ~ESAI_RCCR_RDC_MASK;
186         base->RCCR |= ESAI_RCCR_RDC(protocol->slotNum - 1UL);
187 
188         /* Set slot mask */
189         EASI_RxSetSlotMask(base, SLOT_TO_MASK(protocol->slotNum));
190     }
191 }
192 
ESAI_AnalysisSlot(esai_slot_format_t slotFormat,uint8_t * slotLen,uint8_t * dataLen)193 void ESAI_AnalysisSlot(esai_slot_format_t slotFormat, uint8_t *slotLen, uint8_t *dataLen)
194 {
195     assert((slotLen != NULL) && (dataLen != NULL));
196 
197     switch (slotFormat)
198     {
199         case kESAI_SlotLen8WordLen8:
200             *slotLen = 8U;
201             *dataLen = 8U;
202             break;
203         case kESAI_SlotLen12WordLen12:
204             *slotLen = 12U;
205             *dataLen = 12U;
206             break;
207         case kESAI_SlotLen16WordLen8:
208             *slotLen = 16U;
209             *dataLen = 8U;
210             break;
211         case kESAI_SlotLen16WordLen12:
212             *slotLen = 16U;
213             *dataLen = 12U;
214             break;
215         case kESAI_SlotLen16WordLen16:
216             *slotLen = 16U;
217             *dataLen = 16U;
218             break;
219         case kESAI_SlotLen20WordLen8:
220             *slotLen = 20U;
221             *dataLen = 8U;
222             break;
223         case kESAI_SlotLen20WordLen12:
224             *slotLen = 20U;
225             *dataLen = 12U;
226             break;
227         case kESAI_SlotLen20WordLen16:
228             *slotLen = 20U;
229             *dataLen = 16U;
230             break;
231         case kESAI_SlotLen24WordLen8:
232             *slotLen = 24U;
233             *dataLen = 8U;
234             break;
235         case kESAI_SlotLen24WordLen12:
236             *slotLen = 24U;
237             *dataLen = 12U;
238             break;
239         case kESAI_SlotLen24WordLen16:
240             *slotLen = 24U;
241             *dataLen = 16U;
242             break;
243         case kESAI_SlotLen24WordLen20:
244             *slotLen = 24U;
245             *dataLen = 20U;
246             break;
247         case kESAI_SlotLen24WordLen24:
248             *slotLen = 24U;
249             *dataLen = 24U;
250             break;
251         case kESAI_SlotLen32WordLen8:
252             *slotLen = 32U;
253             *dataLen = 8U;
254             break;
255         case kESAI_SlotLen32WordLen12:
256             *slotLen = 32U;
257             *dataLen = 12U;
258             break;
259         case kESAI_SlotLen32WordLen16:
260             *slotLen = 32U;
261             *dataLen = 16U;
262             break;
263         case kESAI_SlotLen32WordLen20:
264             *slotLen = 32U;
265             *dataLen = 20U;
266             break;
267         case kESAI_SlotLen32WordLen24:
268             *slotLen = 32U;
269             *dataLen = 24U;
270             break;
271         default:
272             assert(false);
273             break;
274     }
275 }
276 
ESAI_GetInstance(ESAI_Type * base)277 uint32_t ESAI_GetInstance(ESAI_Type *base)
278 {
279     uint32_t instance;
280 
281     /* Find the instance index from base address mappings. */
282     for (instance = 0; instance < (uint32_t)FSL_FEATURE_SOC_ESAI_COUNT; instance++)
283     {
284         if (s_esaiBases[instance] == base)
285         {
286             break;
287         }
288     }
289 
290     assert(instance < (uint32_t)FSL_FEATURE_SOC_ESAI_COUNT);
291 
292     return instance;
293 }
294 
ESAI_WriteNonBlocking(ESAI_Type * base,uint32_t bitWidth,uint8_t * buffer,uint32_t size)295 static void ESAI_WriteNonBlocking(ESAI_Type *base, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
296 {
297     uint32_t i           = 0;
298     uint8_t j            = 0;
299     uint8_t bytesPerWord = (uint8_t)(bitWidth / 8U);
300     uint32_t data        = 0;
301     uint32_t temp        = 0;
302 
303     for (i = 0; i < size / bytesPerWord; i++)
304     {
305         for (j = 0; j < bytesPerWord; j++)
306         {
307             temp = (uint32_t)(*buffer);
308             data |= (temp << (8U * j));
309             buffer++;
310         }
311         base->ETDR = data;
312         data       = 0;
313     }
314 }
315 
ESAI_ReadNonBlocking(ESAI_Type * base,uint32_t bitWidth,uint8_t * buffer,uint32_t size)316 static void ESAI_ReadNonBlocking(ESAI_Type *base, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
317 {
318     uint32_t i           = 0;
319     uint8_t j            = 0;
320     uint8_t bytesPerWord = (uint8_t)(bitWidth / 8U);
321     uint32_t data        = 0;
322 
323     for (i = 0; i < size / bytesPerWord; i++)
324     {
325         data = base->ERDR;
326         for (j = 0; j < bytesPerWord; j++)
327         {
328             *buffer = (uint8_t)(data >> (8U * j)) & 0xFFU;
329             buffer++;
330         }
331     }
332 }
333 
334 /*!
335  * brief Initializes the ESAI peripheral.
336  *
337  * Ungates the ESAI clock, resets the module, and configures ESAI with a configuration structure.
338  * The configuration structure can be custom filled or set with default values by
339  * ESAI_GetDefaultConfig().
340  *
341  * note  This API should be called at the beginning of the application to use
342  * the ESAI driver. Otherwise, accessing the ESAI module can cause a hard fault
343  * because the clock is not enabled.
344  *
345  * param base ESAI base pointer
346  * param config ESAI configuration structure.
347  */
ESAI_Init(ESAI_Type * base,esai_config_t * config)348 void ESAI_Init(ESAI_Type *base, esai_config_t *config)
349 {
350 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
351     /* Enable the clock. */
352     (void)CLOCK_EnableClock(s_esaiClock[ESAI_GetInstance(base)]);
353 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
354 
355     /* Enable ESAI logic */
356     ESAI_Enable(base, true);
357 
358     /* Reset ESAI internal logic */
359     ESAI_Reset(base);
360 
361     /* ESAI section personal reset, this reset Tx and Rx section at the same time */
362     base->PCRC = 0U;
363     base->PRRC = 0U;
364 
365     /* Automatically init while FIFO enabled */
366     base->TFCR |= ESAI_TFCR_TIEN_MASK;
367 
368     /* Reset ESAI tx and rx FIFO */
369     ESAI_TxReset(base);
370     ESAI_RxReset(base);
371 
372     /* Clear the Transmit and Rececive Slot Mask */
373     ESAI_TxSetSlotMask(base, 0U);
374     EASI_RxSetSlotMask(base, 0U);
375 
376     /* Set sync mode */
377     base->SAICR &= ~ESAI_SAICR_SYN_MASK;
378     base->SAICR |= ESAI_SAICR_SYN(config->syncMode);
379 
380     /* Set master or slave */
381     if (config->master == kESAI_Master)
382     {
383         base->TCCR |= (ESAI_TCCR_TFSD_MASK | ESAI_TCCR_TCKD_MASK);
384         if (config->syncMode == kESAI_ModeAsync)
385         {
386             base->RCCR |= (ESAI_RCCR_RFSD_MASK | ESAI_RCCR_RCKD_MASK);
387         }
388     }
389     else
390     {
391         base->TCCR &= ~(ESAI_TCCR_TFSD_MASK | ESAI_TCCR_TCKD_MASK);
392         if (config->syncMode == kESAI_ModeAsync)
393         {
394             base->RCCR &= ~(ESAI_RCCR_RFSD_MASK | ESAI_RCCR_RCKD_MASK);
395         }
396     }
397 
398     /* Set HCLK direction */
399     base->TCCR |= ESAI_TCCR_THCKD(config->txHckDirection);
400     if (config->syncMode == kESAI_ModeAsync)
401     {
402         base->RCCR |= ESAI_RCCR_RHCKD(config->rxHckDirection);
403         base->ECR |= ESAI_ECR_ERI_MASK;
404     }
405 
406     /* Set HCLK input and output source */
407     base->ECR &= 0xFFF0FFFFU;
408     base->ECR |=
409         (((uint32_t)config->txHckSource << ESAI_ECR_ETI_SHIFT) | ((uint32_t)config->rxHckSource << ESAI_ECR_ERI_SHIFT) |
410          ((uint32_t)config->txHckOutputSource << ESAI_ECR_ETO_SHIFT) |
411          ((uint32_t)config->rxHckOutputSource << ESAI_ECR_ERO_SHIFT));
412 
413     /* Set the audio protocol */
414     ESAI_SetCustomerProtocol(base, config->txProtocol, &config->txCustomer, true);
415     if (config->txProtocol == kESAI_BusI2S)
416     {
417         config->txFsPolarity = kESAI_ClockActiveLow;
418     }
419     base->TCCR &= ~(ESAI_TCCR_THCKP_MASK | ESAI_TCCR_TFSP_MASK | ESAI_TCCR_TCKP_MASK);
420     base->TCCR |= (ESAI_TCCR_THCKP(config->txHckPolarity) | ESAI_TCCR_TFSP(config->txFsPolarity) |
421                    ESAI_TCCR_TCKP(config->txSckPolarity));
422 
423     ESAI_SetCustomerProtocol(base, config->rxProtocol, &config->rxCustomer, false);
424     if (config->rxProtocol == kESAI_BusI2S)
425     {
426         config->rxFsPolarity = kESAI_ClockActiveLow;
427     }
428     base->RCCR &= ~(ESAI_RCCR_RHCKP_MASK | ESAI_RCCR_RFSP_MASK | ESAI_RCCR_RCKP_MASK);
429     base->RCCR |= (ESAI_RCCR_RHCKP(config->rxHckPolarity) | ESAI_RCCR_RFSP(config->rxFsPolarity) |
430                    ESAI_RCCR_RCKP(config->rxSckPolarity));
431 
432     /* Set watermark */
433     base->TFCR &= ~ESAI_TFCR_TFWM_MASK;
434     base->TFCR |= ESAI_TFCR_TFWM(config->txWatermark);
435     base->RFCR &= ~ESAI_RFCR_RFWM_MASK;
436     base->RFCR |= ESAI_RFCR_RFWM(config->rxWatermark);
437 
438     /* Set the pin connection */
439     base->PCRC = 0xFFFU;
440     base->PRRC = 0xFFFU;
441 }
442 
443 /*!
444  * brief De-initializes the ESAI peripheral.
445  *
446  * This API gates the ESAI clock. The ESAI module can't operate unless ESAI_Init
447  * is called to enable the clock.
448  *
449  * param base ESAI base pointer
450  */
ESAI_Deinit(ESAI_Type * base)451 void ESAI_Deinit(ESAI_Type *base)
452 {
453     ESAI_TxEnable(base, 0U);
454     ESAI_RxEnable(base, 0U);
455 
456     /* Disconnect all pins */
457     base->PCRC = 0U;
458     base->PRRC = 0U;
459     ESAI_Enable(base, false);
460 
461 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
462     /* Disable the clock. */
463     (void)CLOCK_DisableClock(s_esaiClock[ESAI_GetInstance(base)]);
464 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
465 }
466 
467 /*!
468  * brief  Sets the ESAI configuration structure to default values.
469  *
470  * This API initializes the configuration structure for use in ESAI_TxConfig().
471  * The initialized structure can remain unchanged in ESAI_Init(), or it can be modified
472  *  before calling ESAI_Init().
473  *
474  * param config pointer to master configuration structure
475  */
ESAI_GetDefaultConfig(esai_config_t * config)476 void ESAI_GetDefaultConfig(esai_config_t *config)
477 {
478     (void)memset(config, 0, sizeof(esai_config_t));
479 
480     config->syncMode          = kESAI_ModeSync;
481     config->txProtocol        = kESAI_BusLeftJustified;
482     config->rxProtocol        = kESAI_BusLeftJustified;
483     config->master            = kESAI_Master;
484     config->txHckDirection    = kESAI_ClockOutput;
485     config->rxHckDirection    = kESAI_ClockOutput;
486     config->txHckSource       = kESAI_HckSourceExternal;
487     config->rxHckSource       = kESAI_HckSourceExternal;
488     config->txHckOutputSource = kESAI_HckSourceInternal;
489     config->rxHckOutputSource = kESAI_HckSourceInternal;
490     config->txHckPolarity     = kESAI_ClockActiveHigh;
491     config->txFsPolarity      = kESAI_ClockActiveHigh;
492     config->txSckPolarity     = kESAI_ClockActiveLow;
493     config->rxHckPolarity     = kESAI_ClockActiveHigh;
494     config->rxFsPolarity      = kESAI_ClockActiveHigh;
495     config->rxSckPolarity     = kESAI_ClockActiveLow;
496     config->txWatermark       = 64;
497     config->rxWatermark       = 64;
498 }
499 
500 /*!
501  * brief Reset ESAI all tx sections.
502  *
503  * This API only resets the core logic of tx and all tx sections.
504  *
505  * param base ESAI base pointer
506  */
ESAI_TxReset(ESAI_Type * base)507 void ESAI_TxReset(ESAI_Type *base)
508 {
509     uint32_t val = 0;
510 
511     val = base->TFCR;
512 
513     /*disable transmit FIFO*/
514     val &= ~ESAI_TFCR_TFE_MASK;
515 
516     /* Disable Tx FIFOs */
517     val &= ~(ESAI_TFCR_TE0_MASK | ESAI_TFCR_TE1_MASK | ESAI_TFCR_TE2_MASK | ESAI_TFCR_TE3_MASK | ESAI_TFCR_TE4_MASK |
518              ESAI_TFCR_TE5_MASK);
519 
520     /* Reset Tx FIFO */
521     val |= ESAI_TFCR_TFR_MASK;
522     base->TFCR = val;
523 
524     /* Clear the tx FIFO reset */
525     base->TFCR &= ~ESAI_TFCR_TFR_MASK;
526 
527     /* Set ESAI Tx to personal reset */
528     base->TCR &= ~(ESAI_TCR_TE0_MASK | ESAI_TCR_TE1_MASK | ESAI_TCR_TE2_MASK | ESAI_TCR_TE3_MASK | ESAI_TCR_TE4_MASK |
529                    ESAI_TCR_TE5_MASK);
530     base->TCR |= ESAI_TCR_TPR_MASK;
531 
532     /* Clear ESAI Rx */
533     base->TCR &= ~ESAI_TCR_TPR_MASK;
534 }
535 
536 /*!
537  * brief Reset ESAI all rx sections.
538  *
539  * This API only resets the core logic of rx and all rx sections.
540  *
541  * param base ESAI base pointer
542  */
ESAI_RxReset(ESAI_Type * base)543 void ESAI_RxReset(ESAI_Type *base)
544 {
545     uint32_t val = 0;
546 
547     val = base->RFCR;
548 
549     /*disable transmit FIFO*/
550     val &= ~ESAI_RFCR_RFE_MASK;
551 
552     /* Disable Tx FIFOs */
553     val &= ~(ESAI_RFCR_RE0_MASK | ESAI_RFCR_RE1_MASK | ESAI_RFCR_RE2_MASK | ESAI_RFCR_RE3_MASK);
554 
555     /* Reset Tx FIFO */
556     val |= ESAI_RFCR_RFR_MASK;
557     base->RFCR = val;
558 
559     /* Clear the tx FIFO reset */
560     base->RFCR &= ~ESAI_RFCR_RFR_MASK;
561 
562     /* Set ESAI Tx to personal reset */
563     base->RCR &= ~(ESAI_RCR_RE0_MASK | ESAI_RCR_RE1_MASK | ESAI_RCR_RE2_MASK | ESAI_RCR_RE3_MASK);
564     base->RCR |= ESAI_RCR_RPR_MASK;
565     base->RCR &= ~ESAI_RCR_RPR_MASK;
566 }
567 
568 /*!
569  * brief Enables/disables ESAI Tx.
570  *
571  * param base ESAI base pointer
572  * param sectionMap Which sections need to be enabled. 0 means all section disabled. This parameter can be a
573  * combination of each sections, every section N is 2^N in section map.
574  */
ESAI_TxEnable(ESAI_Type * base,uint8_t sectionMap)575 void ESAI_TxEnable(ESAI_Type *base, uint8_t sectionMap)
576 {
577     uint32_t val = 0;
578 
579     /* Wait for Tx initialized */
580     if ((base->TFCR & ESAI_TFCR_TIEN_MASK) != 0U)
581     {
582         while ((base->ESR & ESAI_ESR_TINIT_MASK) != 0U)
583         {
584         }
585     }
586 
587     /* Set TCR regsiter */
588     val = base->TCR & ~(ESAI_TCR_TE5_MASK | ESAI_TCR_TE4_MASK | ESAI_TCR_TE3_MASK | ESAI_TCR_TE2_MASK |
589                         ESAI_TCR_TE1_MASK | ESAI_TCR_TE0_MASK);
590     val |= (sectionMap & 0x3FUL) << ESAI_TCR_TE0_SHIFT;
591     base->TCR = val;
592 
593     /* Set TFCR register */
594     val = base->TFCR & ~(ESAI_TFCR_TE5_MASK | ESAI_TFCR_TE4_MASK | ESAI_TFCR_TE3_MASK | ESAI_TFCR_TE2_MASK |
595                          ESAI_TFCR_TE1_MASK | ESAI_TFCR_TE0_MASK);
596     val |= ((sectionMap & 0x3FUL) << ESAI_TFCR_TE0_SHIFT);
597     base->TFCR = val;
598     base->TFCR |= ESAI_TFCR_TFE_MASK;
599 }
600 
601 /*!
602  * brief Enables/disables ESAI Rx.
603  *
604  * param base ESAI base pointer
605  * param sectionMap Which sections need to be enabled. 0 means all section disabled. This parameter can be a
606  * combination of each sections, every section N is 2^N in section map.
607  */
ESAI_RxEnable(ESAI_Type * base,uint8_t sectionMap)608 void ESAI_RxEnable(ESAI_Type *base, uint8_t sectionMap)
609 {
610     uint32_t val = 0;
611 
612     /* Set RCR register */
613     val = base->RCR & ~(ESAI_RCR_RE3_MASK | ESAI_RCR_RE2_MASK | ESAI_RCR_RE1_MASK | ESAI_RCR_RE0_MASK);
614     val |= (sectionMap & 0xFUL) << ESAI_RCR_RE0_SHIFT;
615     base->RCR = val;
616 
617     /* Set RFCR regsiter */
618     val = base->RFCR & ~(ESAI_RFCR_RE3_MASK | ESAI_RFCR_RE2_MASK | ESAI_RFCR_RE1_MASK | ESAI_RFCR_RE0_MASK);
619     val |= ((sectionMap & 0xFUL) << ESAI_RFCR_RE0_SHIFT);
620     base->RFCR = val;
621     base->RFCR |= ESAI_RFCR_RFE_MASK;
622 }
623 
624 /*!
625  * brief Configures the ESAI Tx audio format.
626  *
627  * The audio format can be changed at run-time. This function configures the sample rate and audio data
628  * format to be transferred.
629  *
630  * param base ESAI base pointer.
631  * param format Pointer to ESAI audio data format structure.
632  * param hckClockHz HCK clock frequency in Hz.
633  * param hckSourceClockHz HCK source clock frequency in Hz.
634  */
ESAI_TxSetFormat(ESAI_Type * base,esai_format_t * format,uint32_t hckClockHz,uint32_t hckSourceClockHz)635 void ESAI_TxSetFormat(ESAI_Type *base, esai_format_t *format, uint32_t hckClockHz, uint32_t hckSourceClockHz)
636 {
637     uint8_t slotNum = (uint8_t)((base->TCCR & ESAI_TCCR_TDC_MASK) >> ESAI_TCCR_TDC_SHIFT) + 1U;
638     uint8_t dataLen = 0U, slotLen = 0U;
639     uint32_t sck  = 0U;
640     uint32_t temp = hckSourceClockHz / (hckClockHz * 2U);
641 
642     /* Get ESAI slot length and data length */
643     ESAI_AnalysisSlot(format->slotType, &slotLen, &dataLen);
644     sck = (uint32_t)format->sampleRate_Hz * slotLen * slotNum;
645 
646     /* Set MSB bit of the audio data */
647     base->TCR &= ~ESAI_TCR_TSWS_MASK;
648     base->TCR |= ESAI_TCR_TSWS(format->slotType);
649 
650     /* Set word length and slot length */
651     base->TFCR &= ~ESAI_TFCR_TWA_MASK;
652     base->TFCR |= ESAI_TFCR_TWA((32UL - dataLen) / 4UL);
653 
654     /* Set clock divider */
655     base->TCCR &= ~(ESAI_TCCR_TFP_MASK | ESAI_TCCR_TPM_MASK);
656     base->TCCR |= ESAI_TCCR_TFP(hckClockHz / sck - 1U);
657 
658     /* Set HCKT clock divider */
659     if (temp > 256U)
660     {
661         base->TCCR &= ~ESAI_TCCR_TPSR_MASK;
662         base->TCCR |= ESAI_TCCR_TPM((temp >> 3U) - 1U);
663     }
664     else
665     {
666         base->TCCR |= ESAI_TCCR_TPSR_MASK;
667         base->TCCR |= ESAI_TCCR_TPM(temp - 1U);
668     }
669 }
670 
671 /*!
672  * brief Configures the ESAI Rx audio format.
673  *
674  * The audio format can be changed at run-time. This function configures the sample rate and audio data
675  * format to be transferred.
676  *
677  * param base ESAI base pointer.
678  * param format Pointer to ESAI audio data format structure.
679  * param hckClockHz HCK clock frequency in Hz.
680  * param hckSourceClockHz HCK source clock frequency in Hz.
681  */
ESAI_RxSetFormat(ESAI_Type * base,esai_format_t * format,uint32_t hckClockHz,uint32_t hckSourceClockHz)682 void ESAI_RxSetFormat(ESAI_Type *base, esai_format_t *format, uint32_t hckClockHz, uint32_t hckSourceClockHz)
683 
684 {
685     uint8_t slotNum = (uint8_t)((base->RCCR & ESAI_RCCR_RDC_MASK) >> ESAI_RCCR_RDC_SHIFT) + 1U;
686     uint8_t dataLen = 0U, slotLen = 0U;
687     uint32_t sck  = 0U;
688     uint32_t temp = hckSourceClockHz / (hckClockHz * 2U);
689 
690     /* Get ESAI slot length and data length */
691     ESAI_AnalysisSlot(format->slotType, &slotLen, &dataLen);
692     sck = (uint32_t)format->sampleRate_Hz * slotLen * slotNum;
693 
694     /* MSB bit of the audio data */
695     base->RCR &= ~ESAI_RCR_RSWS_MASK;
696     base->RCR |= ESAI_RCR_RSWS(format->slotType);
697 
698     /* Set word length and slot length */
699     base->RFCR &= ~ESAI_RFCR_RWA_MASK;
700     base->RFCR |= ESAI_RFCR_RWA((32UL - dataLen) / 4UL);
701 
702     /* Only async mode needs to set the clock divider */
703     if ((base->SAICR & ESAI_SAICR_SYN_MASK) == 0U)
704     {
705         /* Set clock divider */
706         base->RCCR &= ~(ESAI_RCCR_RFSP_MASK | ESAI_RCCR_RPM_MASK);
707         base->RCCR |= ESAI_RCCR_RFP(hckClockHz / sck - 1U);
708 
709         /* Set HCKT clock divider */
710         if (temp > 256U)
711         {
712             base->RCCR &= ~ESAI_RCCR_RPSR_MASK;
713             base->RCCR |= ESAI_RCCR_RPM((temp >> 3U) - 1U);
714         }
715         else
716         {
717             base->RCCR |= ESAI_RCCR_RPSR_MASK;
718             base->RCCR |= ESAI_RCCR_RPM(temp - 1U);
719         }
720     }
721 }
722 
723 /*!
724  * brief Sends data using a blocking method.
725  *
726  * note This function blocks by polling until data is ready to be sent.
727  *
728  * param base ESAI base pointer.
729  * param bitWidth How many bits in a audio word, usually 8/16/24 bits.
730  * param buffer Pointer to the data to be written.
731  * param size Bytes to be written.
732  */
ESAI_WriteBlocking(ESAI_Type * base,uint32_t bitWidth,uint8_t * buffer,uint32_t size)733 void ESAI_WriteBlocking(ESAI_Type *base, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
734 {
735     uint32_t i           = 0;
736     uint8_t bytesPerWord = (uint8_t)bitWidth / 8U;
737 
738     while (i < size)
739     {
740         /* Wait until it can write data */
741         while ((ESAI_GetStatusFlag(base) & (uint32_t)kESAI_TransmitFIFOEmptyFlag) == 0U)
742         {
743         }
744 
745         ESAI_WriteNonBlocking(base, bitWidth, buffer, bytesPerWord);
746         buffer = (uint8_t *)((uint32_t)(buffer) + bytesPerWord);
747         i += bytesPerWord;
748     }
749 
750     /* Wait until the last data is sent */
751     while ((base->SAISR & ESAI_SAISR_TDE_MASK) == 0U)
752     {
753     }
754 }
755 
756 /*!
757  * brief Receives data using a blocking method.
758  *
759  * note This function blocks by polling until data is ready to be sent.
760  *
761  * param base ESAI base pointer.
762  * param bitWidth How many bits in a audio word, usually 8/16/24 bits.
763  * param buffer Pointer to the data to be read.
764  * param size Bytes to be read.
765  */
ESAI_ReadBlocking(ESAI_Type * base,uint32_t bitWidth,uint8_t * buffer,uint32_t size)766 void ESAI_ReadBlocking(ESAI_Type *base, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
767 {
768     uint32_t i           = 0;
769     uint8_t bytesPerWord = (uint8_t)bitWidth / 8U;
770 
771     while (i < size)
772     {
773         /* Wait until data is received */
774         while ((ESAI_GetStatusFlag(base) & (uint32_t)kESAI_ReceiveFIFOFullFlag) == 0U)
775         {
776         }
777 
778         ESAI_ReadNonBlocking(base, bitWidth, buffer, bytesPerWord);
779         buffer = (uint8_t *)((uint32_t)(buffer) + bytesPerWord);
780         i += bytesPerWord;
781     }
782 }
783 
784 /*!
785  * brief Initializes the ESAI Tx handle.
786  *
787  * This function initializes the Tx handle for ESAI Tx transactional APIs. Call
788  * this function one time to get the handle initialized.
789  *
790  * param base ESAI base pointer
791  * param handle ESAI handle pointer.
792  * param callback pointer to user callback function
793  * param userData user parameter passed to the callback function
794  */
ESAI_TransferTxCreateHandle(ESAI_Type * base,esai_handle_t * handle,esai_transfer_callback_t callback,void * userData)795 void ESAI_TransferTxCreateHandle(ESAI_Type *base,
796                                  esai_handle_t *handle,
797                                  esai_transfer_callback_t callback,
798                                  void *userData)
799 {
800     assert(handle != NULL);
801 
802     /* Zero the handle */
803     (void)memset(handle, 0, sizeof(*handle));
804 
805     s_esaiHandle[ESAI_GetInstance(base)][0] = handle;
806 
807     handle->callback  = callback;
808     handle->userData  = userData;
809     handle->watermark = (uint8_t)((base->TFCR & ESAI_TFCR_TFWM_MASK) >> ESAI_TFCR_TFWM_SHIFT);
810 
811     /* Set the isr pointer */
812     s_esaiTxIsr = ESAI_TransferTxHandleIRQ;
813 
814     /* Enable Tx irq */
815     (void)EnableIRQ(s_esaiTxIRQ[ESAI_GetInstance(base)]);
816 }
817 
818 /*!
819  * brief Initializes the ESAI Rx handle.
820  *
821  * This function initializes the Rx handle for ESAI Rx transactional APIs. Call
822  * this function one time to get the handle initialized.
823  *
824  * param base ESAI base pointer.
825  * param handle ESAI handle pointer.
826  * param callback pointer to user callback function
827  * param userData user parameter passed to the callback function
828  */
ESAI_TransferRxCreateHandle(ESAI_Type * base,esai_handle_t * handle,esai_transfer_callback_t callback,void * userData)829 void ESAI_TransferRxCreateHandle(ESAI_Type *base,
830                                  esai_handle_t *handle,
831                                  esai_transfer_callback_t callback,
832                                  void *userData)
833 {
834     assert(handle != NULL);
835 
836     /* Zero the handle */
837     (void)memset(handle, 0, sizeof(*handle));
838 
839     s_esaiHandle[ESAI_GetInstance(base)][1] = handle;
840 
841     handle->callback  = callback;
842     handle->userData  = userData;
843     handle->watermark = (uint8_t)((base->RFCR & ESAI_RFCR_RFWM_MASK) >> ESAI_RFCR_RFWM_SHIFT);
844 
845     /* Set the isr pointer */
846     s_esaiRxIsr = ESAI_TransferRxHandleIRQ;
847 
848     /* Enable Rx irq */
849     (void)EnableIRQ(s_esaiRxIRQ[ESAI_GetInstance(base)]);
850 }
851 
852 /*!
853  * brief Configures the ESAI Tx audio format.
854  *
855  * The audio format can be changed at run-time. This function configures the sample rate and audio data
856  * format to be transferred.
857  *
858  * param base ESAI base pointer.
859  * param handle ESAI handle pointer.
860  * param format Pointer to ESAI audio data format structure.
861  * param hckClockHz HCK clock frequency in Hz.
862  * param hckSourceClockHz HCK clock source frequency in Hz.
863  * return Status of this function. Return value is one of status_t.
864  */
ESAI_TransferTxSetFormat(ESAI_Type * base,esai_handle_t * handle,esai_format_t * format,uint32_t hckClockHz,uint32_t hckSourceClockHz)865 status_t ESAI_TransferTxSetFormat(
866     ESAI_Type *base, esai_handle_t *handle, esai_format_t *format, uint32_t hckClockHz, uint32_t hckSourceClockHz)
867 {
868     assert(handle != NULL);
869 
870     if ((hckClockHz < (uint32_t)format->sampleRate_Hz) || (hckSourceClockHz < (uint32_t)format->sampleRate_Hz))
871     {
872         return kStatus_InvalidArgument;
873     }
874 
875     /* Copy format to handle */
876     ESAI_AnalysisSlot(format->slotType, &handle->slotLen, &handle->bitWidth);
877     handle->sectionMap = format->sectionMap;
878 
879     ESAI_TxSetFormat(base, format, hckClockHz, hckSourceClockHz);
880 
881     return kStatus_Success;
882 }
883 
884 /*!
885  * brief Configures the ESAI Rx audio format.
886  *
887  * The audio format can be changed at run-time. This function configures the sample rate and audio data
888  * format to be transferred.
889  *
890  * param base ESAI base pointer.
891  * param handle ESAI handle pointer.
892  * param format Pointer to ESAI audio data format structure.
893  * param hckClockHz HCK clock frequency in Hz.
894  * param hckSourceClockHz HCK clock source frequency in Hz.
895  * return Status of this function. Return value is one of status_t.
896  */
ESAI_TransferRxSetFormat(ESAI_Type * base,esai_handle_t * handle,esai_format_t * format,uint32_t hckClockHz,uint32_t hckSourceClockHz)897 status_t ESAI_TransferRxSetFormat(
898     ESAI_Type *base, esai_handle_t *handle, esai_format_t *format, uint32_t hckClockHz, uint32_t hckSourceClockHz)
899 {
900     assert(handle != NULL);
901 
902     if ((hckClockHz < (uint32_t)format->sampleRate_Hz) || (hckSourceClockHz < (uint32_t)format->sampleRate_Hz))
903     {
904         return kStatus_InvalidArgument;
905     }
906 
907     /* Copy format to handle */
908     ESAI_AnalysisSlot(format->slotType, &handle->slotLen, &handle->bitWidth);
909     handle->sectionMap = format->sectionMap;
910 
911     ESAI_RxSetFormat(base, format, hckClockHz, hckSourceClockHz);
912 
913     return kStatus_Success;
914 }
915 
916 /*!
917  * brief Performs an interrupt non-blocking send transfer on ESAI.
918  *
919  * note This API returns immediately after the transfer initiates.
920  * Call the ESAI_TxGetTransferStatusIRQ to poll the transfer status and check whether
921  * the transfer is finished. If the return status is not kStatus_ESAI_Busy, the transfer
922  * is finished.
923  *
924  * param base ESAI base pointer
925  * param handle pointer to esai_handle_t structure which stores the transfer state
926  * param xfer pointer to esai_transfer_t structure
927  * retval kStatus_Success Successfully started the data receive.
928  * retval kStatus_ESAI_TxBusy Previous receive still not finished.
929  * retval kStatus_InvalidArgument The input parameter is invalid.
930  */
ESAI_TransferSendNonBlocking(ESAI_Type * base,esai_handle_t * handle,esai_transfer_t * xfer)931 status_t ESAI_TransferSendNonBlocking(ESAI_Type *base, esai_handle_t *handle, esai_transfer_t *xfer)
932 {
933     assert(handle != NULL);
934 
935     uint32_t i = 0;
936 
937     /* Check if the queue is full */
938     if (handle->esaiQueue[handle->queueUser].data != NULL)
939     {
940         return kStatus_ESAI_QueueFull;
941     }
942 
943     /* Add into queue */
944     handle->transferSize[handle->queueUser]       = xfer->dataSize;
945     handle->esaiQueue[handle->queueUser].data     = xfer->data;
946     handle->esaiQueue[handle->queueUser].dataSize = xfer->dataSize;
947     handle->queueUser                             = (handle->queueUser + 1U) % ESAI_XFER_QUEUE_SIZE;
948 
949     /* Set the state to busy */
950     handle->state = kESAI_Busy;
951 
952     /* Use FIFO request interrupt and fifo error*/
953     ESAI_TxEnableInterrupts(base, kESAI_TransmitInterruptEnable);
954 
955     if ((base->TFSR & ESAI_TFSR_TFCNT_MASK) == 0U)
956     {
957         /* Write first word for all channels*/
958         for (i = 0; i < 12U; i++)
959         {
960             ESAI_WriteData(base, 0);
961             ESAI_WriteData(base, 0);
962         }
963     }
964 
965     /* Enable Tx transfer */
966     ESAI_TxEnable(base, handle->sectionMap);
967 
968     return kStatus_Success;
969 }
970 
971 /*!
972  * brief Performs an interrupt non-blocking receive transfer on ESAI.
973  *
974  * note This API returns immediately after the transfer initiates.
975  * Call the ESAI_RxGetTransferStatusIRQ to poll the transfer status and check whether
976  * the transfer is finished. If the return status is not kStatus_ESAI_Busy, the transfer
977  * is finished.
978  *
979  * param base ESAI base pointer
980  * param handle pointer to esai_handle_t structure which stores the transfer state
981  * param xfer pointer to esai_transfer_t structure
982  * retval kStatus_Success Successfully started the data receive.
983  * retval kStatus_ESAI_RxBusy Previous receive still not finished.
984  * retval kStatus_InvalidArgument The input parameter is invalid.
985  */
ESAI_TransferReceiveNonBlocking(ESAI_Type * base,esai_handle_t * handle,esai_transfer_t * xfer)986 status_t ESAI_TransferReceiveNonBlocking(ESAI_Type *base, esai_handle_t *handle, esai_transfer_t *xfer)
987 {
988     assert(handle != NULL);
989 
990     /* Check if the queue is full */
991     if (handle->esaiQueue[handle->queueUser].data != NULL)
992     {
993         return kStatus_ESAI_QueueFull;
994     }
995 
996     /* Add into queue */
997     handle->transferSize[handle->queueUser]       = xfer->dataSize;
998     handle->esaiQueue[handle->queueUser].data     = xfer->data;
999     handle->esaiQueue[handle->queueUser].dataSize = xfer->dataSize;
1000     handle->queueUser                             = (handle->queueUser + 1U) % ESAI_XFER_QUEUE_SIZE;
1001 
1002     /* Set state to busy */
1003     handle->state = kESAI_Busy;
1004 
1005     /* Use FIFO request interrupt and fifo error*/
1006     ESAI_RxEnableInterrupts(base, kESAI_TransmitInterruptEnable);
1007 
1008     /* Enable Rx transfer */
1009     ESAI_RxEnable(base, handle->sectionMap);
1010 
1011     return kStatus_Success;
1012 }
1013 
1014 /*!
1015  * brief Gets a set byte count.
1016  *
1017  * param base ESAI base pointer.
1018  * param handle pointer to esai_handle_t structure which stores the transfer state.
1019  * param count Bytes count sent.
1020  * retval kStatus_Success Succeed get the transfer count.
1021  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1022  */
ESAI_TransferGetSendCount(ESAI_Type * base,esai_handle_t * handle,size_t * count)1023 status_t ESAI_TransferGetSendCount(ESAI_Type *base, esai_handle_t *handle, size_t *count)
1024 {
1025     assert(handle != NULL);
1026 
1027     status_t status = kStatus_Success;
1028 
1029     if (handle->state != (uint32_t)kESAI_Busy)
1030     {
1031         status = kStatus_NoTransferInProgress;
1032     }
1033     else
1034     {
1035         *count = (handle->transferSize[handle->queueDriver] - handle->esaiQueue[handle->queueDriver].dataSize);
1036     }
1037 
1038     return status;
1039 }
1040 
1041 /*!
1042  * brief Gets a received byte count.
1043  *
1044  * param base ESAI base pointer.
1045  * param handle pointer to esai_handle_t structure which stores the transfer state.
1046  * param count Bytes count received.
1047  * retval kStatus_Success Succeed get the transfer count.
1048  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1049  */
ESAI_TransferGetReceiveCount(ESAI_Type * base,esai_handle_t * handle,size_t * count)1050 status_t ESAI_TransferGetReceiveCount(ESAI_Type *base, esai_handle_t *handle, size_t *count)
1051 {
1052     assert(handle != NULL);
1053 
1054     status_t status = kStatus_Success;
1055 
1056     if (handle->state != (uint32_t)kESAI_Busy)
1057     {
1058         status = kStatus_NoTransferInProgress;
1059     }
1060     else
1061     {
1062         *count = (handle->transferSize[handle->queueDriver] - handle->esaiQueue[handle->queueDriver].dataSize);
1063     }
1064 
1065     return status;
1066 }
1067 
1068 /*!
1069  * brief Aborts the current send.
1070  *
1071  * note This API can be called any time when an interrupt non-blocking transfer initiates
1072  * to abort the transfer early.
1073  *
1074  * param base ESAI base pointer.
1075  * param handle pointer to esai_handle_t structure which stores the transfer state.
1076  */
ESAI_TransferAbortSend(ESAI_Type * base,esai_handle_t * handle)1077 void ESAI_TransferAbortSend(ESAI_Type *base, esai_handle_t *handle)
1078 {
1079     assert(handle != NULL);
1080 
1081     /* Stop Tx transfer and disable interrupt */
1082     ESAI_TxEnable(base, 0U);
1083 
1084     /* Use FIFO request interrupt and fifo error */
1085     ESAI_TxDisableInterrupts(base, kESAI_TransmitInterruptEnable);
1086 
1087     handle->state = kESAI_Idle;
1088 
1089     /* Clear the queue */
1090     (void)memset(handle->esaiQueue, 0, sizeof(esai_transfer_t) * ESAI_XFER_QUEUE_SIZE);
1091     handle->queueDriver = 0;
1092     handle->queueUser   = 0;
1093 }
1094 
1095 /*!
1096  * brief Aborts the current IRQ receive.
1097  *
1098  * note This API can be called any time when an interrupt non-blocking transfer initiates
1099  * to abort the transfer early.
1100  *
1101  * param base ESAI base pointer
1102  * param handle pointer to esai_handle_t structure which stores the transfer state.
1103  */
ESAI_TransferAbortReceive(ESAI_Type * base,esai_handle_t * handle)1104 void ESAI_TransferAbortReceive(ESAI_Type *base, esai_handle_t *handle)
1105 {
1106     assert(handle != NULL);
1107 
1108     /* Stop Tx transfer and disable interrupt */
1109     ESAI_RxEnable(base, 0U);
1110 
1111     /* Use FIFO request interrupt and fifo error */
1112     ESAI_RxDisableInterrupts(base, kESAI_TransmitInterruptEnable);
1113 
1114     handle->state = kESAI_Idle;
1115 
1116     /* Clear the queue */
1117     (void)memset(handle->esaiQueue, 0, sizeof(esai_transfer_t) * ESAI_XFER_QUEUE_SIZE);
1118     handle->queueDriver = 0;
1119     handle->queueUser   = 0;
1120 }
1121 
1122 /*!
1123  * brief Tx interrupt handler.
1124  *
1125  * param base ESAI base pointer.
1126  * param handle pointer to esai_handle_t structure.
1127  */
ESAI_TransferTxHandleIRQ(ESAI_Type * base,esai_handle_t * handle)1128 void ESAI_TransferTxHandleIRQ(ESAI_Type *base, esai_handle_t *handle)
1129 {
1130     assert(handle != NULL);
1131 
1132     uint8_t *buffer  = handle->esaiQueue[handle->queueDriver].data;
1133     uint8_t dataSize = handle->bitWidth / 8U;
1134 
1135     /* Handle transfer */
1136     if ((ESAI_GetStatusFlag(base) & (uint32_t)kESAI_TransmitFIFOEmptyFlag) != 0U)
1137     {
1138         /* Judge if the data need to transmit is less than space */
1139         size_t size = MIN((handle->esaiQueue[handle->queueDriver].dataSize),
1140                           (size_t)(((uint32_t)FSL_FEATURE_ESAI_FIFO_SIZEn(base) - handle->watermark) * dataSize));
1141 
1142         /* Copy the data from esai buffer to FIFO */
1143         ESAI_WriteNonBlocking(base, handle->bitWidth, buffer, size);
1144 
1145         /* Update the internal counter */
1146         handle->esaiQueue[handle->queueDriver].dataSize -= size;
1147         handle->esaiQueue[handle->queueDriver].data =
1148             (uint8_t *)((uint32_t)handle->esaiQueue[handle->queueDriver].data + size);
1149     }
1150 
1151     /* If finished a block, call the callback function */
1152     if (handle->esaiQueue[handle->queueDriver].dataSize == 0U)
1153     {
1154         (void)memset(&handle->esaiQueue[handle->queueDriver], 0, sizeof(esai_transfer_t));
1155         handle->queueDriver = (handle->queueDriver + 1U) % ESAI_XFER_QUEUE_SIZE;
1156         if (handle->callback != NULL)
1157         {
1158             (handle->callback)(base, handle, kStatus_ESAI_TxIdle, handle->userData);
1159         }
1160     }
1161 
1162     /* If all data finished, just stop the transfer */
1163     if (handle->esaiQueue[handle->queueDriver].data == NULL)
1164     {
1165         /* Only async mode shall disable Tx */
1166         if ((base->SAICR & ESAI_SAICR_SYN_MASK) == 0U)
1167         {
1168             ESAI_TransferAbortSend(base, handle);
1169         }
1170     }
1171 }
1172 
1173 /*!
1174  * brief Tx interrupt handler.
1175  *
1176  * param base ESAI base pointer.
1177  * param handle pointer to esai_handle_t structure.
1178  */
ESAI_TransferRxHandleIRQ(ESAI_Type * base,esai_handle_t * handle)1179 void ESAI_TransferRxHandleIRQ(ESAI_Type *base, esai_handle_t *handle)
1180 {
1181     assert(handle != NULL);
1182 
1183     uint8_t *buffer  = handle->esaiQueue[handle->queueDriver].data;
1184     uint8_t dataSize = handle->bitWidth / 8U;
1185 
1186     /* Handle transfer */
1187     if ((ESAI_GetStatusFlag(base) & (uint32_t)kESAI_ReceiveFIFOFullFlag) != 0U)
1188     {
1189         /* Judge if the data need to transmit is less than space */
1190         size_t size = MIN((handle->esaiQueue[handle->queueDriver].dataSize), (handle->watermark * (uint32_t)dataSize));
1191 
1192         /* Copy the data from esai buffer to FIFO */
1193         ESAI_ReadNonBlocking(base, handle->bitWidth, buffer, size);
1194 
1195         /* Update the internal counter */
1196         handle->esaiQueue[handle->queueDriver].dataSize -= size;
1197         handle->esaiQueue[handle->queueDriver].data =
1198             (uint8_t *)((uint32_t)handle->esaiQueue[handle->queueDriver].data + size);
1199     }
1200 
1201     /* If finished a block, call the callback function */
1202     if (handle->esaiQueue[handle->queueDriver].dataSize == 0U)
1203     {
1204         (void)memset(&handle->esaiQueue[handle->queueDriver], 0, sizeof(esai_transfer_t));
1205         handle->queueDriver = (handle->queueDriver + 1U) % ESAI_XFER_QUEUE_SIZE;
1206         if (handle->callback != NULL)
1207         {
1208             (handle->callback)(base, handle, kStatus_ESAI_RxIdle, handle->userData);
1209         }
1210     }
1211 
1212     /* If all data finished, just stop the transfer */
1213     if (handle->esaiQueue[handle->queueDriver].data == NULL)
1214     {
1215         ESAI_TransferAbortReceive(base, handle);
1216     }
1217 }
1218 
1219 #ifdef AUDIO__ESAI0
1220 #define ESAI AUDIO__ESAI0
1221 #endif
1222 #ifdef ADMA__ESAI0
1223 #define ESAI ADMA__ESAI0
1224 #endif
1225 #if defined(ESAI)
1226 #define ESAI_DriverIRQHandler AUDIO_ESAI0_INT_IRQHandler
1227 void ESAI_DriverIRQHandler(void);
ESAI_DriverIRQHandler(void)1228 void ESAI_DriverIRQHandler(void)
1229 {
1230     /* Handle Rx operation */
1231     if (((ESAI_GetStatusFlag(ESAI) & (uint32_t)kESAI_ReceiveFIFOFullFlag) != 0U) &&
1232         ((ESAI->RCR & (uint32_t)kESAI_TransmitInterruptEnable) != 0U))
1233     {
1234         s_esaiRxIsr(ESAI, s_esaiHandle[0][1]);
1235     }
1236 
1237     /* Handle Tx operation */
1238     if (((ESAI_GetStatusFlag(ESAI) & (uint32_t)kESAI_TransmitFIFOEmptyFlag) != 0U) &&
1239         ((ESAI->TCR & (uint32_t)kESAI_TransmitInterruptEnable) != 0U))
1240     {
1241         s_esaiTxIsr(ESAI, s_esaiHandle[0][0]);
1242     }
1243     SDK_ISR_EXIT_BARRIER;
1244 }
1245 #endif
1246 
1247 #if defined(AUDIO__ESAI1)
1248 #define ESAI1 AUDIO__ESAI1
AUDIO_ESAI1_INT_IRQHandler(void)1249 void AUDIO_ESAI1_INT_IRQHandler(void)
1250 {
1251     /* Handle Rx operation */
1252     if (((ESAI_GetStatusFlag(ESAI1) & (uint32_t)kESAI_ReceiveFIFOFullFlag) != 0U) &&
1253         ((ESAI1->RCR & (uint32_t)kESAI_TransmitInterruptEnable) != 0U))
1254     {
1255         s_esaiRxIsr(ESAI1, s_esaiHandle[1][1]);
1256     }
1257 
1258     /* Handle Tx operation */
1259     if (((ESAI_GetStatusFlag(ESAI1) & (uint32_t)kESAI_TransmitFIFOEmptyFlag) != 0U) &&
1260         ((ESAI1->TCR & (uint32_t)kESAI_TransmitInterruptEnable) != 0U))
1261     {
1262         s_esaiTxIsr(ESAI1, s_esaiHandle[1][0]);
1263     }
1264     SDK_ISR_EXIT_BARRIER;
1265 }
1266 #endif
1267