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 #include "fsl_asrc_firmware.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.easrc"
14 #endif
15
16 /*******************************************************************************
17 * Definitions
18 ******************************************************************************/
19 /*! @brief asrc sample rate ratio format */
20 typedef enum _asrc_samplerate_ratio_format
21 {
22 kASRC_SampleRateRatio5Int39Frac = 32, /*!< sample rate ratio 5 integer bits and 39 fractional bits */
23 kASRC_SampleRateRatio6Int38Frac = 64, /*!< sample rate ratio 6 integer bits and 38 fractional bits */
24 kASRC_SampleRateRatio7Int37Frac = 128, /*!< sample rate ratio 7 integer bits and 37 fractional bits */
25 } asrc_samplerate_ratio_format_t;
26
27 /*! @brief ASRC support maximum channel number */
28 #define ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMBER 32U
29 /*! @brief ASRC support maximum channel number of one context process pipe line */
30 #define ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER 8U
31 /*! @brief ASRC support maximum channel number of context */
32 #define ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER 4U
33
34 /*! @brief ASRC macro to get register field value*/
35 #define ASRC_GET_SLOT0_CONTEXT_INDEX(context) \
36 ((base->PROC_CTRL_SLOT0_R0[context] & ASRC_PROC_CTRL_SLOT0_R0_SLOT0_CTX_NUM_MASK) >> \
37 ASRC_PROC_CTRL_SLOT0_R0_SLOT0_CTX_NUM_SHIFT)
38 #define ASRC_GET_SLOT0_CHANNEL_NUMBER(context) \
39 ((base->PROC_CTRL_SLOT0_R0[context] & ASRC_PROC_CTRL_SLOT0_R0_SLOT0_NUM_CH_MASK) >> \
40 ASRC_PROC_CTRL_SLOT0_R0_SLOT0_NUM_CH_SHIFT)
41 #define ASRC_GET_SLOT1_CONTEXT_INDEX(context) \
42 ((base->PROC_CTRL_SLOT1_R0[context] & ASRC_PROC_CTRL_SLOT1_R0_SLOT1_CTX_NUM_MASK) >> \
43 ASRC_PROC_CTRL_SLOT1_R0_SLOT1_CTX_NUM_SHIFT)
44 #define ASRC_GET_SLOT1_CHANNEL_NUMBER(context) \
45 ((base->PROC_CTRL_SLOT1_R0[context] & ASRC_PROC_CTRL_SLOT1_R0_SLOT1_NUM_CH_MASK) >> \
46 ASRC_PROC_CTRL_SLOT1_R0_SLOT1_NUM_CH_SHIFT)
47 #define ASRC_IS_CONTEXT_ENABLED(index) ((base->CTX_CTRL[index] & ASRC_CTX_CTRL_RUN_EN_MASK) != 0U)
48 #define ASRC_IS_SLOT0_ENABLED(context) \
49 ((base->PROC_CTRL_SLOT0_R0[context] & ASRC_PROC_CTRL_SLOT0_R0_SLOT0_EN_MASK) != 0U)
50 #define ASRC_IS_SLOT1_ENABLED(context) \
51 ((base->PROC_CTRL_SLOT1_R0[context] & ASRC_PROC_CTRL_SLOT1_R0_SLOT1_EN_MASK) != 0U)
52
53 /*******************************************************************************
54 * Prototypes
55 ******************************************************************************/
56 /*!
57 * @brief ASRC get greatest common divisor between the input and output sample rate.
58 *
59 * @param inputSampleRate input sample rate.
60 * @param outputSampleRate output sample rate.
61 * @retval GCD between the input and output sample rate.
62 */
63 static uint32_t ASRC_GetSampleRateGCD(uint32_t inputSampleRate, uint32_t outputSampleRate);
64
65 /*!
66 * @brief ASRC get available context slot channel.
67 *
68 * @param base ASRC base address.
69 * @param contextProcessor context processor number.
70 * @param slot0UsedChannel slot0 used channel number.
71 * @param slot1UsedChannel slot1 used channel number.
72 */
73 static void ASRC_GetAvailableContextSlot(ASRC_Type *base,
74 uint32_t contextProcessor,
75 uint32_t *slot0UsedChannel,
76 uint32_t *slot1UsedChannel);
77
78 /*!
79 * @brief ASRC enable context slot.
80 *
81 * @param base ASRC base address.
82 * @param contextProcessor context processor number.
83 * @param slot slot number.
84 * @param channelNums channel number
85 * @param startChannel start channel number running on this slot.
86 * @param context context number running on this slot.
87 */
88 static void ASRC_EnableContextSlot(ASRC_Type *base,
89 uint32_t contextProcessor,
90 uint32_t slot,
91 uint32_t channelNums,
92 uint32_t startChannel,
93 asrc_context_t runningContext);
94
95 /*!
96 * @brief ASRC config the sample rate ratio.
97 *
98 * @param base ASRC base address.
99 * @param context context number.
100 * @param inputSampleRate input sample rate.
101 * @param outputSampleRate output sample rate.
102 * @param format sample rate ratio format.
103 * @retval kStatus_Success, else configure failed.
104 */
105 static status_t ASRC_SetSampleRateRatioConfig(ASRC_Type *base,
106 asrc_context_t context,
107 uint32_t inputSampleRate,
108 uint32_t outputSampleRate,
109 asrc_samplerate_ratio_format_t format);
110
111 /*!
112 * @brief ASRC load prefilter configuration.
113 *
114 * @param config prefilter pointer.
115 * @param inputSampleRate input sample rate.
116 * @param outputSampleRate output sample rate.
117 * @retval kStatus_Success, else configure failed.
118 */
119 static status_t ASRC_GetPrefilterConfig(asrc_context_prefilter_config_t *config,
120 uint32_t inputSampleRate,
121 uint32_t outputSampleRate);
122
123 /*!
124 * @brief ASRC load resample configuration.
125 *
126 * @param config resamplefilter pointer.
127 * @param interpolationTap resampler taps
128 * @retval kStatus_Success, else configure failed.
129 */
130 static status_t ASRC_GetResamplerConfig(asrc_context_resampler_config_t *config,
131 asrc_resampler_taps_t interpolationTap);
132
133 /*!
134 * @brief ASRC reset prefilter coeff memory pointer reset.
135 *
136 * @param base ASRC base address.
137 * @param context context number.
138 */
139 static void ASRC_SetPrefilterCoeffMemReset(ASRC_Type *base, asrc_context_t context);
140
141 /*!
142 * @brief ASRC set prefilter configuration.
143 *
144 * @param base ASRC base address.
145 * @param context context number.
146 * @param config prefilter configuration.
147 * @param filter filter configuration load from firmware.
148 * @retval kStatus_Success, else configure failed.
149 */
150 static status_t ASRC_SetPrefilterConfig(ASRC_Type *base,
151 asrc_context_t context,
152 asrc_context_prefilter_config_t *config);
153
154 /*!
155 * @brief ASRC set resampler configuration.
156 *
157 * @param base ASRC base address.
158 * @param context context number.
159 * @param config resampler configuration.
160 * @param filter filter configuration load from firmware.
161 * @retval kStatus_Success, else configure failed.
162 */
163 static status_t ASRC_SetResamplerConfig(ASRC_Type *base,
164 asrc_context_t context,
165 asrc_context_resampler_config_t *config);
166
167 /*!
168 * @brief ASRC set slot config.
169 *
170 * @param base ASRC base address.
171 * @param context context number.
172 * @param requestChannel request channel number need to run on this slot.
173 * @param filter filter configuration load from firmware.
174 * @retval kStatus_Success, else configure failed.
175 */
176 static status_t ASRC_SetSlotConfig(ASRC_Type *base,
177 asrc_context_t context,
178 uint32_t requestChannel,
179 asrc_context_prefilter_config_t *config);
180
181 /*!
182 * @brief ASRC set context processor config.
183 *
184 * @param base ASRC base address.
185 * @param context context number.
186 * @param config context configuration.
187 * @retval kStatus_Success, else configure failed.
188 */
189 static status_t ASRC_SetContextProcessorConfig(ASRC_Type *base, asrc_context_t context, asrc_context_config_t *config);
190
191 /*******************************************************************************
192 * Variables
193 ******************************************************************************/
194 /* Base pointer array */
195 static ASRC_Type *const s_asrcBases[] = ASRC_BASE_PTRS;
196
197 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
198 /* Clock name array */
199 static const clock_ip_name_t s_asrcClock[] = ASRC_CLOCKS;
200 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
201 /*! @brief ASRC filter firmware table */
202 static const uint32_t s_asrcFirmware[] = ASRC_FILTER_FIRMWARE;
203 /*******************************************************************************
204 * Code
205 ******************************************************************************/
ASRC_GetInstance(ASRC_Type * base)206 uint32_t ASRC_GetInstance(ASRC_Type *base)
207 {
208 uint32_t instance;
209
210 /* Find the instance index from base address mappings. */
211 for (instance = 0; instance < ARRAY_SIZE(s_asrcBases); instance++)
212 {
213 if (s_asrcBases[instance] == base)
214 {
215 break;
216 }
217 }
218
219 assert(instance < ARRAY_SIZE(s_asrcBases));
220
221 return instance;
222 }
223
ASRC_GetSampleRateGCD(uint32_t inputSampleRate,uint32_t outputSampleRate)224 static uint32_t ASRC_GetSampleRateGCD(uint32_t inputSampleRate, uint32_t outputSampleRate)
225 {
226 uint32_t temp = 0U, gcd = inputSampleRate;
227
228 while (outputSampleRate != 0U)
229 {
230 temp = outputSampleRate;
231 outputSampleRate = gcd % outputSampleRate;
232 gcd = temp;
233 }
234
235 return gcd;
236 }
237
ASRC_GetAvailableContextSlot(ASRC_Type * base,uint32_t contextProcessor,uint32_t * slot0UsedChannel,uint32_t * slot1UsedChannel)238 static void ASRC_GetAvailableContextSlot(ASRC_Type *base,
239 uint32_t contextProcessor,
240 uint32_t *slot0UsedChannel,
241 uint32_t *slot1UsedChannel)
242 {
243 uint32_t contextIndex = 0U;
244
245 /* looking for available context processor */
246 if (ASRC_IS_SLOT0_ENABLED(contextProcessor))
247 {
248 contextIndex = ASRC_GET_SLOT0_CONTEXT_INDEX(contextProcessor);
249 if (ASRC_IS_CONTEXT_ENABLED(contextIndex))
250 {
251 *slot0UsedChannel = ASRC_GET_SLOT0_CHANNEL_NUMBER(contextProcessor);
252 }
253 }
254
255 if (ASRC_IS_SLOT1_ENABLED(contextProcessor))
256 {
257 contextIndex = ASRC_GET_SLOT1_CONTEXT_INDEX(contextProcessor);
258 if (ASRC_IS_CONTEXT_ENABLED(contextIndex))
259 {
260 *slot1UsedChannel = ASRC_GET_SLOT1_CHANNEL_NUMBER(contextProcessor);
261 }
262 }
263 }
264
ASRC_EnableContextSlot(ASRC_Type * base,uint32_t contextProcessor,uint32_t slot,uint32_t channelNums,uint32_t startChannel,asrc_context_t runningContext)265 static void ASRC_EnableContextSlot(ASRC_Type *base,
266 uint32_t contextProcessor,
267 uint32_t slot,
268 uint32_t channelNums,
269 uint32_t startChannel,
270 asrc_context_t runningContext)
271 {
272 assert(channelNums <= ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER);
273
274 if (slot == 0U)
275 {
276 base->PROC_CTRL_SLOT0_R0[contextProcessor] =
277 ASRC_PROC_CTRL_SLOT0_R0_SLOT0_EN_MASK | ASRC_PROC_CTRL_SLOT0_R0_SLOT0_CTX_NUM(runningContext) |
278 ASRC_PROC_CTRL_SLOT0_R0_SLOT0_NUM_CH(channelNums - 1U) |
279 ASRC_PROC_CTRL_SLOT0_R0_SLOT0_MIN_CH(startChannel) |
280 ASRC_PROC_CTRL_SLOT0_R0_SLOT0_MAX_CH(startChannel + channelNums - 1U);
281 }
282 else
283 {
284 base->PROC_CTRL_SLOT1_R0[contextProcessor] =
285 ASRC_PROC_CTRL_SLOT1_R0_SLOT1_EN_MASK | ASRC_PROC_CTRL_SLOT1_R0_SLOT1_CTX_NUM(runningContext) |
286 ASRC_PROC_CTRL_SLOT1_R0_SLOT1_NUM_CH(channelNums - 1U) |
287 ASRC_PROC_CTRL_SLOT1_R0_SLOT1_MIN_CH(startChannel) |
288 ASRC_PROC_CTRL_SLOT1_R0_SLOT1_MAX_CH(startChannel + channelNums - 1U);
289 }
290 }
291
ASRC_SetSampleRateRatioConfig(ASRC_Type * base,asrc_context_t context,uint32_t inputSampleRate,uint32_t outputSampleRate,asrc_samplerate_ratio_format_t format)292 static status_t ASRC_SetSampleRateRatioConfig(ASRC_Type *base,
293 asrc_context_t context,
294 uint32_t inputSampleRate,
295 uint32_t outputSampleRate,
296 asrc_samplerate_ratio_format_t format)
297 {
298 uint64_t ratio = 0U;
299 uint32_t fracBits = 0U;
300
301 uint32_t gcd = ASRC_GetSampleRateGCD(inputSampleRate, outputSampleRate);
302 uint32_t inRate = inputSampleRate / gcd;
303 uint32_t outRate = outputSampleRate / gcd;
304
305 if (format == kASRC_SampleRateRatio5Int39Frac)
306 {
307 fracBits = 39U;
308 }
309 else if (format == kASRC_SampleRateRatio6Int38Frac)
310 {
311 fracBits = 38U;
312 }
313 else
314 {
315 fracBits = 37U;
316 }
317
318 ratio = ((uint64_t)inRate << fracBits) / outRate;
319
320 base->RS_RATIO_LOW[context].RS_RATIO_LOW = (uint32_t)ratio & 0xFFFFFFFFU;
321 base->RS_RATIO_LOW[context].RS_RATIO_HIGH = ((uint32_t)(ratio >> 32U)) & 0xFFFFFFFFU;
322
323 return kStatus_Success;
324 }
325
ASRC_GetPrefilterConfig(asrc_context_prefilter_config_t * config,uint32_t inputSampleRate,uint32_t outputSampleRate)326 static status_t ASRC_GetPrefilterConfig(asrc_context_prefilter_config_t *config,
327 uint32_t inputSampleRate,
328 uint32_t outputSampleRate)
329 {
330 assert(config != NULL);
331
332 uint32_t gcd = ASRC_GetSampleRateGCD(inputSampleRate, outputSampleRate);
333 uint32_t inSampleRate = inputSampleRate / gcd;
334 uint32_t outSampleRate = outputSampleRate / gcd;
335 uint32_t i = 0U, offset = 0U;
336 const uint32_t *firmware = s_asrcFirmware;
337
338 /* while performing a up-conversion, the prefilter should be bypassed */
339 if (inputSampleRate <= outputSampleRate)
340 {
341 return kStatus_Success;
342 }
343
344 offset = (ASRC_FILTER_INTERPOLATION_FIRMWARE_LEN + 5U) * ASRC_FILTER_INTERPOLATION_FILTER_NUM;
345
346 /* load interpolation filter */
347 for (i = 0U; i < ASRC_FILTER_PREFILTER_FILTER_NUM; i++)
348 {
349 if (firmware[offset] != ASRC_FILTER_FIRMWARE_HEAD)
350 {
351 return kStatus_InvalidArgument;
352 }
353
354 if ((firmware[offset + ASRC_FILTER_PREFILTER_IN_SAMPLE_RATE_INDEX] == inSampleRate) &&
355 ((firmware[offset + ASRC_FILTER_PREFILTER_OUT_SAMPLE_RATE_INDEX] == outSampleRate)))
356 {
357 config->filterSt1Taps = firmware[offset + ASRC_FILTER_PREFILTER_STAGE_1_TAPS_INDEX];
358 config->filterSt2Taps = firmware[offset + ASRC_FILTER_PREFILTER_STAGE_2_TAPS_INDEX];
359 config->filterSt1Exp = firmware[offset + ASRC_FILTER_PREFILTER_STAGE_1_EXPANSION_FACTOR_INDEX];
360 config->filterCoeffAddress = &firmware[offset + ASRC_FILTER_PREFILTER_STAGE_1_DATA_INDEX];
361 break;
362 }
363 offset += ASRC_FILTER_PREFILTER_FIRMWARE_LEN + ASRC_FILTER_PREFILTER_STAGE_1_DATA_INDEX;
364 }
365
366 /* check if the interpolation filter firmware is founded */
367 if (config->filterCoeffAddress == NULL)
368 {
369 return kStatus_InvalidArgument;
370 }
371
372 return kStatus_Success;
373 }
374
ASRC_GetResamplerConfig(asrc_context_resampler_config_t * config,asrc_resampler_taps_t interpolationTap)375 static status_t ASRC_GetResamplerConfig(asrc_context_resampler_config_t *config, asrc_resampler_taps_t interpolationTap)
376 {
377 assert(config != NULL);
378
379 uint32_t i = 0U, offset = 0U;
380 const uint32_t *firmware = s_asrcFirmware;
381
382 /* load prefilter firmware */
383 for (i = 0U; i < ASRC_FILTER_INTERPOLATION_FILTER_NUM; i++)
384 {
385 if (firmware[offset] != ASRC_FILTER_FIRMWARE_HEAD)
386 {
387 return kStatus_InvalidArgument;
388 }
389
390 if (firmware[offset + ASRC_FILTER_INTERPOLATION_TAP_INDEX] == ((uint32_t)interpolationTap + 1U))
391 {
392 config->filterPhases = firmware[offset + ASRC_FILTER_INTERPOLATION_PHASE_INDEX];
393 config->filterCenterTap =
394 ((uint64_t)firmware[offset + 1U + ASRC_FILTER_INTERPOLATION_CENTER_TAP_INDEX] << 32U) +
395 firmware[offset + ASRC_FILTER_INTERPOLATION_CENTER_TAP_INDEX];
396 config->filterCoeffAddress = &firmware[offset + +1U + ASRC_FILTER_INTERPOLATION_DATA_INDEX];
397 break;
398 }
399 offset += ASRC_FILTER_INTERPOLATION_FIRMWARE_LEN + ASRC_FILTER_INTERPOLATION_DATA_INDEX + 1U;
400 }
401
402 /* check if the interpolation filter firmware is founded */
403 if (config->filterCoeffAddress == NULL)
404 {
405 return kStatus_InvalidArgument;
406 }
407
408 return kStatus_Success;
409 }
410
ASRC_SetPrefilterCoeffMemReset(ASRC_Type * base,asrc_context_t context)411 static void ASRC_SetPrefilterCoeffMemReset(ASRC_Type *base, asrc_context_t context)
412 {
413 base->CTX_CTRL_EXT1[context] &= ~ASRC_CTX_CTRL_EXT1_PF_COEFF_MEM_RST_MASK;
414 base->CTX_CTRL_EXT1[context] |= ASRC_CTX_CTRL_EXT1_PF_COEFF_MEM_RST_MASK;
415 base->CTX_CTRL_EXT1[context] &= ~ASRC_CTX_CTRL_EXT1_PF_COEFF_MEM_RST_MASK;
416 }
417
ASRC_SetPrefilterConfig(ASRC_Type * base,asrc_context_t context,asrc_context_prefilter_config_t * config)418 static status_t ASRC_SetPrefilterConfig(ASRC_Type *base,
419 asrc_context_t context,
420 asrc_context_prefilter_config_t *config)
421 {
422 uint32_t contextReg = base->CTX_CTRL_EXT1[context];
423 const uint32_t *coeffPointer = config->filterCoeffAddress;
424 uint32_t i = 0U, j = 0U;
425
426 if (coeffPointer == NULL)
427 {
428 return kStatus_InvalidArgument;
429 }
430
431 contextReg &= ~(ASRC_CTX_CTRL_EXT1_PF_INIT_MODE_MASK | ASRC_CTX_CTRL_EXT1_PF_STOP_MODE_MASK |
432 ASRC_CTX_CTRL_EXT1_PF_EXPANSION_FACTOR_MASK | ASRC_CTX_CTRL_EXT1_PF_ST1_WB_FLOAT_MASK |
433 ASRC_CTX_CTRL_EXT1_PF_TWO_STAGE_EN_MASK);
434
435 contextReg |= ASRC_CTX_CTRL_EXT1_PF_INIT_MODE(config->initMode) |
436 ASRC_CTX_CTRL_EXT1_PF_STOP_MODE(config->stopMode) |
437 ASRC_CTX_CTRL_EXT1_PF_EXPANSION_FACTOR(config->filterSt1Exp - 1U) |
438 ASRC_CTX_CTRL_EXT1_PF_ST1_WB_FLOAT(config->stage1Result) |
439 ASRC_CTX_CTRL_EXT1_PF_TWO_STAGE_EN(config->filterSt2Taps != 0U ? 1U : 0U);
440
441 base->CTX_CTRL_EXT1[context] = contextReg;
442 base->CTX_CTRL_EXT2[context] = ASRC_CTX_CTRL_EXT2_ST1_NUM_TAPS(config->filterSt1Taps - 1U) |
443 ASRC_CTX_CTRL_EXT2_ST2_NUM_TAPS(config->filterSt2Taps - 1U);
444
445 /* reset prefilter coefficient memory */
446 ASRC_SetPrefilterCoeffMemReset(base, context);
447 /* load stage1 */
448 base->CTX_CTRL_EXT1[context] &= ~ASRC_CTX_CTRL_EXT1_PF_COEFF_STAGE_WR_MASK;
449
450 for (i = 0; i < ((config->filterSt1Taps + 1U) / 2U) * 2U; i++)
451 {
452 base->PRE_COEFF_FIFO[context] = coeffPointer[i];
453 }
454
455 /* reset prefilter coefficient memory */
456 ASRC_SetPrefilterCoeffMemReset(base, context);
457 /* load stage2 */
458 if (config->filterSt2Taps != 0U)
459 {
460 base->CTX_CTRL_EXT1[context] |= ASRC_CTX_CTRL_EXT1_PF_COEFF_STAGE_WR_MASK;
461 for (j = 0; j < ((config->filterSt2Taps + 1U) / 2U) * 2U; j++)
462 {
463 base->PRE_COEFF_FIFO[context] = coeffPointer[i + j];
464 }
465 }
466
467 return kStatus_Success;
468 }
469
ASRC_SetResamplerConfig(ASRC_Type * base,asrc_context_t context,asrc_context_resampler_config_t * config)470 static status_t ASRC_SetResamplerConfig(ASRC_Type *base,
471 asrc_context_t context,
472 asrc_context_resampler_config_t *config)
473 {
474 uint32_t contextReg = base->CTX_CTRL_EXT1[context];
475 uint32_t i = 0U;
476 const uint32_t *coeffPointer = config->filterCoeffAddress;
477
478 contextReg &= ~(ASRC_CTX_CTRL_EXT1_RS_INIT_MODE_MASK | ASRC_CTX_CTRL_EXT1_RS_STOP_MODE_MASK);
479 contextReg |= ASRC_CTX_CTRL_EXT1_RS_INIT_MODE(config->initMode) | ASRC_CTX_CTRL_EXT1_RS_STOP_MODE(config->stopMode);
480 base->CTX_CTRL_EXT1[context] = contextReg;
481
482 /* center tap */
483 base->RS_CT_LOW = (uint32_t)config->filterCenterTap & 0xFFFFFFFFU;
484 base->RS_CT_HIGH = (uint32_t)(config->filterCenterTap >> 32U) & 0xFFFFFFFFU;
485
486 /* resampler taps */
487 contextReg = base->CTX_RS_COEFF_CTRL;
488 contextReg &= ~ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS_MASK;
489
490 if (config->tap == kASRC_ResamplerTaps_32)
491 {
492 contextReg |= ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS(0);
493 }
494 else if (config->tap == kASRC_ResamplerTaps_64)
495 {
496 contextReg |= ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS(1);
497 }
498 else
499 {
500 contextReg |= ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS(2);
501 }
502 base->CTX_RS_COEFF_CTRL = contextReg;
503
504 /* load coefficient */
505 /* reset coefficient memory firstly */
506 base->CTX_RS_COEFF_CTRL &= ~ASRC_CTX_RS_COEFF_CTRL_RS_COEFF_PTR_RST_MASK;
507 base->CTX_RS_COEFF_CTRL |= ASRC_CTX_RS_COEFF_CTRL_RS_COEFF_PTR_RST_MASK;
508 base->CTX_RS_COEFF_CTRL &= ~ASRC_CTX_RS_COEFF_CTRL_RS_COEFF_PTR_RST_MASK;
509
510 for (i = 0U; i < ASRC_FILTER_INTERPOLATION_FIRMWARE_LEN; i++)
511 {
512 base->CTX_RS_COEFF_MEM = coeffPointer[i];
513 }
514
515 return kStatus_Success;
516 }
517
ASRC_SetSlotConfig(ASRC_Type * base,asrc_context_t context,uint32_t requestChannel,asrc_context_prefilter_config_t * config)518 static status_t ASRC_SetSlotConfig(ASRC_Type *base,
519 asrc_context_t context,
520 uint32_t requestChannel,
521 asrc_context_prefilter_config_t *config)
522 {
523 uint32_t availableSlot = 0U, availableContext = 0U, availableChannel = 0U, startChannel = 0U;
524 uint32_t i = 0U;
525 uint32_t slot0UsedChannel = 0U, slot1UsedChannel = 0U;
526 uint32_t stage1MemSize = 0U, stage1MemAddr = 0U, stage2MemSize = 0U, stage2MemAddr = 0U, stage1Exp = 0U;
527 uint32_t leftChannel = requestChannel;
528
529 for (i = 0U; i < ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER; i++)
530 {
531 /* record start channel */
532 startChannel += availableChannel;
533
534 ASRC_GetAvailableContextSlot(base, i, &slot0UsedChannel, &slot1UsedChannel);
535
536 /* context is busy */
537 if ((slot0UsedChannel != 0U) && ((slot1UsedChannel != 0U)))
538 {
539 continue;
540 }
541 /* context is idle */
542 if ((slot0UsedChannel == 0U) && (slot1UsedChannel == 0U))
543 {
544 availableSlot = 0U;
545 availableChannel = ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER;
546 availableContext = i;
547 }
548 /* context slot 0 is busy, slot 1 is idle */
549 else if (slot0UsedChannel != 0U)
550 {
551 availableSlot = 1U;
552 availableChannel = ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER - slot0UsedChannel;
553 availableContext = i;
554 }
555 /* context slot0 is idle, slot 1 is busy, ((slot0UsedChannel == 0U) && (slot1UsedChannel != 0U))*/
556 else
557 {
558 availableSlot = 0U;
559 availableChannel = ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER - slot1UsedChannel;
560 availableContext = i;
561 }
562
563 availableChannel = availableChannel > leftChannel ? leftChannel : availableChannel;
564 leftChannel -= availableChannel;
565 /* enable the available slot */
566 ASRC_EnableContextSlot(base, availableContext, availableSlot, availableChannel, startChannel, context);
567
568 if (availableSlot == 0U)
569 {
570 if (config->filterSt2Taps != 0U)
571 {
572 stage1Exp = (config->filterSt1Exp - 1U) * availableChannel;
573 stage1MemSize =
574 (config->filterSt1Taps - 1U) * config->filterSt1Exp * availableChannel + availableChannel;
575 stage1MemAddr = 0U;
576 stage2MemSize = availableChannel * config->filterSt2Taps;
577 stage2MemAddr = stage1MemSize;
578 }
579 else
580 {
581 stage1MemSize = availableChannel * config->filterSt1Taps;
582 stage1MemAddr = 0U;
583 }
584
585 base->PROC_CTRL_SLOT0_R1[availableContext] = stage1Exp;
586 base->PROC_CTRL_SLOT0_R2[availableContext] = ASRC_PROC_CTRL_SLOT0_R2_SLOT0_ST1_ST_ADDR(stage1MemAddr) |
587 ASRC_PROC_CTRL_SLOT0_R2_SLOT0_ST1_MEM_ALLOC(stage1MemSize);
588 base->PROC_CTRL_SLOT0_R3[availableContext] = ASRC_PROC_CTRL_SLOT0_R3_SLOT0_ST2_ST_ADDR(stage2MemAddr) |
589 ASRC_PROC_CTRL_SLOT0_R3_SLOT0_ST2_MEM_ALLOC(stage2MemSize);
590 }
591 else
592 {
593 if (config->filterSt2Taps != 0U)
594 {
595 stage1Exp = (config->filterSt1Exp - 1U) * availableChannel;
596 stage1MemSize =
597 (config->filterSt1Taps - 1U) * config->filterSt1Exp * availableChannel + availableChannel;
598 stage1MemAddr = 0x1800U - stage1MemSize;
599 stage2MemSize = availableChannel * config->filterSt2Taps;
600 stage2MemAddr = 0x1800U - stage1MemSize - stage2MemSize;
601 }
602 else
603 {
604 stage1MemSize = availableChannel * config->filterSt1Taps;
605 stage1MemAddr = 0x1800U - stage1MemSize;
606 }
607
608 base->PROC_CTRL_SLOT1_R1[availableContext] = stage1Exp;
609 base->PROC_CTRL_SLOT1_R2[availableContext] = ASRC_PROC_CTRL_SLOT1_R2_SLOT1_ST1_ST_ADDR(stage1MemAddr) |
610 ASRC_PROC_CTRL_SLOT1_R2_SLOT1_ST1_MEM_ALLOC(stage1MemSize);
611 base->PROC_CTRL_SLOT1_R3[availableContext] = ASRC_PROC_CTRL_SLOT1_R3_SLOT1_ST2_ST_ADDR(stage2MemAddr) |
612 ASRC_PROC_CTRL_SLOT1_R3_SLOT1_ST2_MEM_ALLOC(stage2MemSize);
613 }
614
615 /* one context processor can satisfy the channel requirement*/
616 if (leftChannel == 0U)
617 {
618 return kStatus_Success;
619 }
620 /* multiple slot across context processor is required */
621 else
622 {
623 continue;
624 }
625 }
626
627 return kStatus_Fail;
628 }
629
ASRC_SetContextProcessorConfig(ASRC_Type * base,asrc_context_t context,asrc_context_config_t * config)630 static status_t ASRC_SetContextProcessorConfig(ASRC_Type *base, asrc_context_t context, asrc_context_config_t *config)
631 {
632 assert(config != NULL);
633
634 /* bypass resampler */
635 if (config->contextInput.sampleRate == config->contextOutput.sampleRate)
636 {
637 ASRC_EnableResamplerBypass(base, context, true);
638 }
639 else
640 {
641 /* ensure resampler is not bypassed */
642 ASRC_EnableResamplerBypass(base, context, false);
643
644 if (config->contextResampler.filterCoeffAddress == NULL)
645 {
646 if (ASRC_GetResamplerConfig(&config->contextResampler, config->contextResampler.tap) != kStatus_Success)
647 {
648 return kStatus_InvalidArgument;
649 }
650 }
651 /* resampler configuration */
652 if (ASRC_SetResamplerConfig(base, context, &config->contextResampler) != kStatus_Success)
653 {
654 return kStatus_ASRCResamplerConfigureFailed;
655 }
656 }
657
658 /* up conversion should bypass the prefilter */
659 if (config->contextInput.sampleRate <= config->contextOutput.sampleRate)
660 {
661 /* prefilter bypass mode */
662 ASRC_EnablePreFilterBypass(base, context, true);
663 }
664 else
665 {
666 /* ensure prefilter not in bypass mode */
667 ASRC_EnablePreFilterBypass(base, context, false);
668 /* load default configuration if not assigned by application */
669 if (config->contextPrefilter.filterCoeffAddress == NULL)
670 {
671 if (ASRC_GetPrefilterConfig(&config->contextPrefilter, config->contextInput.sampleRate,
672 config->contextOutput.sampleRate) == kStatus_InvalidArgument)
673 {
674 return kStatus_InvalidArgument;
675 }
676 }
677 if (ASRC_SetPrefilterConfig(base, context, &config->contextPrefilter) != kStatus_Success)
678 {
679 return kStatus_ASRCPrefilterConfigureFailed;
680 }
681 }
682
683 /* set channel number in context */
684 ASRC_SetContextChannelNumber(base, context, config->contextChannelNums);
685
686 return ASRC_SetSlotConfig(base, context, config->contextChannelNums, &config->contextPrefilter);
687 }
688
689 /*!
690 * brief Initializes the asrc peripheral.
691 *
692 * This API gates the asrc clock. The asrc module can't operate unless ASRC_Init is called to enable the clock.
693 *
694 * param base asrc base pointer.
695 */
ASRC_Init(ASRC_Type * base)696 void ASRC_Init(ASRC_Type *base)
697 {
698 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
699 /* Enable the asrc clock */
700 CLOCK_EnableClock(s_asrcClock[ASRC_GetInstance(base)]);
701 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
702
703 for (uint32_t i = 0U; i < ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER; i++)
704 {
705 /* disable ASRC module and reset ASRC slot configurations*/
706 base->CTX_CTRL[i] = 0U;
707 base->CTX_OUT_CTRL[i] = 0U;
708 base->PROC_CTRL_SLOT0_R0[i] = 0U;
709 base->PROC_CTRL_SLOT1_R0[i] = 0U;
710 }
711
712 /* disable all the interrupt */
713 base->IRQ_CTRL = 0U;
714 base->IRQ_FLAGS = 0xFFFU;
715 }
716
717 /*!
718 * brief De-initializes the ASRC peripheral.
719 *
720 * This API gates the ASRC clock and disable ASRC module. The ASRC module can't operate unless ASRC_Init
721 *
722 * param base ASRC base pointer.
723 */
ASRC_Deinit(ASRC_Type * base)724 void ASRC_Deinit(ASRC_Type *base)
725 {
726 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
727 CLOCK_DisableClock(s_asrcClock[ASRC_GetInstance(base)]);
728 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
729 }
730
731 /*!
732 * brief ASRC configure context input.
733 *
734 * param base ASRC base pointer.
735 * param context index of asrc context, reference asrc_context_t.
736 * param config ASRC context input configuration pointer.
737 */
ASRC_SetContextInputConfig(ASRC_Type * base,asrc_context_t context,asrc_context_input_config_t * config)738 status_t ASRC_SetContextInputConfig(ASRC_Type *base, asrc_context_t context, asrc_context_input_config_t *config)
739 {
740 assert(config != NULL);
741
742 uint32_t contextReg = base->CTX_CTRL[context];
743
744 contextReg &= ~(ASRC_CTX_CTRL_SIGN_IN_MASK | ASRC_CTX_CTRL_FLOAT_FMT_MASK | ASRC_CTX_CTRL_BITS_PER_SAMPLE_MASK |
745 ASRC_CTX_CTRL_BIT_REV_MASK | ASRC_CTX_CTRL_SAMPLE_POSITION_MASK | ASRC_CTX_CTRL_FIFO_WTMK_MASK);
746
747 contextReg |= ASRC_CTX_CTRL_FIFO_WTMK(config->watermark);
748
749 contextReg |= ASRC_CTX_CTRL_SIGN_IN(config->dataFormat.dataSign) |
750 ASRC_CTX_CTRL_FLOAT_FMT(config->dataFormat.dataType) |
751 ASRC_CTX_CTRL_BITS_PER_SAMPLE(config->dataFormat.dataWidth) |
752 ASRC_CTX_CTRL_BIT_REV(config->dataFormat.dataEndianness) |
753 ASRC_CTX_CTRL_SAMPLE_POSITION(config->dataFormat.dataPosition);
754
755 base->CTX_CTRL[context] = contextReg;
756
757 base->CTRL_IN_ACCESS[context] = ASRC_CTRL_IN_ACCESS_ACCESS_LENGTH(config->accessCtrl.accessLen) |
758 ASRC_CTRL_IN_ACCESS_ITERATIONS(config->accessCtrl.accessIterations) |
759 ASRC_CTRL_IN_ACCESS_GROUP_LENGTH(config->accessCtrl.accessGroupLen);
760
761 return kStatus_Success;
762 }
763
764 /*!
765 * brief ASRC configure context output.
766 *
767 * param base ASRC base pointer.
768 * param context index of asrc context, reference asrc_context_t.
769 * param config ASRC context output configuration pointer.
770 */
ASRC_SetContextOutputConfig(ASRC_Type * base,asrc_context_t context,asrc_context_output_config_t * config)771 status_t ASRC_SetContextOutputConfig(ASRC_Type *base, asrc_context_t context, asrc_context_output_config_t *config)
772 {
773 assert(config != NULL);
774
775 uint32_t contextReg = base->CTX_OUT_CTRL[context];
776 uint32_t samplePosition = config->dataFormat.dataPosition;
777
778 contextReg &=
779 ~(ASRC_CTX_OUT_CTRL_SIGN_OUT_MASK | ASRC_CTX_OUT_CTRL_FLOAT_FMT_MASK | ASRC_CTX_OUT_CTRL_IEC_V_DATA_MASK |
780 ASRC_CTX_OUT_CTRL_DITHER_EN_MASK | ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE_MASK | ASRC_CTX_OUT_CTRL_BIT_REV_MASK |
781 ASRC_CTX_OUT_CTRL_SAMPLE_POSITION_MASK | ASRC_CTX_OUT_CTRL_FIFO_WTMK_MASK);
782
783 contextReg |= ASRC_CTX_OUT_CTRL_FIFO_WTMK(config->watermark);
784
785 if (config->enableIEC60958)
786 {
787 if (config->dataFormat.dataWidth == kASRC_DataWidth16Bit)
788 {
789 samplePosition = 12U;
790 }
791 else if (config->dataFormat.dataWidth == kASRC_DataWidth20Bit)
792 {
793 samplePosition = 8U;
794 }
795 else if (config->dataFormat.dataWidth == kASRC_DataWidth24Bit)
796 {
797 samplePosition = 4U;
798 }
799 else
800 {
801 return kStatus_InvalidArgument;
802 }
803
804 contextReg |= ASRC_CTX_OUT_CTRL_IEC_V_DATA_MASK;
805 }
806
807 contextReg |= ASRC_CTX_OUT_CTRL_DITHER_EN(config->enableDither);
808
809 contextReg |= ASRC_CTX_OUT_CTRL_SIGN_OUT(config->dataFormat.dataSign) |
810 ASRC_CTX_OUT_CTRL_FLOAT_FMT(config->dataFormat.dataType) |
811 ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE(config->dataFormat.dataWidth) |
812 ASRC_CTX_OUT_CTRL_BIT_REV(config->dataFormat.dataEndianness) |
813 ASRC_CTX_OUT_CTRL_SAMPLE_POSITION(samplePosition);
814
815 base->CTX_OUT_CTRL[context] = contextReg;
816
817 base->CTRL_OUT_ACCESS[context] = ASRC_CTRL_OUT_ACCESS_ACCESS_LENGTH(config->accessCtrl.accessLen) |
818 ASRC_CTRL_OUT_ACCESS_ITERATIONS(config->accessCtrl.accessIterations) |
819 ASRC_CTRL_OUT_ACCESS_GROUP_LENGTH(config->accessCtrl.accessGroupLen);
820
821 return kStatus_Success;
822 }
823
824 /*!
825 * brief ASRC get context default configuration.
826 *
827 * param config ASRC context configuration pointer.
828 * param channels input audio data channel numbers.
829 * param inSampleRate input sample rate.
830 * param outSampleRate output sample rate.
831 */
ASRC_GetContextDefaultConfig(asrc_context_config_t * config,uint32_t channels,uint32_t inSampleRate,uint32_t outSampleRate)832 void ASRC_GetContextDefaultConfig(asrc_context_config_t *config,
833 uint32_t channels,
834 uint32_t inSampleRate,
835 uint32_t outSampleRate)
836 {
837 assert(config != NULL);
838
839 (void)memset(config, 0, sizeof(asrc_context_config_t));
840
841 config->contextChannelNums = (uint8_t)channels;
842
843 /* input configuration */
844 config->contextInput.sampleRate = inSampleRate;
845 config->contextInput.watermark = FSL_ASRC_INPUT_FIFO_DEPTH / 2U;
846 config->contextInput.accessCtrl.accessIterations = 1;
847 config->contextInput.accessCtrl.accessGroupLen = (uint8_t)channels;
848 config->contextInput.accessCtrl.accessLen = (uint8_t)channels;
849 config->contextInput.dataFormat.dataPosition = 0U;
850 config->contextInput.dataFormat.dataEndianness = kASRC_DataEndianLittle;
851 config->contextInput.dataFormat.dataWidth = kASRC_DataWidth16Bit;
852 config->contextInput.dataFormat.dataType = kASRC_DataTypeInteger;
853 config->contextInput.dataFormat.dataSign = kASRC_DataSigned;
854 /* output configuration */
855 config->contextOutput.sampleRate = outSampleRate;
856 config->contextOutput.watermark = FSL_ASRC_OUTPUT_FIFO_DEPTH / 8U;
857 config->contextOutput.accessCtrl.accessIterations = 1;
858 config->contextOutput.accessCtrl.accessGroupLen = (uint8_t)channels;
859 config->contextOutput.accessCtrl.accessLen = (uint8_t)channels;
860 config->contextOutput.dataFormat.dataPosition = 0;
861 config->contextOutput.dataFormat.dataEndianness = kASRC_DataEndianLittle;
862 config->contextOutput.dataFormat.dataWidth = kASRC_DataWidth16Bit;
863 config->contextOutput.dataFormat.dataType = kASRC_DataTypeInteger;
864 config->contextOutput.dataFormat.dataSign = kASRC_DataSigned;
865 config->contextOutput.enableDither = false;
866 config->contextOutput.enableIEC60958 = false;
867 /* prefilter configuration */
868 config->contextPrefilter.initMode = kASRC_SampleBufferFillZeroOnInit;
869 config->contextPrefilter.stopMode = kASRC_SampleBufferFillLastSampleOnStop;
870 config->contextPrefilter.stage1Result = kASRC_PrefilterStage1ResultFloat;
871 /* resampler configuration */
872 config->contextResampler.initMode = kASRC_SampleBufferFillZeroOnInit;
873 config->contextResampler.stopMode = kASRC_SampleBufferFillLastSampleOnStop;
874 config->contextResampler.tap = kASRC_ResamplerTaps_128;
875 }
876
877 /*!
878 * brief ASRC configure context.
879 *
880 * param base ASRC base pointer.
881 * param context index of asrc context, reference asrc_context_t.
882 * param config ASRC context configuration pointer.
883 * retval kStatus_InvalidArgument invalid parameters.
884 * kStatus_ASRCConfigureFailed context configure failed.
885 * kStatus_Success context configure success.
886 */
ASRC_SetContextConfig(ASRC_Type * base,asrc_context_t context,asrc_context_config_t * config)887 status_t ASRC_SetContextConfig(ASRC_Type *base, asrc_context_t context, asrc_context_config_t *config)
888 {
889 assert(config != NULL);
890
891 if ((config->contextChannelNums == 0U) || (config->contextChannelNums > ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMBER))
892 {
893 return kStatus_InvalidArgument;
894 }
895
896 if (((config->contextInput.sampleRate < (uint32_t)kASRC_SampleRate_8000) ||
897 (config->contextInput.sampleRate > (uint32_t)kASRC_SampleRate_768000)) ||
898 ((config->contextOutput.sampleRate < (uint32_t)kASRC_SampleRate_8000) ||
899 (config->contextOutput.sampleRate > (uint32_t)kASRC_SampleRate_768000)))
900 {
901 return kStatus_InvalidArgument;
902 }
903
904 /* sampel ratio configure */
905 if (ASRC_SetSampleRateRatioConfig(base, context, config->contextInput.sampleRate, config->contextOutput.sampleRate,
906 (asrc_samplerate_ratio_format_t)config->contextResampler.tap) != kStatus_Success)
907 {
908 return kStatus_ASRCConfigureFailed;
909 }
910
911 /* configure context input */
912 if (ASRC_SetContextInputConfig(base, context, &config->contextInput) != kStatus_Success)
913 {
914 return kStatus_ASRCConfigureFailed;
915 }
916
917 /* allocate context processor */
918 if (ASRC_SetContextProcessorConfig(base, context, config) != kStatus_Success)
919 {
920 return kStatus_ASRCConfigureFailed;
921 }
922
923 /* configure context output */
924 if (ASRC_SetContextOutputConfig(base, context, &config->contextOutput) != kStatus_Success)
925 {
926 return kStatus_ASRCConfigureFailed;
927 }
928
929 return kStatus_Success;
930 }
931
932 /*!
933 * brief ASRC get output sample count.
934 *
935 * param inSampleRate output sample rate.
936 * param inSamplesSize input sample rate.
937 * param inWidth input samples buffer size, the size of buffer should be converted to align with 4 byte .
938 * param outSampleRate input sample width.
939 * param outWidth Output width.
940 * retval output samples size.
941 */
ASRC_GetContextOutSampleSize(uint32_t inSampleRate,uint32_t inSamplesSize,uint32_t inWidth,uint32_t outSampleRate,uint32_t outWidth)942 uint32_t ASRC_GetContextOutSampleSize(
943 uint32_t inSampleRate, uint32_t inSamplesSize, uint32_t inWidth, uint32_t outSampleRate, uint32_t outWidth)
944 {
945 uint32_t reminder = (((uint64_t)inSamplesSize / inWidth) * outSampleRate % inSampleRate) == 0U ? 0U : 1U;
946 uint32_t quotient = (uint32_t)(((uint64_t)inSamplesSize / inWidth) * outSampleRate / inSampleRate);
947
948 return (reminder + quotient) * outWidth;
949 }
950
951 /*!
952 * brief Get the ASRC read fifo remained samples.
953 * Since the DMA request will be triggered only when the sample group in read fifo is bigger then the watermark, so when
954 * the data size cannot be divisible by the (watermark + 1), then part of sample will left in read fifo, application
955 * should call this api to get the left samples.
956 *
957 * param base ASRC base pointer.
958 * param context context id.
959 * param outAddr address to receive remained sample in read fifo.
960 * param outWidth output data width.
961 * param sampleCount specify the read sample count.
962 * retval sample counts actual read from output fifo.
963 */
ASRC_ReadFIFORemainedSample(ASRC_Type * base,asrc_context_t context,uint32_t * outAddr,uint32_t outWidth,uint32_t sampleCount)964 uint32_t ASRC_ReadFIFORemainedSample(
965 ASRC_Type *base, asrc_context_t context, uint32_t *outAddr, uint32_t outWidth, uint32_t sampleCount)
966 {
967 uint32_t remainSample = base->SAMPLE_FIFO_STATUS[context] & ASRC_SAMPLE_FIFO_STATUS_NUM_SAMPLE_GROUPS_OUT_MASK;
968 uint32_t channel = (base->CTX_CTRL[context] & ASRC_CTX_CTRL_NUM_CH_EN_MASK) + 1U;
969 uint32_t i = 0U, sizeToRead = remainSample * channel;
970
971 if (sizeToRead == 0U)
972 {
973 return 0U;
974 }
975
976 if (sampleCount < sizeToRead)
977 {
978 sizeToRead = sampleCount;
979 }
980
981 for (i = 0U; i < sizeToRead; i++)
982 {
983 *outAddr = ASRC_ReadContextFifo(base, context);
984 outAddr = (uint32_t *)((size_t)outAddr + outWidth);
985 }
986
987 return sizeToRead;
988 }
989
990 /*!
991 * brief ASRC blocking convert audio sample rate.
992 * This function depends on the configuration of input and output, so it should be called after the
993 * ASRC_SetContextConfig. The data format it supports:
994 * 1.16bit 16bit per sample in input buffer, input buffer size
995 * should be calculate as: samples 2U output buffer size can be calculated by call function
996 * ASRC_GetContextOutSampleSize, the parameter outWidth should be 2
997 * 2.20bit 24bit per sample in input buffer, input buffer size should be calculate as: samples 3U output buffer size can
998 * be calculated by call function ASRC_GetContextOutSampleSize, the outWidth should be 3. 3.24bit 24bit per sample in
999 * input buffer, input buffer size should be calculate as: samples * 3U output buffer size can be calculated by call
1000 * function ASRC_GetContextOutSampleSize, the outWidth should be 3. 4.32bit 32bit per sample in input buffer, input
1001 * buffer size should be calculate as: samples * 4U output buffer size can be calculated by call function
1002 * ASRC_GetContextOutSampleSize, the outWidth should be 4.
1003 *
1004 * param base ASRC base pointer.
1005 * param context context id.
1006 * param xfer .xfer configuration.
1007 * retval kStatus_Success.
1008 */
ASRC_TransferBlocking(ASRC_Type * base,asrc_context_t context,asrc_transfer_t * xfer)1009 status_t ASRC_TransferBlocking(ASRC_Type *base, asrc_context_t context, asrc_transfer_t *xfer)
1010 {
1011 assert((xfer->inDataAddr != NULL) && (xfer->outDataAddr != NULL));
1012 assert(xfer->inDataSize % sizeof(uint32_t) == 0U);
1013
1014 uint32_t inWatermarkSamples =
1015 (((base->CTX_CTRL[context] & ASRC_CTX_CTRL_FIFO_WTMK_MASK) >> ASRC_CTX_CTRL_FIFO_WTMK_SHIFT) + 1U) *
1016 ((base->CTX_CTRL[context] & ASRC_CTX_CTRL_NUM_CH_EN_MASK) + 1U);
1017 uint32_t outWatermarkSamples =
1018 (((base->CTX_OUT_CTRL[context] & ASRC_CTX_OUT_CTRL_FIFO_WTMK_MASK) >> ASRC_CTX_OUT_CTRL_FIFO_WTMK_SHIFT) + 1U) *
1019 ((base->CTX_CTRL[context] & ASRC_CTX_CTRL_NUM_CH_EN_MASK) + 1U);
1020 uint32_t inWidth =
1021 ((base->CTX_CTRL[context] & ASRC_CTX_CTRL_BITS_PER_SAMPLE_MASK) >> ASRC_CTX_CTRL_BITS_PER_SAMPLE_SHIFT);
1022 uint32_t outWidth = ((base->CTX_OUT_CTRL[context] & ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE_MASK) >>
1023 ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE_SHIFT);
1024 uint32_t inMask =
1025 (inWidth == (uint32_t)kASRC_DataWidth32Bit ? 0xFFFFFFFFU :
1026 inWidth == (uint32_t)kASRC_DataWidth24Bit ?
1027 0xFFFFFFU :
1028 inWidth == (uint32_t)kASRC_DataWidth20Bit ? 0xFFFFFU : 0xFFFFU);
1029 inWidth =
1030 (inWidth == (uint32_t)kASRC_DataWidth32Bit ?
1031 4U :
1032 inWidth == (uint32_t)kASRC_DataWidth24Bit ? 3U : inWidth == (uint32_t)kASRC_DataWidth20Bit ? 3U : 2U);
1033 outWidth =
1034 (outWidth == (uint32_t)kASRC_DataWidth32Bit ?
1035 4U :
1036 outWidth == (uint32_t)kASRC_DataWidth24Bit ? 3U : outWidth == (uint32_t)kASRC_DataWidth20Bit ? 3U : 2U);
1037 uint32_t inSamples = xfer->inDataSize / inWidth;
1038 uint32_t outSamples = xfer->outDataSize / outWidth;
1039 uint32_t *writePointer = xfer->inDataAddr;
1040 uint32_t *readPointer = xfer->outDataAddr;
1041
1042 uint32_t writtenSamples = 0U, readSamples = 0U, i = 0U, j = 0U;
1043 /* enable context run */
1044 ASRC_EnableContextRun(base, context, true);
1045 ASRC_EnableContextRunStop(base, context, false);
1046
1047 while ((inSamples != 0U) || (outSamples != 0U))
1048 {
1049 if (inSamples != 0U)
1050 {
1051 if (inSamples < inWatermarkSamples)
1052 {
1053 writtenSamples = inSamples;
1054 }
1055 else
1056 {
1057 writtenSamples = inWatermarkSamples;
1058 }
1059
1060 if ((ASRC_GetFifoStatus(base, context) & (uint32_t)kASRC_FifoStatusInputFifoWatermarkFlag) != 0U)
1061 {
1062 for (i = 0U; i < writtenSamples; i++)
1063 {
1064 ASRC_WriteContextFifo(base, context, *writePointer & inMask);
1065 writePointer = (uint32_t *)((size_t)writePointer + inWidth);
1066 }
1067
1068 inSamples -= writtenSamples;
1069 }
1070 }
1071
1072 if (outSamples <= outWatermarkSamples)
1073 {
1074 readSamples = ASRC_ReadFIFORemainedSample(base, context, readPointer, outWidth, outSamples);
1075 /* for the case that all the output samples have write to the output fifo and all the fifo samples has been
1076 * read */
1077 if (((ASRC_GetInterruptStatus(base) & ((uint32_t)kASRC_Context0RunStopDone << (uint32_t)context)) != 0U) &&
1078 (readSamples == 0U))
1079 {
1080 ASRC_ClearInterruptStatus(base, ((uint32_t)kASRC_Context0RunStopDone << (uint32_t)context));
1081 break;
1082 }
1083 outSamples -= readSamples;
1084 continue;
1085 }
1086 else
1087 {
1088 readSamples = outWatermarkSamples;
1089 }
1090
1091 if ((ASRC_GetFifoStatus(base, context) & (uint32_t)kASRC_FifoStatusOutputFifoWatermarkFlag) != 0U)
1092 {
1093 for (j = 0U; j < readSamples; j++)
1094 {
1095 *readPointer = ASRC_ReadContextFifo(base, context);
1096 readPointer = (uint32_t *)((size_t)readPointer + outWidth);
1097 }
1098 outSamples -= readSamples;
1099 }
1100 else
1101 {
1102 /* flush all the samples out */
1103 if ((inSamples == 0U) && (outSamples > outWatermarkSamples))
1104 {
1105 ASRC_EnableContextRunStop(base, context, true);
1106 }
1107 }
1108 }
1109
1110 /* disable context run */
1111 ASRC_EnableContextRun(base, context, false);
1112 ASRC_EnableContextRunStop(base, context, false);
1113
1114 return kStatus_Success;
1115 }
1116