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