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