1 /*
2 * Copyright 2019-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_asrc.h"
9
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.asrc"
13 #endif
14
15 /*******************************************************************************
16 * Definitations
17 ******************************************************************************/
18 /*! @brief Typedef for asrc tx interrupt handler. */
19 typedef void (*asrc_isr_t)(ASRC_Type *base, asrc_handle_t *asrcHandle);
20 /*! @brief ASRC support maximum channel number */
21 #define ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMER (10U)
22 #define ASRC_SAMPLE_RATIO_DECIMAL_DEPTH (26U)
23 /*******************************************************************************
24 * Prototypes
25 ******************************************************************************/
26 /*!
27 * @brief ASRC read non blocking.
28 *
29 * @param base ASRC base pointer.
30 * @param channelPair ASRC channel pair.
31 * @param destAddress dest buffer address.
32 * @param samples number of samples to read.
33 * @param sampleWidth the width that one sample takes.
34 */
35 static void ASRC_ReadNonBlocking(
36 ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *destAddress, uint32_t samples, uint32_t sampleWidth);
37
38 /*!
39 * @brief ASRC write non blocking.
40 *
41 * @param base ASRC base pointer.
42 * @param channelPair ASRC channel pair.
43 * @param srcAddress source buffer address.
44 * @param samples number of samples to read.
45 * @param sampleMask the mask of sample data.
46 * @param sampleWidth the width that one sample takes.
47 */
48 static void ASRC_WriteNonBlocking(ASRC_Type *base,
49 asrc_channel_pair_t channelPair,
50 const uint32_t *srcAddress,
51 uint32_t samples,
52 uint32_t sampleMask,
53 uint32_t sampleWidth);
54
55 /*!
56 * @brief ASRC calculate divider and prescaler.
57 *
58 * @param sampleRate_Hz sample rate.
59 * @param sourceClock_Hz source clock.
60 */
61 static uint32_t ASRC_CalculateClockDivider(uint32_t sampleRate_Hz, uint32_t sourceClock_Hz);
62
63 /*!
64 * @brief ASRC pre/post processing selection.
65 *
66 * @param inSampleRate in audio data sample rate.
67 * @param outSampleRate out audio data sample rate.
68 * @param preProc pre processing selection.
69 * @param postProc post precessing selection.
70 */
71 static status_t ASRC_ProcessSelection(uint32_t inSampleRate,
72 uint32_t outSampleRate,
73 uint32_t *preProc,
74 uint32_t *postProc);
75 /*******************************************************************************
76 * Variables
77 ******************************************************************************/
78 /* Base pointer array */
79 static ASRC_Type *const s_asrcBases[] = ASRC_BASE_PTRS;
80 /*!@brief asrc handle pointer */
81 static asrc_handle_t *s_asrcHandle[ARRAY_SIZE(s_asrcBases)][FSL_ASRC_CHANNEL_PAIR_COUNT];
82 /* IRQ number array */
83 static const IRQn_Type s_asrcIRQ[] = ASRC_IRQS;
84
85 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
86 /* Clock name array */
87 static const clock_ip_name_t s_asrcClock[] = ASRC_CLOCKS;
88 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
89 /*! @brief Pointer to IRQ handler for each instance. */
90 static asrc_isr_t s_asrcIsr;
91 /*******************************************************************************
92 * Code
93 ******************************************************************************/
ASRC_GetInstance(ASRC_Type * base)94 uint32_t ASRC_GetInstance(ASRC_Type *base)
95 {
96 uint32_t instance;
97
98 /* Find the instance index from base address mappings. */
99 for (instance = 0; instance < ARRAY_SIZE(s_asrcBases); instance++)
100 {
101 if (s_asrcBases[instance] == base)
102 {
103 break;
104 }
105 }
106
107 assert(instance < ARRAY_SIZE(s_asrcBases));
108
109 return instance;
110 }
111
ASRC_ReadNonBlocking(ASRC_Type * base,asrc_channel_pair_t channelPair,uint32_t * destAddress,uint32_t samples,uint32_t sampleWidth)112 static void ASRC_ReadNonBlocking(
113 ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *destAddress, uint32_t samples, uint32_t sampleWidth)
114 {
115 uint32_t i = 0U;
116 uint32_t *destAddr = destAddress;
117 volatile uint32_t *srcAddr = ASRC_ASRDO_ADDR(base, channelPair);
118
119 for (i = 0U; i < samples; i++)
120 {
121 *destAddr = *srcAddr;
122 destAddr = (uint32_t *)((uint32_t)destAddr + sampleWidth);
123 }
124 }
125
ASRC_WriteNonBlocking(ASRC_Type * base,asrc_channel_pair_t channelPair,const uint32_t * srcAddress,uint32_t samples,uint32_t sampleMask,uint32_t sampleWidth)126 static void ASRC_WriteNonBlocking(ASRC_Type *base,
127 asrc_channel_pair_t channelPair,
128 const uint32_t *srcAddress,
129 uint32_t samples,
130 uint32_t sampleMask,
131 uint32_t sampleWidth)
132 {
133 uint32_t i = 0U;
134 const uint32_t *srcAddr = srcAddress;
135 volatile uint32_t *destAddr = ASRC_ASRDI_ADDR(base, channelPair);
136
137 for (i = 0U; i < samples; i++)
138 {
139 *destAddr = *srcAddr & sampleMask;
140 srcAddr = (uint32_t *)((uint32_t)srcAddr + sampleWidth);
141 }
142 }
143
ASRC_CalculateClockDivider(uint32_t sampleRate_Hz,uint32_t sourceClock_Hz)144 static uint32_t ASRC_CalculateClockDivider(uint32_t sampleRate_Hz, uint32_t sourceClock_Hz)
145 {
146 assert(sourceClock_Hz >= sampleRate_Hz);
147
148 uint32_t divider = sourceClock_Hz / sampleRate_Hz;
149 uint32_t prescaler = 0U;
150
151 /* sourceClock_Hz = sampleRate_Hz * divider * (2 ^ prescaler) */
152 while (divider > 8U)
153 {
154 divider >>= 1U;
155 prescaler++;
156 }
157 /* Hardware limitation:
158 * If the prescaler is set to 1, the clock divider can only be set to 1 and the clock source must have a 50% duty
159 * cycle
160 */
161 if ((prescaler == 1U) && (divider != 1U))
162 {
163 divider >>= 1U;
164 prescaler++;
165 }
166 /* fine tuning */
167 if (sourceClock_Hz / ((1UL << prescaler) * divider) > sampleRate_Hz)
168 {
169 divider++;
170 }
171
172 return ((divider - 1U) << 3U) | (prescaler & 0x7U);
173 }
174
ASRC_ProcessSelection(uint32_t inSampleRate,uint32_t outSampleRate,uint32_t * preProc,uint32_t * postProc)175 static status_t ASRC_ProcessSelection(uint32_t inSampleRate,
176 uint32_t outSampleRate,
177 uint32_t *preProc,
178 uint32_t *postProc)
179 {
180 bool op2Cond = false;
181 bool op0Cond = false;
182
183 op2Cond = (((inSampleRate * 15U > outSampleRate * 16U) && (outSampleRate < 56000U)) ||
184 ((inSampleRate > 56000U) && (outSampleRate < 56000U)));
185 op0Cond = (inSampleRate * 23U < outSampleRate * 8U);
186
187 /* preProc == 4 or preProc == 5 is not support now */
188 if ((inSampleRate * 8U > 129U * outSampleRate) || ((inSampleRate * 8U > 65U * outSampleRate)))
189 {
190 return kStatus_ASRCNotSupport;
191 }
192
193 if (inSampleRate * 8U > 33U * outSampleRate)
194 {
195 *preProc = 2U;
196 }
197 else if (inSampleRate * 8U > 15U * outSampleRate)
198 {
199 if (inSampleRate > 152000U)
200 {
201 *preProc = 2U;
202 }
203 else
204 {
205 *preProc = 1U;
206 }
207 }
208 else if (inSampleRate < 76000U)
209 {
210 *preProc = 0;
211 }
212 else if (inSampleRate > 152000U)
213 {
214 *preProc = 2;
215 }
216 else
217 {
218 *preProc = 1;
219 }
220
221 if (op2Cond)
222 {
223 *postProc = 2;
224 }
225 else if (op0Cond)
226 {
227 *postProc = 0;
228 }
229 else
230 {
231 *postProc = 1;
232 }
233
234 return kStatus_Success;
235 }
236
237 /*!
238 * brief Map register sample width to real sample width.
239 *
240 * note This API is depends on the ASRC configuration, should be called after the ASRC_SetChannelPairConfig.
241 * param base asrc base pointer.
242 * param channelPair asrc channel pair index.
243 * param inWidth ASRC channel pair number.
244 * param outWidth input sample rate.
245 * retval input sample mask value.
246 */
ASRC_MapSamplesWidth(ASRC_Type * base,asrc_channel_pair_t channelPair,uint32_t * inWidth,uint32_t * outWidth)247 uint32_t ASRC_MapSamplesWidth(ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *inWidth, uint32_t *outWidth)
248 {
249 uint32_t sampleMask = 0U,
250 inRegWidth = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_IWD_MASK) >> ASRC_ASRMCR1_IWD_SHIFT,
251 outRegWidth = ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_OW16_MASK,
252 inDataAlign = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_IMSB_MASK) >> ASRC_ASRMCR1_IMSB_SHIFT,
253 outDataAlign = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_OMSB_MASK) >> ASRC_ASRMCR1_OMSB_SHIFT;
254 /* get in sample width */
255 if (inRegWidth == (uint32_t)kASRC_DataWidth8Bit)
256 {
257 *inWidth = 1U;
258 sampleMask = 0xFFU;
259 if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
260 {
261 *inWidth = 2U;
262 sampleMask = 0xFF00U;
263 }
264 }
265 else if (inRegWidth == (uint32_t)kASRC_DataWidth16Bit)
266 {
267 *inWidth = 2U;
268 sampleMask = 0xFFFFU;
269 if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
270 {
271 *inWidth = 4U;
272 sampleMask = 0xFFFF0000U;
273 }
274 }
275 else
276 {
277 *inWidth = 3U;
278 sampleMask = 0xFFFFFFU;
279
280 if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
281 {
282 sampleMask = 0xFFFFFF00U;
283 *inWidth = 4U;
284 }
285 }
286 /* get out sample width */
287 if (outRegWidth == (uint32_t)kASRC_DataWidth16Bit)
288 {
289 *outWidth = 2U;
290 if (outDataAlign == (uint32_t)kASRC_DataAlignMSB)
291 {
292 *outWidth = 4U;
293 }
294 }
295 else
296 {
297 *outWidth = 4U;
298 }
299
300 return sampleMask;
301 }
302
303 /*!
304 * brief ASRC configure ideal ratio.
305 * The ideal ratio should be used when input clock source is not avalible.
306 *
307 * param base ASRC base pointer.
308 * param channelPair ASRC channel pair.
309 * param inputSampleRate input audio data sample rate.
310 * param outputSampleRate output audio data sample rate.
311 */
ASRC_SetIdealRatioConfig(ASRC_Type * base,asrc_channel_pair_t channelPair,uint32_t inputSampleRate,uint32_t outputSampleRate)312 status_t ASRC_SetIdealRatioConfig(ASRC_Type *base,
313 asrc_channel_pair_t channelPair,
314 uint32_t inputSampleRate,
315 uint32_t outputSampleRate)
316 {
317 uint32_t ratio = 0U, i = 0U;
318 uint32_t preProc = 0U, postProc = 0U;
319 uint32_t asrcfg = base->ASRCFG;
320 /* caculate integer part */
321 ratio = (inputSampleRate / outputSampleRate) << ASRC_SAMPLE_RATIO_DECIMAL_DEPTH;
322
323 inputSampleRate %= outputSampleRate;
324 /* get decimal part */
325 for (i = 1U; i <= ASRC_SAMPLE_RATIO_DECIMAL_DEPTH; i++)
326 {
327 inputSampleRate <<= 1;
328
329 if (inputSampleRate < outputSampleRate)
330 {
331 continue;
332 }
333
334 ratio |= 1UL << (ASRC_SAMPLE_RATIO_DECIMAL_DEPTH - i);
335 inputSampleRate -= outputSampleRate;
336
337 if (0U == inputSampleRate)
338 {
339 break;
340 }
341 }
342 /* select pre/post precessing option */
343 if (ASRC_ProcessSelection(inputSampleRate, outputSampleRate, &preProc, &postProc) != kStatus_Success)
344 {
345 return kStatus_ASRCNotSupport;
346 }
347
348 ASRC_IDEAL_RATIO_HIGH(base, channelPair) = ASRC_ASRIDRHA_IDRATIOA_H(ratio >> 24U);
349 ASRC_IDEAL_RATIO_LOW(base, channelPair) = ASRC_ASRIDRLA_IDRATIOA_L(ratio);
350 base->ASRCTR &= ~ASRC_ASRCTR_AT_MASK(channelPair);
351 asrcfg &= ~(ASRC_ASRCFG_PRE_MODE_MASK(channelPair) | ASRC_ASRCFG_POST_MODE_MASK(channelPair));
352 asrcfg |= ASRC_ASRCFG_PRE_MODE(preProc, channelPair) | ASRC_ASRCFG_POST_MODE(postProc, channelPair);
353 base->ASRCFG = asrcfg;
354
355 return kStatus_Success;
356 }
357
358 /*!
359 * brief Initializes the asrc peripheral.
360 *
361 * This API gates the asrc clock. The asrc module can't operate unless ASRC_Init is called to enable the clock.
362 *
363 * param base asrc base pointer.
364 * param asrcPeripheralClock_Hz peripheral clock of ASRC.
365 */
ASRC_Init(ASRC_Type * base,uint32_t asrcPeripheralClock_Hz)366 void ASRC_Init(ASRC_Type *base, uint32_t asrcPeripheralClock_Hz)
367 {
368 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
369 /* Enable the asrc clock */
370 CLOCK_EnableClock(s_asrcClock[ASRC_GetInstance(base)]);
371 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
372
373 /* disable ASRC channel pair, enable ASRC */
374 base->ASRCTR = 1U;
375
376 /* disable all the interrupt */
377 base->ASRIER = 0U;
378
379 #if (defined FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM) && FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM
380 /* set paramter register to default configurations per recommand value in reference manual */
381 base->ASRPM[0] = 0x7fffffU;
382 base->ASRPM[1] = 0x255555U;
383 base->ASRPM[2] = 0xff7280U;
384 base->ASRPM[3] = 0xff7280U;
385 base->ASRPM[4] = 0xff7280U;
386 #else
387 /* set paramter register to default configurations per recommand value in reference manual */
388 base->ASRPMn[0] = 0x7fffffU;
389 base->ASRPMn[1] = 0x255555U;
390 base->ASRPMn[2] = 0xff7280U;
391 base->ASRPMn[3] = 0xff7280U;
392 base->ASRPMn[4] = 0xff7280U;
393 #endif /*FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM*/
394 /* set task queue fifo */
395 base->ASRTFR1 = ASRC_ASRTFR1_TF_BASE(0x7C);
396 /* 76K/56K divider */
397 base->ASR76K = ASRC_ASR76K_ASR76K(asrcPeripheralClock_Hz / 76000U);
398 base->ASR56K = ASRC_ASR56K_ASR56K(asrcPeripheralClock_Hz / 56000U);
399 }
400
401 /*!
402 * brief De-initializes the ASRC peripheral.
403 *
404 * This API gates the ASRC clock and disable ASRC module. The ASRC module can't operate unless ASRC_Init
405 *
406 * param base ASRC base pointer.
407 */
ASRC_Deinit(ASRC_Type * base)408 void ASRC_Deinit(ASRC_Type *base)
409 {
410 /* disable ASRC module */
411 ASRC_ModuleEnable(base, false);
412
413 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
414 CLOCK_DisableClock(s_asrcClock[ASRC_GetInstance(base)]);
415 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
416 }
417
418 /*!
419 * brief Do software reset .
420 *
421 * This software reset bit is self-clear bit, it will generate a software reset signal inside ASRC.
422 * After 9 cycles of the ASRC processing clock, this reset process will stop and this bit will cleared
423 * automatically.
424 *
425 * param base ASRC base pointer
426 */
ASRC_SoftwareReset(ASRC_Type * base)427 void ASRC_SoftwareReset(ASRC_Type *base)
428 {
429 base->ASRCTR |= ASRC_ASRCTR_SRST_MASK;
430 /* polling reset clear automatically */
431 while ((base->ASRCTR & ASRC_ASRCTR_SRST_MASK) != 0U)
432 {
433 }
434 }
435
436 /*!
437 * brief ASRC configure channel pair.
438 *
439 * param base ASRC base pointer.
440 * param channelPair index of channel pair, reference _asrc_channel_pair.
441 * param config ASRC channel pair configuration pointer.
442 * param inputSampleRate in audio data sample rate.
443 * param outSampleRate out audio data sample rate.
444 */
ASRC_SetChannelPairConfig(ASRC_Type * base,asrc_channel_pair_t channelPair,asrc_channel_pair_config_t * config,uint32_t inputSampleRate,uint32_t outputSampleRate)445 status_t ASRC_SetChannelPairConfig(ASRC_Type *base,
446 asrc_channel_pair_t channelPair,
447 asrc_channel_pair_config_t *config,
448 uint32_t inputSampleRate,
449 uint32_t outputSampleRate)
450 {
451 assert(config != NULL);
452
453 if (config->outDataWidth == kASRC_DataWidth8Bit)
454 {
455 return kStatus_InvalidArgument;
456 }
457
458 if (((inputSampleRate < (uint32_t)kASRC_SampleRate_8000HZ) ||
459 (inputSampleRate > (uint32_t)kASRC_SampleRate_192000HZ)) ||
460 ((outputSampleRate < (uint32_t)kASRC_SampleRate_8000HZ) ||
461 (outputSampleRate > (uint32_t)kASRC_SampleRate_192000HZ)) ||
462 (((outputSampleRate > (uint32_t)kASRC_SampleRate_8000HZ) &&
463 (outputSampleRate < (uint32_t)kASRC_SampleRate_30000HZ)) &&
464 (inputSampleRate / outputSampleRate > 8U || outputSampleRate / inputSampleRate > 24U)))
465 {
466 return kStatus_InvalidArgument;
467 }
468
469 uint32_t i = 0U;
470 /* channel pair processing selection and ratio configuration */
471 uint32_t asrctr = base->ASRCTR & (~(ASRC_ASRCTR_AT_MASK(channelPair) | ASRC_ASRCTR_RATIO_MASK(channelPair)));
472 /* use automatic selection for processing option by default */
473 asrctr |= ASRC_ASRCTR_AT_MASK(channelPair);
474 /* ratio configuration */
475 asrctr |= ASRC_ASRCTR_RATIO(config->sampleRateRatio, channelPair);
476 base->ASRCTR = asrctr;
477
478 /* audio data channel counter configurations */
479 uint32_t asrcncr = base->ASRCNCR & (~ASRC_ASRCNCR_CHANNEL_COUNTER_MASK(channelPair));
480 base->ASRCNCR = asrcncr | ASRC_ASRCNCR_CHANNEL_COUNTER(config->audioDataChannels, channelPair);
481
482 /* in clock source and out clock source configurations */
483 uint32_t asrcsr =
484 base->ASRCSR &
485 (~(ASRC_ASRCSR_INPUT_CLOCK_SOURCE_MASK(channelPair) | ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE_MASK(channelPair)));
486 asrcsr |= ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE(config->outClockSource, channelPair);
487 if (config->inClockSource != kASRC_ClockSourceNotAvalible)
488 {
489 asrcsr |= ASRC_ASRCSR_INPUT_CLOCK_SOURCE(config->inClockSource, channelPair);
490 }
491 base->ASRCSR = asrcsr;
492
493 /* clock divider configuration */
494 uint32_t asrcdr =
495 base->ASRCDR1 &
496 (~(ASRC_ASRCDR_INPUT_PRESCALER_MASK(channelPair) | ASRC_ASRCDR_INPUT_DIVIDER_MASK(channelPair) |
497 ASRC_ASRCDR_OUTPUT_PRESCALER_MASK(channelPair) | ASRC_ASRCDR_OUTPUT_DIVIDER_MASK(channelPair)));
498
499 asrcdr |= ASCR_ASRCDR_OUTPUT_CLOCK_DIVIDER_PRESCALER(
500 ASRC_CalculateClockDivider(outputSampleRate, config->outSourceClock_Hz), channelPair);
501 if (config->inClockSource != kASRC_ClockSourceNotAvalible)
502 {
503 asrcdr |= ASCR_ASRCDR_INPUT_CLOCK_DIVIDER_PRESCALER(
504 ASRC_CalculateClockDivider(inputSampleRate, config->inSourceClock_Hz), channelPair);
505 }
506
507 if (channelPair == kASRC_ChannelPairC)
508 {
509 base->ASRCDR2 = asrcdr;
510 }
511 else
512 {
513 base->ASRCDR1 = asrcdr;
514 }
515
516 /* data width/sign extension/data align configuration */
517 ASRC_ASRMCR1(base, channelPair) = ASRC_ASRMCR1_OW16(config->outDataWidth) | ASRC_ASRMCR1_IWD(config->inDataWidth) |
518 ASRC_ASRMCR1_OSGN(config->outSignExtension) |
519 ASRC_ASRMCR1_OMSB(config->outDataAlign) | ASRC_ASRMCR1_IMSB(config->inDataAlign);
520 /* data configurations, MISC */
521 uint32_t asrmcra = ASRC_ASRMCR(base, channelPair) &
522 (~(ASRC_ASRMCRA_BUFSTALLA_MASK | ASRC_ASRMCRA_EXTTHRSHA_MASK |
523 ASRC_ASRMCRA_INFIFO_THRESHOLDA_MASK | ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_MASK));
524 /* buffer stall */
525 asrmcra |= ASRC_ASRMCRA_BUFSTALLA(config->bufStallWhenFifoEmptyFull);
526 /* in fifo and out fifo threshold */
527 asrmcra |= ASRC_ASRMCRA_EXTTHRSHA_MASK | ASRC_ASRMCRA_INFIFO_THRESHOLDA(config->inFifoThreshold - 1UL) |
528 ASRC_ASRMCRA_OUTFIFO_THRESHOLDA(config->outFifoThreshold - 1UL);
529 ASRC_ASRMCR(base, channelPair) = asrmcra;
530
531 if (config->sampleRateRatio == kASRC_RatioUseIdealRatio)
532 {
533 if (ASRC_SetIdealRatioConfig(base, channelPair, inputSampleRate, outputSampleRate) != kStatus_Success)
534 {
535 return kStatus_ASRCChannelPairConfigureFailed;
536 }
537 }
538
539 /* channel pair enable */
540 ASRC_ChannelPairEnable(base, channelPair, true);
541
542 /* wait channel initial served */
543 while (!ASRC_GetChannelPairInitialStatus(base, channelPair))
544 {
545 }
546
547 for (i = 0U; i < (uint32_t)config->audioDataChannels * 4U; i++)
548 {
549 ASRC_ChannelPairWriteData(base, channelPair, 0U);
550 }
551
552 return kStatus_Success;
553 }
554
555 /*!
556 * brief Get output sample buffer size.
557 *
558 * note This API is depends on the ASRC output configuration, should be called after the ASRC_SetChannelPairConfig.
559 *
560 * param base asrc base pointer.
561 * param channelPair ASRC channel pair number.
562 * param inSampleRate input sample rate.
563 * param outSampleRate output sample rate.
564 * param inSamples input sampleS size.
565 * retval output buffer size in byte.
566 */
ASRC_GetOutSamplesSize(ASRC_Type * base,asrc_channel_pair_t channelPair,uint32_t inSampleRate,uint32_t outSampleRate,uint32_t inSamplesize)567 uint32_t ASRC_GetOutSamplesSize(ASRC_Type *base,
568 asrc_channel_pair_t channelPair,
569 uint32_t inSampleRate,
570 uint32_t outSampleRate,
571 uint32_t inSamplesize)
572 {
573 uint32_t inSamples = 0U;
574 uint32_t outSamples = 0U;
575 uint32_t outSamplesBufSize = 0U, audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
576 ;
577 asrc_data_width_t outWdith = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OW16_MASK) == ASRC_ASRMCR1_OW16_MASK ?
578 kASRC_DataWidth16Bit :
579 kASRC_DataWidth24Bit;
580 asrc_data_align_t outAlign = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OMSB_MASK) == ASRC_ASRMCR1_OMSB_MASK ?
581 kASRC_DataAlignMSB :
582 kASRC_DataAlignLSB;
583 uint32_t inWdith = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_IWD_MASK) >> ASRC_ASRMCR1_IWD_SHIFT;
584 asrc_data_align_t inAlign = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_IMSB_MASK) == ASRC_ASRMCR1_IMSB_MASK ?
585 kASRC_DataAlignMSB :
586 kASRC_DataAlignLSB;
587
588 bool signExtend = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OSGN_MASK) == ASRC_ASRMCR1_OSGN_MASK ? true : false;
589
590 /* 24bit input data */
591 if (inWdith == 0U)
592 {
593 inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 4U : 3U);
594 }
595 /* 16bit input data */
596 else if (inWdith == 1U)
597 {
598 inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 4U : 2U);
599 }
600 /* 8bit input data */
601 else
602 {
603 inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 2U : 1U);
604 }
605
606 outSamples = (uint32_t)((uint64_t)inSamples * outSampleRate / inSampleRate);
607 /* make sure output samples is in group */
608 outSamples = outSamples - outSamples % audioChannels;
609
610 if (outWdith == kASRC_DataWidth16Bit)
611 {
612 if ((outAlign == kASRC_DataAlignMSB) || signExtend)
613 {
614 outSamplesBufSize = outSamples * 4U;
615 }
616 else
617 {
618 outSamplesBufSize = outSamples * 2U;
619 }
620 }
621
622 if (outWdith == kASRC_DataWidth24Bit)
623 {
624 outSamplesBufSize = outSamples * 4U;
625 }
626
627 return outSamplesBufSize;
628 }
629
630 /*!
631 * brief Performs an blocking convert on asrc.
632 *
633 * note This API returns immediately after the convert finished.
634 *
635 * param base asrc base pointer.
636 * param channelPair channel pair index.
637 * param xfer Pointer to the ASRC_transfer_t structure.
638 * retval kStatus_Success Successfully started the data receive.
639 */
ASRC_TransferBlocking(ASRC_Type * base,asrc_channel_pair_t channelPair,asrc_transfer_t * xfer)640 status_t ASRC_TransferBlocking(ASRC_Type *base, asrc_channel_pair_t channelPair, asrc_transfer_t *xfer)
641 {
642 assert(xfer != NULL);
643
644 uint32_t inWaterMark = ASRC_ASRMCR(base, channelPair) & ASRC_ASRMCRA_INFIFO_THRESHOLDA_MASK,
645 outWaterMark = (ASRC_ASRMCR(base, channelPair) & ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_MASK) >>
646 ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_SHIFT,
647 audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
648 uint8_t *inAddr = (uint8_t *)xfer->inData, *outAddr = (uint8_t *)xfer->outData;
649 uint32_t onceWriteSamples = 0U;
650 uint32_t status = 0U, inSampleMask = 0U, inSamples = 0U, outSamples = 0U, inWidth = 0U, outWidth = 0U;
651
652 inSampleMask = ASRC_MapSamplesWidth(base, channelPair, &inWidth, &outWidth);
653 inSamples = xfer->inDataSize / inWidth;
654 outSamples = xfer->outDataSize / outWidth;
655 inWaterMark *= audioChannels;
656 outWaterMark *= audioChannels;
657
658 while (outSamples != 0U)
659 {
660 status = ASRC_GetStatus(base);
661
662 if ((status & ((uint32_t)kASRC_StatusPairCInputReady | (uint32_t)kASRC_StatusPairBInputReady |
663 (uint32_t)kASRC_StatusPairAInputReady)) != 0U)
664 {
665 onceWriteSamples =
666 MIN(inSamples, (size_t)((FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH * audioChannels - inWaterMark)));
667 ASRC_WriteNonBlocking(base, channelPair, (uint32_t *)(uint32_t)inAddr, onceWriteSamples, inSampleMask,
668 inWidth);
669 inAddr = (uint8_t *)((uint32_t)inAddr + onceWriteSamples * inWidth);
670 inSamples -= onceWriteSamples;
671 }
672
673 if (outSamples > outWaterMark)
674 {
675 if ((status & ((uint32_t)kASRC_StatusPairCOutputReady | (uint32_t)kASRC_StatusPairAOutputReady |
676 (uint32_t)kASRC_StatusPairBOutputReady)) != 0U)
677 {
678 ASRC_ReadNonBlocking(base, channelPair, (uint32_t *)(uint32_t)outAddr, outWaterMark, outWidth);
679 outAddr = (uint8_t *)((uint32_t)outAddr + outWaterMark * outWidth);
680 outSamples -= outWaterMark;
681 }
682 }
683 else
684 {
685 outSamples -=
686 ASRC_GetRemainFifoSamples(base, channelPair, (uint32_t *)(uint32_t)outAddr, outWidth, outSamples);
687 continue;
688 }
689 }
690
691 return kStatus_Success;
692 }
693
694 /*!
695 * brief ASRC configure channel pair.
696 *
697 * param base ASRC base pointer.
698 * param handle ASRC transactional handle pointer.
699 * param config ASRC channel pair configuration pointer.
700 * param inputSampleRate in audio data sample rate.
701 * param outputSampleRate out audio data sample rate.
702 */
ASRC_TransferSetChannelPairConfig(ASRC_Type * base,asrc_handle_t * handle,asrc_channel_pair_config_t * config,uint32_t inputSampleRate,uint32_t outputSampleRate)703 status_t ASRC_TransferSetChannelPairConfig(ASRC_Type *base,
704 asrc_handle_t *handle,
705 asrc_channel_pair_config_t *config,
706 uint32_t inputSampleRate,
707 uint32_t outputSampleRate)
708 {
709 assert(handle != NULL);
710
711 handle->in.fifoThreshold = config->inFifoThreshold * (uint32_t)config->audioDataChannels;
712 handle->out.fifoThreshold = config->outFifoThreshold * (uint32_t)config->audioDataChannels;
713 handle->audioDataChannels = config->audioDataChannels;
714
715 if (ASRC_SetChannelPairConfig(base, handle->channelPair, config, inputSampleRate, outputSampleRate) !=
716 kStatus_Success)
717 {
718 return kStatus_ASRCChannelPairConfigureFailed;
719 }
720
721 handle->in.sampleMask =
722 ASRC_MapSamplesWidth(base, handle->channelPair, &handle->in.sampleWidth, &handle->out.sampleWidth);
723
724 return kStatus_Success;
725 }
726
727 /*!
728 * brief Get left samples in fifo.
729 *
730 * param base asrc base pointer.
731 * param channelPair ASRC channel pair number.
732 * param buffer input sample numbers.
733 * param outSampleWidth output sample width.
734 * param remainSamples output sample rate.
735 * retval remain samples number.
736 */
ASRC_GetRemainFifoSamples(ASRC_Type * base,asrc_channel_pair_t channelPair,uint32_t * buffer,uint32_t outSampleWidth,uint32_t remainSamples)737 uint32_t ASRC_GetRemainFifoSamples(
738 ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *buffer, uint32_t outSampleWidth, uint32_t remainSamples)
739 {
740 uint32_t remainSamplesInFifo = 0U;
741 uint32_t audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
742 remainSamplesInFifo =
743 ((ASRC_ASRFST_ADDR(base, channelPair) & ASRC_ASRFSTA_OUTFIFO_FILLA_MASK) >> ASRC_ASRFSTA_OUTFIFO_FILLA_SHIFT) *
744 audioChannels;
745
746 if (remainSamples < remainSamplesInFifo)
747 {
748 remainSamplesInFifo = remainSamples;
749 }
750
751 ASRC_ReadNonBlocking(base, channelPair, (uint32_t *)buffer, remainSamplesInFifo, outSampleWidth);
752
753 return remainSamplesInFifo;
754 }
755
756 /*!
757 * brief Initializes the ASRC handle.
758 *
759 * This function initializes the handle for the ASRC transactional APIs. Call
760 * this function once to get the handle initialized.
761 *
762 * param base ASRC base pointer
763 * param handle ASRC handle pointer.
764 * param inCallback Pointer to the user callback function.
765 * param outCallback Pointer to the user callback function.
766 * param userData User parameter passed to the callback function
767 */
ASRC_TransferCreateHandle(ASRC_Type * base,asrc_handle_t * handle,asrc_channel_pair_t channelPair,asrc_transfer_callback_t inCallback,asrc_transfer_callback_t outCallback,void * userData)768 void ASRC_TransferCreateHandle(ASRC_Type *base,
769 asrc_handle_t *handle,
770 asrc_channel_pair_t channelPair,
771 asrc_transfer_callback_t inCallback,
772 asrc_transfer_callback_t outCallback,
773 void *userData)
774 {
775 assert(handle != NULL);
776
777 uint32_t instance = ASRC_GetInstance(base);
778
779 (void)memset(handle, 0, sizeof(*handle));
780
781 s_asrcHandle[instance][channelPair] = handle;
782
783 handle->in.callback = inCallback;
784 handle->out.callback = outCallback;
785 handle->userData = userData;
786 handle->channelPair = channelPair;
787 /* Set the isr pointer */
788 s_asrcIsr = ASRC_TransferHandleIRQ;
789
790 (void)EnableIRQ(s_asrcIRQ[instance]);
791 }
792
793 /*!
794 * brief Performs an interrupt non-blocking convert on asrc.
795 *
796 * note This API returns immediately after the transfer initiates, application should check the wait and check the
797 * callback status.
798 *
799 * param base asrc base pointer.
800 * param handle Pointer to the asrc_handle_t structure which stores the transfer state.
801 * param xfer Pointer to the ASRC_transfer_t structure.
802 * retval kStatus_Success Successfully started the data receive.
803 * retval kStatus_ASRCBusy Previous receive still not finished.
804 */
ASRC_TransferNonBlocking(ASRC_Type * base,asrc_handle_t * handle,asrc_transfer_t * xfer)805 status_t ASRC_TransferNonBlocking(ASRC_Type *base, asrc_handle_t *handle, asrc_transfer_t *xfer)
806 {
807 assert(handle != NULL);
808 assert(xfer != NULL);
809
810 /* Check if the queue is full */
811 if ((handle->in.asrcQueue[handle->in.queueUser] != NULL) || (handle->out.asrcQueue[handle->out.queueUser] != NULL))
812 {
813 return kStatus_ASRCBusy;
814 }
815
816 /* Add into queue */
817 handle->in.transferSamples[handle->in.queueUser] = xfer->inDataSize / handle->in.sampleWidth;
818 handle->in.asrcQueue[handle->in.queueUser] = xfer->inData;
819 handle->in.queueUser = (handle->in.queueUser + 1U) % ASRC_XFER_QUEUE_SIZE;
820
821 handle->out.asrcQueue[handle->out.queueUser] = xfer->outData;
822 handle->out.transferSamples[handle->out.queueUser] = xfer->outDataSize / handle->out.sampleWidth;
823 handle->out.queueUser = (handle->out.queueUser + 1U) % ASRC_XFER_QUEUE_SIZE;
824
825 if (handle->state != (uint32_t)kStatus_ASRCBusy)
826 {
827 /* enable channel pair interrupt */
828 ASRC_EnableInterrupt(base, ASRC_ASRIER_INPUT_INTERRUPT_MASK(handle->channelPair) |
829 (uint32_t)kASRC_OverLoadInterruptMask |
830 ASRC_ASRIER_OUTPUTPUT_INTERRUPT_MASK(handle->channelPair));
831 }
832
833 /* Set the state to busy */
834 handle->state = kStatus_ASRCBusy;
835
836 return kStatus_Success;
837 }
838
839 /*!
840 * brief Gets a set byte count.
841 *
842 * param base asrc base pointer.
843 * param handle Pointer to the ASRC_handle_t structure which stores the transfer state.
844 * param count Bytes count sent.
845 * retval kStatus_Success Succeed get the transfer count.
846 * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
847 */
ASRC_TransferGetConvertedCount(ASRC_Type * base,asrc_handle_t * handle,size_t * count)848 status_t ASRC_TransferGetConvertedCount(ASRC_Type *base, asrc_handle_t *handle, size_t *count)
849 {
850 assert(handle != NULL);
851
852 status_t status = kStatus_Success;
853
854 if (handle->state != (uint32_t)kStatus_ASRCBusy)
855 {
856 status = kStatus_ASRCIdle;
857 }
858 else
859 {
860 *count = handle->out.transferSamples[handle->out.queueDriver];
861 }
862
863 return status;
864 }
865
866 /*!
867 * brief Aborts the current convert.
868 *
869 * note This API can be called any time when an interrupt non-blocking transfer initiates
870 * to abort the transfer early.
871 *
872 * param base asrc base pointer.
873 * param handle Pointer to the ASRC_handle_t structure which stores the transfer state.
874 */
ASRC_TransferAbortConvert(ASRC_Type * base,asrc_handle_t * handle)875 void ASRC_TransferAbortConvert(ASRC_Type *base, asrc_handle_t *handle)
876 {
877 assert(handle != NULL);
878
879 /* enable ASRC module */
880 ASRC_ModuleEnable(base, false);
881
882 handle->state = kStatus_ASRCIdle;
883
884 handle->in.queueDriver = 0;
885 handle->in.queueUser = 0;
886 handle->out.queueDriver = 0;
887 handle->out.queueUser = 0;
888 }
889
890 /*!
891 * brief Terminate all asrc convert.
892 *
893 * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
894 * current transfer slot, please call ASRC_TransferAbortSend.
895 *
896 * param base asrc base pointer.
897 * param handle asrc eDMA handle pointer.
898 */
ASRC_TransferTerminateConvert(ASRC_Type * base,asrc_handle_t * handle)899 void ASRC_TransferTerminateConvert(ASRC_Type *base, asrc_handle_t *handle)
900 {
901 assert(handle != NULL);
902
903 /* Abort the current transfer */
904 ASRC_TransferAbortConvert(base, handle);
905
906 /* Clear all the internal information */
907 (void)memset(handle->in.asrcQueue, 0, sizeof(handle->in.asrcQueue));
908 (void)memset(handle->in.transferSamples, 0, sizeof(handle->in.transferSamples));
909 (void)memset(handle->out.asrcQueue, 0, sizeof(handle->out.asrcQueue));
910 (void)memset(handle->out.transferSamples, 0, sizeof(handle->out.transferSamples));
911 }
912
913 /*!
914 * brief ASRC convert interrupt handler.
915 *
916 * param base asrc base pointer.
917 * param handle Pointer to the asrc_handle_t structure.
918 */
ASRC_TransferHandleIRQ(ASRC_Type * base,asrc_handle_t * handle)919 void ASRC_TransferHandleIRQ(ASRC_Type *base, asrc_handle_t *handle)
920 {
921 assert(handle != NULL);
922
923 uint32_t status = base->ASRSTR;
924
925 /* Handle Error */
926 if ((status & (uint32_t)kASRC_StatusInputError) != 0U)
927 {
928 /* Call the callback */
929 if (handle->in.callback != NULL)
930 {
931 (handle->in.callback)(base, handle, kStatus_ASRCConvertError, handle->userData);
932 }
933 }
934
935 if ((status & (uint32_t)kASRC_StatusOutputError) != 0U)
936 {
937 /* Call the callback */
938 if (handle->out.callback != NULL)
939 {
940 (handle->out.callback)(base, handle, kStatus_ASRCConvertError, handle->userData);
941 }
942 }
943
944 /* Handle transfer */
945 if ((status & ((uint32_t)kASRC_StatusPairCOutputReady | (uint32_t)kASRC_StatusPairAOutputReady |
946 (uint32_t)kASRC_StatusPairBOutputReady)) != 0U)
947 {
948 if (handle->out.transferSamples[handle->out.queueDriver] != 0U)
949 {
950 ASRC_ReadNonBlocking(base, handle->channelPair,
951 (uint32_t *)(uint32_t)handle->out.asrcQueue[handle->out.queueDriver],
952 handle->out.fifoThreshold, handle->out.sampleWidth);
953 handle->out.transferSamples[handle->out.queueDriver] -= handle->out.fifoThreshold;
954 handle->out.asrcQueue[handle->out.queueDriver] =
955 (uint8_t *)((uint32_t)handle->out.asrcQueue[handle->out.queueDriver] +
956 handle->out.fifoThreshold * handle->out.sampleWidth);
957 }
958 }
959
960 if ((status & ((uint32_t)kASRC_StatusPairCInputReady | (uint32_t)kASRC_StatusPairBInputReady |
961 (uint32_t)kASRC_StatusPairAInputReady)) != 0U)
962 {
963 /* Judge if the data need to transmit is less than space */
964 uint32_t size = MIN((handle->in.transferSamples[handle->in.queueDriver]),
965 (size_t)((FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH * (uint32_t)handle->audioDataChannels -
966 handle->in.fifoThreshold)));
967 ASRC_WriteNonBlocking(base, handle->channelPair,
968 (uint32_t *)(uint32_t)handle->in.asrcQueue[handle->in.queueDriver], size,
969 handle->in.sampleMask, handle->in.sampleWidth);
970 handle->in.transferSamples[handle->in.queueDriver] -= size;
971 handle->in.asrcQueue[handle->in.queueDriver] =
972 (uint8_t *)((uint32_t)handle->in.asrcQueue[handle->in.queueDriver] + size * handle->in.sampleWidth);
973 }
974
975 /* If finished a block, call the callback function */
976 if (handle->in.transferSamples[handle->in.queueDriver] == 0U)
977 {
978 handle->in.asrcQueue[handle->in.queueDriver] = NULL;
979 handle->in.queueDriver = (handle->in.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
980 if (handle->in.callback != NULL)
981 {
982 (handle->in.callback)(base, handle, kStatus_ASRCIdle, handle->userData);
983 }
984 }
985
986 if (handle->out.transferSamples[handle->out.queueDriver] < (handle->out.fifoThreshold + 1U))
987 {
988 handle->out.transferSamples[handle->out.queueDriver] -= ASRC_GetRemainFifoSamples(
989 base, handle->channelPair, (uint32_t *)(uint32_t)handle->out.asrcQueue[handle->out.queueDriver],
990 handle->out.sampleWidth, handle->out.transferSamples[handle->out.queueDriver]);
991 }
992
993 if (handle->out.transferSamples[handle->out.queueDriver] == 0U)
994 {
995 handle->out.asrcQueue[handle->out.queueDriver] = NULL;
996 handle->out.queueDriver = (handle->out.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
997 if (handle->out.callback != NULL)
998 {
999 (handle->out.callback)(base, handle, kStatus_ASRCIdle, handle->userData);
1000 }
1001 }
1002
1003 /* If all data finished, just stop the transfer */
1004 if (handle->out.asrcQueue[handle->out.queueDriver] == NULL)
1005 {
1006 ASRC_TransferAbortConvert(base, handle);
1007 }
1008 }
1009
1010 #if defined ASRC
1011 void ASRC_DriverIRQHandler(void);
ASRC_DriverIRQHandler(void)1012 void ASRC_DriverIRQHandler(void)
1013 {
1014 /* channel PAIR A interrupt handling*/
1015 if ((ASRC->ASRSTR & (uint32_t)kASRC_StatusPairAInterrupt) != 0U)
1016 {
1017 s_asrcIsr(ASRC, s_asrcHandle[0][0U]);
1018 }
1019 /* channel PAIR B interrupt handling*/
1020 if ((ASRC->ASRSTR & (uint32_t)kASRC_StatusPairBInterrupt) != 0U)
1021 {
1022 s_asrcIsr(ASRC, s_asrcHandle[0][1U]);
1023 }
1024 /* channel PAIR C interrupt handling*/
1025 if ((ASRC->ASRSTR & (uint32_t)kASRC_StatusPairCInterrupt) != 0U)
1026 {
1027 s_asrcIsr(ASRC, s_asrcHandle[0][2U]);
1028 }
1029 SDK_ISR_EXIT_BARRIER;
1030 }
1031 #endif /* ASRC */
1032