Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:58

0001 /*
0002  * Copyright 2019-2021 NXP
0003  * All rights reserved.
0004  *
0005  * SPDX-License-Identifier: BSD-3-Clause
0006  */
0007 
0008 #include "fsl_asrc.h"
0009 
0010 /* Component ID definition, used by tools. */
0011 #ifndef FSL_COMPONENT_ID
0012 #define FSL_COMPONENT_ID "platform.drivers.asrc"
0013 #endif
0014 
0015 /*******************************************************************************
0016  * Definitations
0017  ******************************************************************************/
0018 /*! @brief Typedef for asrc tx interrupt handler. */
0019 typedef void (*asrc_isr_t)(ASRC_Type *base, asrc_handle_t *asrcHandle);
0020 /*! @brief ASRC support maximum channel number */
0021 #define ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMER (10U)
0022 #define ASRC_SAMPLE_RATIO_DECIMAL_DEPTH    (26U)
0023 /*******************************************************************************
0024  * Prototypes
0025  ******************************************************************************/
0026 /*!
0027  * @brief ASRC read non blocking.
0028  *
0029  * @param base ASRC base pointer.
0030  * @param channelPair ASRC channel pair.
0031  * @param destAddress dest buffer address.
0032  * @param samples number of samples to read.
0033  * @param sampleWidth the width that one sample takes.
0034  */
0035 static void ASRC_ReadNonBlocking(
0036     ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *destAddress, uint32_t samples, uint32_t sampleWidth);
0037 
0038 /*!
0039  * @brief ASRC write non blocking.
0040  *
0041  * @param base ASRC base pointer.
0042  * @param channelPair ASRC channel pair.
0043  * @param srcAddress source buffer address.
0044  * @param samples number of samples to read.
0045  * @param sampleMask the mask of sample data.
0046  * @param sampleWidth the width that one sample takes.
0047  */
0048 static void ASRC_WriteNonBlocking(ASRC_Type *base,
0049                                   asrc_channel_pair_t channelPair,
0050                                   const uint32_t *srcAddress,
0051                                   uint32_t samples,
0052                                   uint32_t sampleMask,
0053                                   uint32_t sampleWidth);
0054 
0055 /*!
0056  * @brief ASRC calculate divider and prescaler.
0057  *
0058  * @param sampleRate_Hz sample rate.
0059  * @param sourceClock_Hz source clock.
0060  */
0061 static uint32_t ASRC_CalculateClockDivider(uint32_t sampleRate_Hz, uint32_t sourceClock_Hz);
0062 
0063 /*!
0064  * @brief ASRC pre/post processing selection.
0065  *
0066  * @param inSampleRate in audio data sample rate.
0067  * @param outSampleRate out audio data sample rate.
0068  * @param preProc pre processing selection.
0069  * @param postProc post precessing selection.
0070  */
0071 static status_t ASRC_ProcessSelection(uint32_t inSampleRate,
0072                                       uint32_t outSampleRate,
0073                                       uint32_t *preProc,
0074                                       uint32_t *postProc);
0075 /*******************************************************************************
0076  * Variables
0077  ******************************************************************************/
0078 /* Base pointer array */
0079 static ASRC_Type *const s_asrcBases[] = ASRC_BASE_PTRS;
0080 /*!@brief asrc handle pointer */
0081 static asrc_handle_t *s_asrcHandle[ARRAY_SIZE(s_asrcBases)][FSL_ASRC_CHANNEL_PAIR_COUNT];
0082 /* IRQ number array */
0083 static const IRQn_Type s_asrcIRQ[] = ASRC_IRQS;
0084 
0085 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0086 /* Clock name array */
0087 static const clock_ip_name_t s_asrcClock[] = ASRC_CLOCKS;
0088 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0089 /*! @brief Pointer to IRQ handler for each instance. */
0090 static asrc_isr_t s_asrcIsr;
0091 /*******************************************************************************
0092  * Code
0093  ******************************************************************************/
0094 uint32_t ASRC_GetInstance(ASRC_Type *base)
0095 {
0096     uint32_t instance;
0097 
0098     /* Find the instance index from base address mappings. */
0099     for (instance = 0; instance < ARRAY_SIZE(s_asrcBases); instance++)
0100     {
0101         if (s_asrcBases[instance] == base)
0102         {
0103             break;
0104         }
0105     }
0106 
0107     assert(instance < ARRAY_SIZE(s_asrcBases));
0108 
0109     return instance;
0110 }
0111 
0112 static void ASRC_ReadNonBlocking(
0113     ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *destAddress, uint32_t samples, uint32_t sampleWidth)
0114 {
0115     uint32_t i                 = 0U;
0116     uint32_t *destAddr         = destAddress;
0117     volatile uint32_t *srcAddr = ASRC_ASRDO_ADDR(base, channelPair);
0118 
0119     for (i = 0U; i < samples; i++)
0120     {
0121         *destAddr = *srcAddr;
0122         destAddr  = (uint32_t *)((uint32_t)destAddr + sampleWidth);
0123     }
0124 }
0125 
0126 static void ASRC_WriteNonBlocking(ASRC_Type *base,
0127                                   asrc_channel_pair_t channelPair,
0128                                   const uint32_t *srcAddress,
0129                                   uint32_t samples,
0130                                   uint32_t sampleMask,
0131                                   uint32_t sampleWidth)
0132 {
0133     uint32_t i                  = 0U;
0134     const uint32_t *srcAddr     = srcAddress;
0135     volatile uint32_t *destAddr = ASRC_ASRDI_ADDR(base, channelPair);
0136 
0137     for (i = 0U; i < samples; i++)
0138     {
0139         *destAddr = *srcAddr & sampleMask;
0140         srcAddr   = (uint32_t *)((uint32_t)srcAddr + sampleWidth);
0141     }
0142 }
0143 
0144 static uint32_t ASRC_CalculateClockDivider(uint32_t sampleRate_Hz, uint32_t sourceClock_Hz)
0145 {
0146     assert(sourceClock_Hz >= sampleRate_Hz);
0147 
0148     uint32_t divider   = sourceClock_Hz / sampleRate_Hz;
0149     uint32_t prescaler = 0U;
0150 
0151     /* sourceClock_Hz = sampleRate_Hz * divider * (2 ^ prescaler) */
0152     while (divider > 8U)
0153     {
0154         divider >>= 1U;
0155         prescaler++;
0156     }
0157     /* Hardware limitation:
0158      * 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
0159      * cycle
0160      */
0161     if ((prescaler == 1U) && (divider != 1U))
0162     {
0163         divider >>= 1U;
0164         prescaler++;
0165     }
0166     /* fine tuning */
0167     if (sourceClock_Hz / ((1UL << prescaler) * divider) > sampleRate_Hz)
0168     {
0169         divider++;
0170     }
0171 
0172     return ((divider - 1U) << 3U) | (prescaler & 0x7U);
0173 }
0174 
0175 static status_t ASRC_ProcessSelection(uint32_t inSampleRate,
0176                                       uint32_t outSampleRate,
0177                                       uint32_t *preProc,
0178                                       uint32_t *postProc)
0179 {
0180     bool op2Cond = false;
0181     bool op0Cond = false;
0182 
0183     op2Cond = (((inSampleRate * 15U > outSampleRate * 16U) && (outSampleRate < 56000U)) ||
0184                ((inSampleRate > 56000U) && (outSampleRate < 56000U)));
0185     op0Cond = (inSampleRate * 23U < outSampleRate * 8U);
0186 
0187     /* preProc == 4 or preProc == 5 is not support now */
0188     if ((inSampleRate * 8U > 129U * outSampleRate) || ((inSampleRate * 8U > 65U * outSampleRate)))
0189     {
0190         return kStatus_ASRCNotSupport;
0191     }
0192 
0193     if (inSampleRate * 8U > 33U * outSampleRate)
0194     {
0195         *preProc = 2U;
0196     }
0197     else if (inSampleRate * 8U > 15U * outSampleRate)
0198     {
0199         if (inSampleRate > 152000U)
0200         {
0201             *preProc = 2U;
0202         }
0203         else
0204         {
0205             *preProc = 1U;
0206         }
0207     }
0208     else if (inSampleRate < 76000U)
0209     {
0210         *preProc = 0;
0211     }
0212     else if (inSampleRate > 152000U)
0213     {
0214         *preProc = 2;
0215     }
0216     else
0217     {
0218         *preProc = 1;
0219     }
0220 
0221     if (op2Cond)
0222     {
0223         *postProc = 2;
0224     }
0225     else if (op0Cond)
0226     {
0227         *postProc = 0;
0228     }
0229     else
0230     {
0231         *postProc = 1;
0232     }
0233 
0234     return kStatus_Success;
0235 }
0236 
0237 /*!
0238  * brief Map register sample width to real sample width.
0239  *
0240  * note This API is depends on the ASRC configuration, should be called after the ASRC_SetChannelPairConfig.
0241  * param base asrc base pointer.
0242  * param channelPair asrc channel pair index.
0243  * param inWidth ASRC channel pair number.
0244  * param outWidth input sample rate.
0245  * retval input sample mask value.
0246  */
0247 uint32_t ASRC_MapSamplesWidth(ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *inWidth, uint32_t *outWidth)
0248 {
0249     uint32_t sampleMask   = 0U,
0250              inRegWidth   = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_IWD_MASK) >> ASRC_ASRMCR1_IWD_SHIFT,
0251              outRegWidth  = ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_OW16_MASK,
0252              inDataAlign  = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_IMSB_MASK) >> ASRC_ASRMCR1_IMSB_SHIFT,
0253              outDataAlign = (ASRC_ASRMCR1(base, channelPair) & ASRC_ASRMCR1_OMSB_MASK) >> ASRC_ASRMCR1_OMSB_SHIFT;
0254     /* get in sample width */
0255     if (inRegWidth == (uint32_t)kASRC_DataWidth8Bit)
0256     {
0257         *inWidth   = 1U;
0258         sampleMask = 0xFFU;
0259         if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
0260         {
0261             *inWidth   = 2U;
0262             sampleMask = 0xFF00U;
0263         }
0264     }
0265     else if (inRegWidth == (uint32_t)kASRC_DataWidth16Bit)
0266     {
0267         *inWidth   = 2U;
0268         sampleMask = 0xFFFFU;
0269         if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
0270         {
0271             *inWidth   = 4U;
0272             sampleMask = 0xFFFF0000U;
0273         }
0274     }
0275     else
0276     {
0277         *inWidth   = 3U;
0278         sampleMask = 0xFFFFFFU;
0279 
0280         if (inDataAlign == (uint32_t)kASRC_DataAlignMSB)
0281         {
0282             sampleMask = 0xFFFFFF00U;
0283             *inWidth   = 4U;
0284         }
0285     }
0286     /* get out sample width */
0287     if (outRegWidth == (uint32_t)kASRC_DataWidth16Bit)
0288     {
0289         *outWidth = 2U;
0290         if (outDataAlign == (uint32_t)kASRC_DataAlignMSB)
0291         {
0292             *outWidth = 4U;
0293         }
0294     }
0295     else
0296     {
0297         *outWidth = 4U;
0298     }
0299 
0300     return sampleMask;
0301 }
0302 
0303 /*!
0304  * brief ASRC configure ideal ratio.
0305  * The ideal ratio should be used when input clock source is not avalible.
0306  *
0307  * param base ASRC base pointer.
0308  * param channelPair ASRC channel pair.
0309  * param inputSampleRate input audio data sample rate.
0310  * param outputSampleRate output audio data sample rate.
0311  */
0312 status_t ASRC_SetIdealRatioConfig(ASRC_Type *base,
0313                                   asrc_channel_pair_t channelPair,
0314                                   uint32_t inputSampleRate,
0315                                   uint32_t outputSampleRate)
0316 {
0317     uint32_t ratio = 0U, i = 0U;
0318     uint32_t preProc = 0U, postProc = 0U;
0319     uint32_t asrcfg = base->ASRCFG;
0320     /* caculate integer part */
0321     ratio = (inputSampleRate / outputSampleRate) << ASRC_SAMPLE_RATIO_DECIMAL_DEPTH;
0322 
0323     inputSampleRate %= outputSampleRate;
0324     /* get decimal part */
0325     for (i = 1U; i <= ASRC_SAMPLE_RATIO_DECIMAL_DEPTH; i++)
0326     {
0327         inputSampleRate <<= 1;
0328 
0329         if (inputSampleRate < outputSampleRate)
0330         {
0331             continue;
0332         }
0333 
0334         ratio |= 1UL << (ASRC_SAMPLE_RATIO_DECIMAL_DEPTH - i);
0335         inputSampleRate -= outputSampleRate;
0336 
0337         if (0U == inputSampleRate)
0338         {
0339             break;
0340         }
0341     }
0342     /* select pre/post precessing option */
0343     if (ASRC_ProcessSelection(inputSampleRate, outputSampleRate, &preProc, &postProc) != kStatus_Success)
0344     {
0345         return kStatus_ASRCNotSupport;
0346     }
0347 
0348     ASRC_IDEAL_RATIO_HIGH(base, channelPair) = ASRC_ASRIDRHA_IDRATIOA_H(ratio >> 24U);
0349     ASRC_IDEAL_RATIO_LOW(base, channelPair)  = ASRC_ASRIDRLA_IDRATIOA_L(ratio);
0350     base->ASRCTR &= ~ASRC_ASRCTR_AT_MASK(channelPair);
0351     asrcfg &= ~(ASRC_ASRCFG_PRE_MODE_MASK(channelPair) | ASRC_ASRCFG_POST_MODE_MASK(channelPair));
0352     asrcfg |= ASRC_ASRCFG_PRE_MODE(preProc, channelPair) | ASRC_ASRCFG_POST_MODE(postProc, channelPair);
0353     base->ASRCFG = asrcfg;
0354 
0355     return kStatus_Success;
0356 }
0357 
0358 /*!
0359  * brief Initializes the asrc peripheral.
0360  *
0361  * This API gates the asrc clock. The asrc module can't operate unless ASRC_Init is called to enable the clock.
0362  *
0363  * param base asrc base pointer.
0364  * param asrcPeripheralClock_Hz peripheral clock of ASRC.
0365  */
0366 void ASRC_Init(ASRC_Type *base, uint32_t asrcPeripheralClock_Hz)
0367 {
0368 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0369     /* Enable the asrc clock */
0370     CLOCK_EnableClock(s_asrcClock[ASRC_GetInstance(base)]);
0371 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0372 
0373     /* disable ASRC channel pair, enable ASRC */
0374     base->ASRCTR = 1U;
0375 
0376     /* disable all the interrupt */
0377     base->ASRIER = 0U;
0378 
0379 #if (defined FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM) && FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM
0380     /* set paramter register to default configurations per recommand value in reference manual */
0381     base->ASRPM[0] = 0x7fffffU;
0382     base->ASRPM[1] = 0x255555U;
0383     base->ASRPM[2] = 0xff7280U;
0384     base->ASRPM[3] = 0xff7280U;
0385     base->ASRPM[4] = 0xff7280U;
0386 #else
0387     /* set paramter register to default configurations per recommand value in reference manual */
0388     base->ASRPMn[0] = 0x7fffffU;
0389     base->ASRPMn[1] = 0x255555U;
0390     base->ASRPMn[2] = 0xff7280U;
0391     base->ASRPMn[3] = 0xff7280U;
0392     base->ASRPMn[4] = 0xff7280U;
0393 #endif /*FSL_FEATURE_ASRC_PARAMETER_REGISTER_NAME_ASRPM*/
0394     /* set task queue fifo */
0395     base->ASRTFR1 = ASRC_ASRTFR1_TF_BASE(0x7C);
0396     /* 76K/56K divider */
0397     base->ASR76K = ASRC_ASR76K_ASR76K(asrcPeripheralClock_Hz / 76000U);
0398     base->ASR56K = ASRC_ASR56K_ASR56K(asrcPeripheralClock_Hz / 56000U);
0399 }
0400 
0401 /*!
0402  * brief De-initializes the ASRC peripheral.
0403  *
0404  * This API gates the ASRC clock and disable ASRC module. The ASRC module can't operate unless ASRC_Init
0405  *
0406  * param base ASRC base pointer.
0407  */
0408 void ASRC_Deinit(ASRC_Type *base)
0409 {
0410     /* disable ASRC module */
0411     ASRC_ModuleEnable(base, false);
0412 
0413 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0414     CLOCK_DisableClock(s_asrcClock[ASRC_GetInstance(base)]);
0415 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0416 }
0417 
0418 /*!
0419  * brief Do software reset .
0420  *
0421  * This software reset bit is self-clear bit, it will generate a software reset signal inside ASRC.
0422  * After 9 cycles of the ASRC processing clock, this reset process will stop and this bit will cleared
0423  * automatically.
0424  *
0425  * param base ASRC base pointer
0426  */
0427 void ASRC_SoftwareReset(ASRC_Type *base)
0428 {
0429     base->ASRCTR |= ASRC_ASRCTR_SRST_MASK;
0430     /* polling reset clear automatically */
0431     while ((base->ASRCTR & ASRC_ASRCTR_SRST_MASK) != 0U)
0432     {
0433     }
0434 }
0435 
0436 /*!
0437  * brief ASRC configure channel pair.
0438  *
0439  * param base ASRC base pointer.
0440  * param channelPair index of channel pair, reference _asrc_channel_pair.
0441  * param config ASRC channel pair configuration pointer.
0442  * param inputSampleRate in audio data sample rate.
0443  * param outSampleRate out audio data sample rate.
0444  */
0445 status_t ASRC_SetChannelPairConfig(ASRC_Type *base,
0446                                    asrc_channel_pair_t channelPair,
0447                                    asrc_channel_pair_config_t *config,
0448                                    uint32_t inputSampleRate,
0449                                    uint32_t outputSampleRate)
0450 {
0451     assert(config != NULL);
0452 
0453     if (config->outDataWidth == kASRC_DataWidth8Bit)
0454     {
0455         return kStatus_InvalidArgument;
0456     }
0457 
0458     if (((inputSampleRate < (uint32_t)kASRC_SampleRate_8000HZ) ||
0459          (inputSampleRate > (uint32_t)kASRC_SampleRate_192000HZ)) ||
0460         ((outputSampleRate < (uint32_t)kASRC_SampleRate_8000HZ) ||
0461          (outputSampleRate > (uint32_t)kASRC_SampleRate_192000HZ)) ||
0462         (((outputSampleRate > (uint32_t)kASRC_SampleRate_8000HZ) &&
0463           (outputSampleRate < (uint32_t)kASRC_SampleRate_30000HZ)) &&
0464          (inputSampleRate / outputSampleRate > 8U || outputSampleRate / inputSampleRate > 24U)))
0465     {
0466         return kStatus_InvalidArgument;
0467     }
0468 
0469     uint32_t i = 0U;
0470     /* channel pair processing selection and ratio configuration */
0471     uint32_t asrctr = base->ASRCTR & (~(ASRC_ASRCTR_AT_MASK(channelPair) | ASRC_ASRCTR_RATIO_MASK(channelPair)));
0472     /* use automatic selection for processing option by default */
0473     asrctr |= ASRC_ASRCTR_AT_MASK(channelPair);
0474     /* ratio configuration */
0475     asrctr |= ASRC_ASRCTR_RATIO(config->sampleRateRatio, channelPair);
0476     base->ASRCTR = asrctr;
0477 
0478     /* audio data channel counter configurations */
0479     uint32_t asrcncr = base->ASRCNCR & (~ASRC_ASRCNCR_CHANNEL_COUNTER_MASK(channelPair));
0480     base->ASRCNCR    = asrcncr | ASRC_ASRCNCR_CHANNEL_COUNTER(config->audioDataChannels, channelPair);
0481 
0482     /* in clock source and out clock source configurations */
0483     uint32_t asrcsr =
0484         base->ASRCSR &
0485         (~(ASRC_ASRCSR_INPUT_CLOCK_SOURCE_MASK(channelPair) | ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE_MASK(channelPair)));
0486     asrcsr |= ASRC_ASRCSR_OUTPUT_CLOCK_SOURCE(config->outClockSource, channelPair);
0487     if (config->inClockSource != kASRC_ClockSourceNotAvalible)
0488     {
0489         asrcsr |= ASRC_ASRCSR_INPUT_CLOCK_SOURCE(config->inClockSource, channelPair);
0490     }
0491     base->ASRCSR = asrcsr;
0492 
0493     /* clock divider configuration */
0494     uint32_t asrcdr =
0495         base->ASRCDR1 &
0496         (~(ASRC_ASRCDR_INPUT_PRESCALER_MASK(channelPair) | ASRC_ASRCDR_INPUT_DIVIDER_MASK(channelPair) |
0497            ASRC_ASRCDR_OUTPUT_PRESCALER_MASK(channelPair) | ASRC_ASRCDR_OUTPUT_DIVIDER_MASK(channelPair)));
0498 
0499     asrcdr |= ASCR_ASRCDR_OUTPUT_CLOCK_DIVIDER_PRESCALER(
0500         ASRC_CalculateClockDivider(outputSampleRate, config->outSourceClock_Hz), channelPair);
0501     if (config->inClockSource != kASRC_ClockSourceNotAvalible)
0502     {
0503         asrcdr |= ASCR_ASRCDR_INPUT_CLOCK_DIVIDER_PRESCALER(
0504             ASRC_CalculateClockDivider(inputSampleRate, config->inSourceClock_Hz), channelPair);
0505     }
0506 
0507     if (channelPair == kASRC_ChannelPairC)
0508     {
0509         base->ASRCDR2 = asrcdr;
0510     }
0511     else
0512     {
0513         base->ASRCDR1 = asrcdr;
0514     }
0515 
0516     /* data width/sign extension/data align configuration */
0517     ASRC_ASRMCR1(base, channelPair) = ASRC_ASRMCR1_OW16(config->outDataWidth) | ASRC_ASRMCR1_IWD(config->inDataWidth) |
0518                                       ASRC_ASRMCR1_OSGN(config->outSignExtension) |
0519                                       ASRC_ASRMCR1_OMSB(config->outDataAlign) | ASRC_ASRMCR1_IMSB(config->inDataAlign);
0520     /* data configurations, MISC */
0521     uint32_t asrmcra = ASRC_ASRMCR(base, channelPair) &
0522                        (~(ASRC_ASRMCRA_BUFSTALLA_MASK | ASRC_ASRMCRA_EXTTHRSHA_MASK |
0523                           ASRC_ASRMCRA_INFIFO_THRESHOLDA_MASK | ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_MASK));
0524     /* buffer stall */
0525     asrmcra |= ASRC_ASRMCRA_BUFSTALLA(config->bufStallWhenFifoEmptyFull);
0526     /* in fifo and out fifo threshold */
0527     asrmcra |= ASRC_ASRMCRA_EXTTHRSHA_MASK | ASRC_ASRMCRA_INFIFO_THRESHOLDA(config->inFifoThreshold - 1UL) |
0528                ASRC_ASRMCRA_OUTFIFO_THRESHOLDA(config->outFifoThreshold - 1UL);
0529     ASRC_ASRMCR(base, channelPair) = asrmcra;
0530 
0531     if (config->sampleRateRatio == kASRC_RatioUseIdealRatio)
0532     {
0533         if (ASRC_SetIdealRatioConfig(base, channelPair, inputSampleRate, outputSampleRate) != kStatus_Success)
0534         {
0535             return kStatus_ASRCChannelPairConfigureFailed;
0536         }
0537     }
0538 
0539     /* channel pair enable */
0540     ASRC_ChannelPairEnable(base, channelPair, true);
0541 
0542     /* wait channel initial served */
0543     while (!ASRC_GetChannelPairInitialStatus(base, channelPair))
0544     {
0545     }
0546 
0547     for (i = 0U; i < (uint32_t)config->audioDataChannels * 4U; i++)
0548     {
0549         ASRC_ChannelPairWriteData(base, channelPair, 0U);
0550     }
0551 
0552     return kStatus_Success;
0553 }
0554 
0555 /*!
0556  * brief Get output sample buffer size.
0557  *
0558  * note This API is depends on the ASRC output configuration, should be called after the ASRC_SetChannelPairConfig.
0559  *
0560  * param base asrc base pointer.
0561  * param channelPair ASRC channel pair number.
0562  * param inSampleRate input sample rate.
0563  * param outSampleRate output sample rate.
0564  * param inSamples input sampleS size.
0565  * retval output buffer size in byte.
0566  */
0567 uint32_t ASRC_GetOutSamplesSize(ASRC_Type *base,
0568                                 asrc_channel_pair_t channelPair,
0569                                 uint32_t inSampleRate,
0570                                 uint32_t outSampleRate,
0571                                 uint32_t inSamplesize)
0572 {
0573     uint32_t inSamples         = 0U;
0574     uint32_t outSamples        = 0U;
0575     uint32_t outSamplesBufSize = 0U, audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
0576     ;
0577     asrc_data_width_t outWdith = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OW16_MASK) == ASRC_ASRMCR1_OW16_MASK ?
0578                                      kASRC_DataWidth16Bit :
0579                                      kASRC_DataWidth24Bit;
0580     asrc_data_align_t outAlign = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OMSB_MASK) == ASRC_ASRMCR1_OMSB_MASK ?
0581                                      kASRC_DataAlignMSB :
0582                                      kASRC_DataAlignLSB;
0583     uint32_t inWdith          = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_IWD_MASK) >> ASRC_ASRMCR1_IWD_SHIFT;
0584     asrc_data_align_t inAlign = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_IMSB_MASK) == ASRC_ASRMCR1_IMSB_MASK ?
0585                                     kASRC_DataAlignMSB :
0586                                     kASRC_DataAlignLSB;
0587 
0588     bool signExtend = (base->ASRMCR1[channelPair] & ASRC_ASRMCR1_OSGN_MASK) == ASRC_ASRMCR1_OSGN_MASK ? true : false;
0589 
0590     /* 24bit input data */
0591     if (inWdith == 0U)
0592     {
0593         inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 4U : 3U);
0594     }
0595     /* 16bit input data */
0596     else if (inWdith == 1U)
0597     {
0598         inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 4U : 2U);
0599     }
0600     /* 8bit input data */
0601     else
0602     {
0603         inSamples = inSamplesize / (inAlign == kASRC_DataAlignMSB ? 2U : 1U);
0604     }
0605 
0606     outSamples = (uint32_t)((uint64_t)inSamples * outSampleRate / inSampleRate);
0607     /* make sure output samples is in group */
0608     outSamples = outSamples - outSamples % audioChannels;
0609 
0610     if (outWdith == kASRC_DataWidth16Bit)
0611     {
0612         if ((outAlign == kASRC_DataAlignMSB) || signExtend)
0613         {
0614             outSamplesBufSize = outSamples * 4U;
0615         }
0616         else
0617         {
0618             outSamplesBufSize = outSamples * 2U;
0619         }
0620     }
0621 
0622     if (outWdith == kASRC_DataWidth24Bit)
0623     {
0624         outSamplesBufSize = outSamples * 4U;
0625     }
0626 
0627     return outSamplesBufSize;
0628 }
0629 
0630 /*!
0631  * brief Performs an blocking convert on asrc.
0632  *
0633  * note This API returns immediately after the convert finished.
0634  *
0635  * param base asrc base pointer.
0636  * param channelPair channel pair index.
0637  * param xfer Pointer to the ASRC_transfer_t structure.
0638  * retval kStatus_Success Successfully started the data receive.
0639  */
0640 status_t ASRC_TransferBlocking(ASRC_Type *base, asrc_channel_pair_t channelPair, asrc_transfer_t *xfer)
0641 {
0642     assert(xfer != NULL);
0643 
0644     uint32_t inWaterMark  = ASRC_ASRMCR(base, channelPair) & ASRC_ASRMCRA_INFIFO_THRESHOLDA_MASK,
0645              outWaterMark = (ASRC_ASRMCR(base, channelPair) & ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_MASK) >>
0646                             ASRC_ASRMCRA_OUTFIFO_THRESHOLDA_SHIFT,
0647              audioChannels = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
0648     uint8_t *inAddr = (uint8_t *)xfer->inData, *outAddr = (uint8_t *)xfer->outData;
0649     uint32_t onceWriteSamples = 0U;
0650     uint32_t status = 0U, inSampleMask = 0U, inSamples = 0U, outSamples = 0U, inWidth = 0U, outWidth = 0U;
0651 
0652     inSampleMask = ASRC_MapSamplesWidth(base, channelPair, &inWidth, &outWidth);
0653     inSamples    = xfer->inDataSize / inWidth;
0654     outSamples   = xfer->outDataSize / outWidth;
0655     inWaterMark *= audioChannels;
0656     outWaterMark *= audioChannels;
0657 
0658     while (outSamples != 0U)
0659     {
0660         status = ASRC_GetStatus(base);
0661 
0662         if ((status & ((uint32_t)kASRC_StatusPairCInputReady | (uint32_t)kASRC_StatusPairBInputReady |
0663                        (uint32_t)kASRC_StatusPairAInputReady)) != 0U)
0664         {
0665             onceWriteSamples =
0666                 MIN(inSamples, (size_t)((FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH * audioChannels - inWaterMark)));
0667             ASRC_WriteNonBlocking(base, channelPair, (uint32_t *)(uint32_t)inAddr, onceWriteSamples, inSampleMask,
0668                                   inWidth);
0669             inAddr = (uint8_t *)((uint32_t)inAddr + onceWriteSamples * inWidth);
0670             inSamples -= onceWriteSamples;
0671         }
0672 
0673         if (outSamples > outWaterMark)
0674         {
0675             if ((status & ((uint32_t)kASRC_StatusPairCOutputReady | (uint32_t)kASRC_StatusPairAOutputReady |
0676                            (uint32_t)kASRC_StatusPairBOutputReady)) != 0U)
0677             {
0678                 ASRC_ReadNonBlocking(base, channelPair, (uint32_t *)(uint32_t)outAddr, outWaterMark, outWidth);
0679                 outAddr = (uint8_t *)((uint32_t)outAddr + outWaterMark * outWidth);
0680                 outSamples -= outWaterMark;
0681             }
0682         }
0683         else
0684         {
0685             outSamples -=
0686                 ASRC_GetRemainFifoSamples(base, channelPair, (uint32_t *)(uint32_t)outAddr, outWidth, outSamples);
0687             continue;
0688         }
0689     }
0690 
0691     return kStatus_Success;
0692 }
0693 
0694 /*!
0695  * brief ASRC configure channel pair.
0696  *
0697  * param base ASRC base pointer.
0698  * param handle ASRC transactional handle pointer.
0699  * param config ASRC channel pair configuration pointer.
0700  * param inputSampleRate in audio data sample rate.
0701  * param outputSampleRate out audio data sample rate.
0702  */
0703 status_t ASRC_TransferSetChannelPairConfig(ASRC_Type *base,
0704                                            asrc_handle_t *handle,
0705                                            asrc_channel_pair_config_t *config,
0706                                            uint32_t inputSampleRate,
0707                                            uint32_t outputSampleRate)
0708 {
0709     assert(handle != NULL);
0710 
0711     handle->in.fifoThreshold  = config->inFifoThreshold * (uint32_t)config->audioDataChannels;
0712     handle->out.fifoThreshold = config->outFifoThreshold * (uint32_t)config->audioDataChannels;
0713     handle->audioDataChannels = config->audioDataChannels;
0714 
0715     if (ASRC_SetChannelPairConfig(base, handle->channelPair, config, inputSampleRate, outputSampleRate) !=
0716         kStatus_Success)
0717     {
0718         return kStatus_ASRCChannelPairConfigureFailed;
0719     }
0720 
0721     handle->in.sampleMask =
0722         ASRC_MapSamplesWidth(base, handle->channelPair, &handle->in.sampleWidth, &handle->out.sampleWidth);
0723 
0724     return kStatus_Success;
0725 }
0726 
0727 /*!
0728  * brief Get left samples in fifo.
0729  *
0730  * param base asrc base pointer.
0731  * param channelPair ASRC channel pair number.
0732  * param buffer input sample numbers.
0733  * param outSampleWidth output sample width.
0734  * param remainSamples output sample rate.
0735  * retval remain samples number.
0736  */
0737 uint32_t ASRC_GetRemainFifoSamples(
0738     ASRC_Type *base, asrc_channel_pair_t channelPair, uint32_t *buffer, uint32_t outSampleWidth, uint32_t remainSamples)
0739 {
0740     uint32_t remainSamplesInFifo = 0U;
0741     uint32_t audioChannels       = ASRC_GET_CHANNEL_COUNTER(base, channelPair);
0742     remainSamplesInFifo =
0743         ((ASRC_ASRFST_ADDR(base, channelPair) & ASRC_ASRFSTA_OUTFIFO_FILLA_MASK) >> ASRC_ASRFSTA_OUTFIFO_FILLA_SHIFT) *
0744         audioChannels;
0745 
0746     if (remainSamples < remainSamplesInFifo)
0747     {
0748         remainSamplesInFifo = remainSamples;
0749     }
0750 
0751     ASRC_ReadNonBlocking(base, channelPair, (uint32_t *)buffer, remainSamplesInFifo, outSampleWidth);
0752 
0753     return remainSamplesInFifo;
0754 }
0755 
0756 /*!
0757  * brief Initializes the ASRC handle.
0758  *
0759  * This function initializes the handle for the ASRC transactional APIs. Call
0760  * this function once to get the handle initialized.
0761  *
0762  * param base ASRC base pointer
0763  * param handle ASRC handle pointer.
0764  * param inCallback Pointer to the user callback function.
0765  * param outCallback Pointer to the user callback function.
0766  * param userData User parameter passed to the callback function
0767  */
0768 void ASRC_TransferCreateHandle(ASRC_Type *base,
0769                                asrc_handle_t *handle,
0770                                asrc_channel_pair_t channelPair,
0771                                asrc_transfer_callback_t inCallback,
0772                                asrc_transfer_callback_t outCallback,
0773                                void *userData)
0774 {
0775     assert(handle != NULL);
0776 
0777     uint32_t instance = ASRC_GetInstance(base);
0778 
0779     (void)memset(handle, 0, sizeof(*handle));
0780 
0781     s_asrcHandle[instance][channelPair] = handle;
0782 
0783     handle->in.callback  = inCallback;
0784     handle->out.callback = outCallback;
0785     handle->userData     = userData;
0786     handle->channelPair  = channelPair;
0787     /* Set the isr pointer */
0788     s_asrcIsr = ASRC_TransferHandleIRQ;
0789 
0790     (void)EnableIRQ(s_asrcIRQ[instance]);
0791 }
0792 
0793 /*!
0794  * brief Performs an interrupt non-blocking convert on asrc.
0795  *
0796  * note This API returns immediately after the transfer initiates, application should check the wait and check the
0797  * callback status.
0798  *
0799  * param base asrc base pointer.
0800  * param handle Pointer to the asrc_handle_t structure which stores the transfer state.
0801  * param xfer Pointer to the ASRC_transfer_t structure.
0802  * retval kStatus_Success Successfully started the data receive.
0803  * retval kStatus_ASRCBusy Previous receive still not finished.
0804  */
0805 status_t ASRC_TransferNonBlocking(ASRC_Type *base, asrc_handle_t *handle, asrc_transfer_t *xfer)
0806 {
0807     assert(handle != NULL);
0808     assert(xfer != NULL);
0809 
0810     /* Check if the queue is full */
0811     if ((handle->in.asrcQueue[handle->in.queueUser] != NULL) || (handle->out.asrcQueue[handle->out.queueUser] != NULL))
0812     {
0813         return kStatus_ASRCBusy;
0814     }
0815 
0816     /* Add into queue */
0817     handle->in.transferSamples[handle->in.queueUser] = xfer->inDataSize / handle->in.sampleWidth;
0818     handle->in.asrcQueue[handle->in.queueUser]       = xfer->inData;
0819     handle->in.queueUser                             = (handle->in.queueUser + 1U) % ASRC_XFER_QUEUE_SIZE;
0820 
0821     handle->out.asrcQueue[handle->out.queueUser]       = xfer->outData;
0822     handle->out.transferSamples[handle->out.queueUser] = xfer->outDataSize / handle->out.sampleWidth;
0823     handle->out.queueUser                              = (handle->out.queueUser + 1U) % ASRC_XFER_QUEUE_SIZE;
0824 
0825     if (handle->state != (uint32_t)kStatus_ASRCBusy)
0826     {
0827         /* enable channel pair interrupt */
0828         ASRC_EnableInterrupt(base, ASRC_ASRIER_INPUT_INTERRUPT_MASK(handle->channelPair) |
0829                                        (uint32_t)kASRC_OverLoadInterruptMask |
0830                                        ASRC_ASRIER_OUTPUTPUT_INTERRUPT_MASK(handle->channelPair));
0831     }
0832 
0833     /* Set the state to busy */
0834     handle->state = kStatus_ASRCBusy;
0835 
0836     return kStatus_Success;
0837 }
0838 
0839 /*!
0840  * brief Gets a set byte count.
0841  *
0842  * param base asrc base pointer.
0843  * param handle Pointer to the ASRC_handle_t structure which stores the transfer state.
0844  * param count Bytes count sent.
0845  * retval kStatus_Success Succeed get the transfer count.
0846  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
0847  */
0848 status_t ASRC_TransferGetConvertedCount(ASRC_Type *base, asrc_handle_t *handle, size_t *count)
0849 {
0850     assert(handle != NULL);
0851 
0852     status_t status = kStatus_Success;
0853 
0854     if (handle->state != (uint32_t)kStatus_ASRCBusy)
0855     {
0856         status = kStatus_ASRCIdle;
0857     }
0858     else
0859     {
0860         *count = handle->out.transferSamples[handle->out.queueDriver];
0861     }
0862 
0863     return status;
0864 }
0865 
0866 /*!
0867  * brief Aborts the current convert.
0868  *
0869  * note This API can be called any time when an interrupt non-blocking transfer initiates
0870  * to abort the transfer early.
0871  *
0872  * param base asrc base pointer.
0873  * param handle Pointer to the ASRC_handle_t structure which stores the transfer state.
0874  */
0875 void ASRC_TransferAbortConvert(ASRC_Type *base, asrc_handle_t *handle)
0876 {
0877     assert(handle != NULL);
0878 
0879     /* enable ASRC module */
0880     ASRC_ModuleEnable(base, false);
0881 
0882     handle->state = kStatus_ASRCIdle;
0883 
0884     handle->in.queueDriver  = 0;
0885     handle->in.queueUser    = 0;
0886     handle->out.queueDriver = 0;
0887     handle->out.queueUser   = 0;
0888 }
0889 
0890 /*!
0891  * brief Terminate all asrc convert.
0892  *
0893  * This function will clear all transfer slots buffered in the asrc queue. If users only want to abort the
0894  * current transfer slot, please call ASRC_TransferAbortSend.
0895  *
0896  * param base asrc base pointer.
0897  * param handle asrc eDMA handle pointer.
0898  */
0899 void ASRC_TransferTerminateConvert(ASRC_Type *base, asrc_handle_t *handle)
0900 {
0901     assert(handle != NULL);
0902 
0903     /* Abort the current transfer */
0904     ASRC_TransferAbortConvert(base, handle);
0905 
0906     /* Clear all the internal information */
0907     (void)memset(handle->in.asrcQueue, 0, sizeof(handle->in.asrcQueue));
0908     (void)memset(handle->in.transferSamples, 0, sizeof(handle->in.transferSamples));
0909     (void)memset(handle->out.asrcQueue, 0, sizeof(handle->out.asrcQueue));
0910     (void)memset(handle->out.transferSamples, 0, sizeof(handle->out.transferSamples));
0911 }
0912 
0913 /*!
0914  * brief ASRC convert interrupt handler.
0915  *
0916  * param base asrc base pointer.
0917  * param handle Pointer to the asrc_handle_t structure.
0918  */
0919 void ASRC_TransferHandleIRQ(ASRC_Type *base, asrc_handle_t *handle)
0920 {
0921     assert(handle != NULL);
0922 
0923     uint32_t status = base->ASRSTR;
0924 
0925     /* Handle Error */
0926     if ((status & (uint32_t)kASRC_StatusInputError) != 0U)
0927     {
0928         /* Call the callback */
0929         if (handle->in.callback != NULL)
0930         {
0931             (handle->in.callback)(base, handle, kStatus_ASRCConvertError, handle->userData);
0932         }
0933     }
0934 
0935     if ((status & (uint32_t)kASRC_StatusOutputError) != 0U)
0936     {
0937         /* Call the callback */
0938         if (handle->out.callback != NULL)
0939         {
0940             (handle->out.callback)(base, handle, kStatus_ASRCConvertError, handle->userData);
0941         }
0942     }
0943 
0944     /* Handle transfer */
0945     if ((status & ((uint32_t)kASRC_StatusPairCOutputReady | (uint32_t)kASRC_StatusPairAOutputReady |
0946                    (uint32_t)kASRC_StatusPairBOutputReady)) != 0U)
0947     {
0948         if (handle->out.transferSamples[handle->out.queueDriver] != 0U)
0949         {
0950             ASRC_ReadNonBlocking(base, handle->channelPair,
0951                                  (uint32_t *)(uint32_t)handle->out.asrcQueue[handle->out.queueDriver],
0952                                  handle->out.fifoThreshold, handle->out.sampleWidth);
0953             handle->out.transferSamples[handle->out.queueDriver] -= handle->out.fifoThreshold;
0954             handle->out.asrcQueue[handle->out.queueDriver] =
0955                 (uint8_t *)((uint32_t)handle->out.asrcQueue[handle->out.queueDriver] +
0956                             handle->out.fifoThreshold * handle->out.sampleWidth);
0957         }
0958     }
0959 
0960     if ((status & ((uint32_t)kASRC_StatusPairCInputReady | (uint32_t)kASRC_StatusPairBInputReady |
0961                    (uint32_t)kASRC_StatusPairAInputReady)) != 0U)
0962     {
0963         /* Judge if the data need to transmit is less than space */
0964         uint32_t size = MIN((handle->in.transferSamples[handle->in.queueDriver]),
0965                             (size_t)((FSL_ASRC_CHANNEL_PAIR_FIFO_DEPTH * (uint32_t)handle->audioDataChannels -
0966                                       handle->in.fifoThreshold)));
0967         ASRC_WriteNonBlocking(base, handle->channelPair,
0968                               (uint32_t *)(uint32_t)handle->in.asrcQueue[handle->in.queueDriver], size,
0969                               handle->in.sampleMask, handle->in.sampleWidth);
0970         handle->in.transferSamples[handle->in.queueDriver] -= size;
0971         handle->in.asrcQueue[handle->in.queueDriver] =
0972             (uint8_t *)((uint32_t)handle->in.asrcQueue[handle->in.queueDriver] + size * handle->in.sampleWidth);
0973     }
0974 
0975     /* If finished a block, call the callback function */
0976     if (handle->in.transferSamples[handle->in.queueDriver] == 0U)
0977     {
0978         handle->in.asrcQueue[handle->in.queueDriver] = NULL;
0979         handle->in.queueDriver                       = (handle->in.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
0980         if (handle->in.callback != NULL)
0981         {
0982             (handle->in.callback)(base, handle, kStatus_ASRCIdle, handle->userData);
0983         }
0984     }
0985 
0986     if (handle->out.transferSamples[handle->out.queueDriver] < (handle->out.fifoThreshold + 1U))
0987     {
0988         handle->out.transferSamples[handle->out.queueDriver] -= ASRC_GetRemainFifoSamples(
0989             base, handle->channelPair, (uint32_t *)(uint32_t)handle->out.asrcQueue[handle->out.queueDriver],
0990             handle->out.sampleWidth, handle->out.transferSamples[handle->out.queueDriver]);
0991     }
0992 
0993     if (handle->out.transferSamples[handle->out.queueDriver] == 0U)
0994     {
0995         handle->out.asrcQueue[handle->out.queueDriver] = NULL;
0996         handle->out.queueDriver                        = (handle->out.queueDriver + 1U) % ASRC_XFER_QUEUE_SIZE;
0997         if (handle->out.callback != NULL)
0998         {
0999             (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);
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 */