File indexing completed on 2025-05-11 08:23:00
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fsl_pdm.h"
0010
0011 #ifndef FSL_COMPONENT_ID
0012 #define FSL_COMPONENT_ID "platform.drivers.pdm"
0013 #endif
0014
0015
0016
0017
0018
0019 typedef void (*pdm_isr_t)(PDM_Type *base, pdm_handle_t *pdmHandle);
0020
0021
0022
0023 #if !(defined FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV && FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV)
0024
0025
0026
0027
0028
0029
0030
0031
0032 static status_t PDM_ValidateSrcClockRate(uint32_t channelMask,
0033 pdm_df_quality_mode_t qualityMode,
0034 uint8_t osr,
0035 uint32_t regDiv);
0036 #endif
0037
0038
0039
0040
0041
0042 static PDM_Type *const s_pdmBases[] = PDM_BASE_PTRS;
0043
0044 static pdm_handle_t *s_pdmHandle[ARRAY_SIZE(s_pdmBases)];
0045 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0046
0047 static const clock_ip_name_t s_pdmClock[] = PDM_CLOCKS;
0048 #endif
0049
0050 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0051 #if defined(FSL_PDM_HAS_FILTER_CLOCK_GATE) && FSL_PDM_HAS_FILTER_CLOCK_GATE
0052
0053 static const clock_ip_name_t s_pdmFilterClock[] = PDM_FILTER_CLOCKS;
0054 #endif
0055 #endif
0056
0057
0058 static pdm_isr_t s_pdmIsr;
0059 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
0060
0061 static pdm_hwvad_notification_t s_pdm_hwvad_notification[ARRAY_SIZE(s_pdmBases)];
0062 #endif
0063
0064
0065
0066 uint32_t PDM_GetInstance(PDM_Type *base)
0067 {
0068 uint32_t instance;
0069
0070
0071 for (instance = 0; instance < ARRAY_SIZE(s_pdmBases); instance++)
0072 {
0073 if (s_pdmBases[instance] == base)
0074 {
0075 break;
0076 }
0077 }
0078
0079 assert(instance < ARRAY_SIZE(s_pdmBases));
0080
0081 return instance;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 void PDM_ReadFifo(
0096 PDM_Type *base, uint32_t startChannel, uint32_t channelNums, void *buffer, size_t size, uint32_t dataWidth)
0097 {
0098 uint32_t i = 0, j = 0U;
0099 uint32_t *dataAddr = (uint32_t *)buffer;
0100
0101 for (i = 0U; i < size; i++)
0102 {
0103 for (j = 0; j < channelNums; j++)
0104 {
0105 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH != 2U)
0106 *dataAddr = base->DATACH[startChannel + j] >> (dataWidth == 4U ? 0U : 8U);
0107 dataAddr = (uint32_t *)((uint32_t)dataAddr + dataWidth);
0108 #else
0109 *dataAddr = base->DATACH[startChannel + j];
0110 dataAddr = (uint32_t *)((uint32_t)dataAddr + 2U);
0111 #endif
0112 }
0113 }
0114 }
0115
0116 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 2U)
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 void PDM_ReadNonBlocking(PDM_Type *base, uint32_t startChannel, uint32_t channelNums, int16_t *buffer, size_t size)
0127 {
0128 uint32_t i = 0, j = 0U;
0129
0130 for (i = 0U; i < size; i++)
0131 {
0132 for (j = 0; j < channelNums; j++)
0133 {
0134 *buffer++ = (int16_t)base->DATACH[startChannel + j];
0135 }
0136 }
0137 }
0138 #endif
0139
0140 #if !(defined FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV && FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV)
0141 static status_t PDM_ValidateSrcClockRate(uint32_t channelMask,
0142 pdm_df_quality_mode_t qualityMode,
0143 uint8_t osr,
0144 uint32_t regDiv)
0145 {
0146 uint32_t enabledChannel = 0U, i = 0U, factor = 0U, k = 0U;
0147
0148 for (i = 0U; i < (uint32_t)FSL_FEATURE_PDM_CHANNEL_NUM; i++)
0149 {
0150 if (((channelMask >> i) & 0x01U) != 0U)
0151 {
0152 enabledChannel++;
0153 }
0154 }
0155
0156 switch (qualityMode)
0157 {
0158 case kPDM_QualityModeMedium:
0159 factor = FSL_FEATURE_PDM_HIGH_QUALITY_CLKDIV_FACTOR;
0160 k = 2U;
0161 break;
0162
0163 case kPDM_QualityModeHigh:
0164 factor = FSL_FEATURE_PDM_HIGH_QUALITY_CLKDIV_FACTOR;
0165 k = 1U;
0166 break;
0167
0168 case kPDM_QualityModeLow:
0169 factor = FSL_FEATURE_PDM_HIGH_QUALITY_CLKDIV_FACTOR;
0170 k = 4U;
0171 break;
0172
0173 case kPDM_QualityModeVeryLow0:
0174 factor = FSL_FEATURE_PDM_VERY_LOW_QUALITY_CLKDIV_FACTOR;
0175 k = 2U;
0176 break;
0177
0178 case kPDM_QualityModeVeryLow1:
0179 factor = FSL_FEATURE_PDM_VERY_LOW_QUALITY_CLKDIV_FACTOR;
0180 k = 4U;
0181 break;
0182
0183 case kPDM_QualityModeVeryLow2:
0184 factor = FSL_FEATURE_PDM_VERY_LOW_QUALITY_CLKDIV_FACTOR;
0185 k = 8U;
0186 break;
0187
0188 default:
0189 assert(false);
0190 break;
0191 }
0192
0193
0194
0195 if (((regDiv * k) / 2U * 100U) < (((10U + factor * enabledChannel) * 100U / (8U * osr)) * k / 2U))
0196 {
0197 return kStatus_Fail;
0198 }
0199
0200 return kStatus_Success;
0201 }
0202 #endif
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 status_t PDM_SetSampleRateConfig(PDM_Type *base, uint32_t sourceClock_HZ, uint32_t sampleRate_HZ)
0218 {
0219 uint32_t osr = (base->CTRL_2 & PDM_CTRL_2_CICOSR_MASK) >> PDM_CTRL_2_CICOSR_SHIFT;
0220 #if !(defined FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV && FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV)
0221 pdm_df_quality_mode_t qualityMode =
0222 (pdm_df_quality_mode_t)(uint32_t)((base->CTRL_2 & PDM_CTRL_2_QSEL_MASK) >> PDM_CTRL_2_QSEL_SHIFT);
0223 uint32_t enabledChannelMask = base->CTRL_1 & (uint32_t)kPDM_EnableChannelAll;
0224 #endif
0225
0226 uint32_t pdmClockRate = 0U;
0227 uint32_t regDiv = 0U;
0228
0229
0230 osr = 16U - osr;
0231 pdmClockRate = sampleRate_HZ * osr * 8U;
0232 regDiv = sourceClock_HZ / pdmClockRate;
0233
0234 if (regDiv > PDM_CTRL_2_CLKDIV_MASK)
0235 {
0236 return kStatus_Fail;
0237 }
0238
0239 #if !(defined FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV && FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV)
0240 if (PDM_ValidateSrcClockRate(enabledChannelMask, qualityMode, (uint8_t)osr, regDiv) == kStatus_Fail)
0241 {
0242 return kStatus_Fail;
0243 }
0244 #endif
0245
0246 base->CTRL_2 = (base->CTRL_2 & (~PDM_CTRL_2_CLKDIV_MASK)) | PDM_CTRL_2_CLKDIV(regDiv);
0247
0248 return kStatus_Success;
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 status_t PDM_SetSampleRate(
0262 PDM_Type *base, uint32_t enableChannelMask, pdm_df_quality_mode_t qualityMode, uint8_t osr, uint32_t clkDiv)
0263 {
0264 #if !(defined FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV && FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV)
0265 uint8_t realOsr = 16U - (osr & (PDM_CTRL_2_CICOSR_MASK >> PDM_CTRL_2_CICOSR_SHIFT));
0266 #endif
0267 uint32_t regDiv = clkDiv >> 1U;
0268
0269 switch (qualityMode)
0270 {
0271 case kPDM_QualityModeHigh:
0272 regDiv <<= 1U;
0273 break;
0274 case kPDM_QualityModeLow:
0275 case kPDM_QualityModeVeryLow1:
0276 regDiv >>= 1U;
0277 break;
0278 case kPDM_QualityModeVeryLow2:
0279 regDiv >>= 2U;
0280 break;
0281 default:
0282 assert(false);
0283 break;
0284 }
0285
0286 #if !(defined FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV && FSL_FEATURE_PDM_HAS_NO_MINIMUM_CLKDIV)
0287 if (PDM_ValidateSrcClockRate(enableChannelMask, qualityMode, realOsr, regDiv) == kStatus_Fail)
0288 {
0289 return kStatus_Fail;
0290 }
0291 #endif
0292
0293 assert(regDiv <= PDM_CTRL_2_CLKDIV_MASK);
0294 base->CTRL_2 = (base->CTRL_2 & (~PDM_CTRL_2_CLKDIV_MASK)) | PDM_CTRL_2_CLKDIV(regDiv);
0295
0296 return kStatus_Success;
0297 }
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 void PDM_Init(PDM_Type *base, const pdm_config_t *config)
0314 {
0315 assert(config != NULL);
0316 assert(config->fifoWatermark <= PDM_FIFO_CTRL_FIFOWMK_MASK);
0317
0318 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0319
0320 CLOCK_EnableClock(s_pdmClock[PDM_GetInstance(base)]);
0321 #if defined(FSL_PDM_HAS_FILTER_CLOCK_GATE) && FSL_PDM_HAS_FILTER_CLOCK_GATE
0322 CLOCK_EnableClock(s_pdmFilterClock[PDM_GetInstance(base)]);
0323 #endif
0324 #endif
0325
0326
0327 base->CTRL_1 &=
0328 ~(PDM_CTRL_1_MDIS_MASK | PDM_CTRL_1_PDMIEN_MASK | PDM_CTRL_1_ERREN_MASK | (uint32_t)kPDM_EnableChannelAll);
0329
0330
0331 while ((base->STAT & PDM_STAT_BSY_FIL_MASK) != 0U)
0332 {
0333 }
0334
0335
0336 base->CTRL_1 |= PDM_CTRL_1_SRES_MASK;
0337
0338
0339 base->CTRL_1 = (base->CTRL_1 & (~PDM_CTRL_1_DOZEN_MASK)) | PDM_CTRL_1_DOZEN(config->enableDoze);
0340
0341 base->CTRL_2 = (base->CTRL_2 & (~(PDM_CTRL_2_CICOSR_MASK | PDM_CTRL_2_QSEL_MASK))) |
0342 PDM_CTRL_2_CICOSR(config->cicOverSampleRate) | PDM_CTRL_2_QSEL(config->qualityMode);
0343
0344
0345 base->FIFO_CTRL = PDM_FIFO_CTRL_FIFOWMK(config->fifoWatermark);
0346 }
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 void PDM_Deinit(PDM_Type *base)
0357 {
0358
0359 PDM_Enable(base, false);
0360
0361 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0362 CLOCK_DisableClock(s_pdmClock[PDM_GetInstance(base)]);
0363 #if defined(FSL_PDM_HAS_FILTER_CLOCK_GATE) && FSL_PDM_HAS_FILTER_CLOCK_GATE
0364 CLOCK_DisableClock(s_pdmFilterClock[PDM_GetInstance(base)]);
0365 #endif
0366 #endif
0367 }
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 void PDM_EnableInterrupts(PDM_Type *base, uint32_t mask)
0379 {
0380 if ((mask & (uint32_t)kPDM_FIFOInterruptEnable) != 0U)
0381 {
0382 base->CTRL_1 = (base->CTRL_1 & (~PDM_CTRL_1_DISEL_MASK)) | (uint32_t)kPDM_FIFOInterruptEnable;
0383 }
0384 if ((mask & (uint32_t)kPDM_ErrorInterruptEnable) != 0U)
0385 {
0386 base->CTRL_1 = (base->CTRL_1 & (~PDM_CTRL_1_ERREN_MASK)) | (uint32_t)kPDM_ErrorInterruptEnable;
0387 }
0388 }
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398 void PDM_SetChannelConfig(PDM_Type *base, uint32_t channel, const pdm_channel_config_t *config)
0399 {
0400 assert(config != NULL);
0401 assert(channel <= (uint32_t)FSL_FEATURE_PDM_CHANNEL_NUM);
0402
0403 uint32_t dcCtrl = 0U;
0404
0405 #if (defined(FSL_FEATURE_PDM_HAS_DC_OUT_CTRL) && (FSL_FEATURE_PDM_HAS_DC_OUT_CTRL))
0406 dcCtrl = base->DC_OUT_CTRL;
0407
0408 dcCtrl &= ~((uint32_t)PDM_DC_OUT_CTRL_DCCONFIG0_MASK << (channel << 1U));
0409 dcCtrl |= (uint32_t)config->outputCutOffFreq << (channel << 1U);
0410 base->DC_OUT_CTRL = dcCtrl;
0411 #endif
0412
0413 #if !(defined(FSL_FEATURE_PDM_DC_CTRL_VALUE_FIXED) && (FSL_FEATURE_PDM_DC_CTRL_VALUE_FIXED))
0414 dcCtrl = base->DC_CTRL;
0415
0416 dcCtrl &= ~((uint32_t)PDM_DC_CTRL_DCCONFIG0_MASK << (channel << 1U));
0417 dcCtrl |= (uint32_t)config->cutOffFreq << (channel << 1U);
0418 base->DC_CTRL = dcCtrl;
0419 #endif
0420
0421 PDM_SetChannelGain(base, channel, config->gain);
0422
0423
0424 base->CTRL_1 |= 1UL << channel;
0425 }
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435 void PDM_SetChannelGain(PDM_Type *base, uint32_t channel, pdm_df_output_gain_t gain)
0436 {
0437 assert(channel <= (uint32_t)FSL_FEATURE_PDM_CHANNEL_NUM);
0438
0439 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
0440 uint32_t outCtrl = base->RANGE_CTRL;
0441 #else
0442 uint32_t outCtrl = base->OUT_CTRL;
0443 #endif
0444
0445 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
0446 outCtrl &= ~((uint32_t)PDM_RANGE_CTRL_RANGEADJ0_MASK << (channel << 2U));
0447 #else
0448 outCtrl &= ~((uint32_t)PDM_OUT_CTRL_OUTGAIN0_MASK << (channel << 2U));
0449 #endif
0450
0451 outCtrl |= (uint32_t)gain << (channel << 2U);
0452
0453 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
0454 base->RANGE_CTRL = outCtrl;
0455 #else
0456 base->OUT_CTRL = outCtrl;
0457 #endif
0458 }
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 status_t PDM_TransferSetChannelConfig(
0470 PDM_Type *base, pdm_handle_t *handle, uint32_t channel, const pdm_channel_config_t *config, uint32_t format)
0471 {
0472 assert(handle != NULL);
0473
0474 PDM_SetChannelConfig(base, channel, config);
0475
0476 handle->format = format;
0477
0478 if (handle->channelNums == 0U)
0479 {
0480 handle->startChannel = (uint8_t)channel;
0481 }
0482
0483 handle->channelNums++;
0484
0485 if (handle->channelNums > (uint8_t)FSL_FEATURE_PDM_CHANNEL_NUM)
0486 {
0487 return kStatus_PDM_ChannelConfig_Failed;
0488 }
0489
0490 return kStatus_Success;
0491 }
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 void PDM_TransferCreateHandle(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_callback_t callback, void *userData)
0505 {
0506 assert(handle != NULL);
0507
0508
0509 (void)memset(handle, 0, sizeof(*handle));
0510
0511 s_pdmHandle[PDM_GetInstance(base)] = handle;
0512
0513 handle->callback = callback;
0514 handle->userData = userData;
0515 handle->watermark = (uint8_t)(base->FIFO_CTRL & PDM_FIFO_CTRL_FIFOWMK_MASK);
0516
0517
0518 s_pdmIsr = PDM_TransferHandleIRQ;
0519
0520
0521 (void)EnableIRQ(PDM_EVENT_IRQn);
0522 #if !(defined FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ && FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ)
0523
0524 (void)EnableIRQ(PDM_ERROR_IRQn);
0525 #endif
0526 }
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542 status_t PDM_TransferReceiveNonBlocking(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_t *xfer)
0543 {
0544 assert(handle != NULL);
0545
0546
0547 if (handle->pdmQueue[handle->queueUser].data != NULL)
0548 {
0549 return kStatus_PDM_QueueFull;
0550 }
0551
0552
0553 handle->transferSize[handle->queueUser] = xfer->dataSize;
0554 handle->pdmQueue[handle->queueUser].data = xfer->data;
0555 handle->pdmQueue[handle->queueUser].dataSize = xfer->dataSize;
0556 handle->queueUser = (handle->queueUser + 1U) % PDM_XFER_QUEUE_SIZE;
0557
0558
0559 handle->state = kStatus_PDM_Busy;
0560
0561
0562 PDM_EnableInterrupts(base, (uint32_t)kPDM_FIFOInterruptEnable);
0563
0564 PDM_Enable(base, true);
0565
0566 return kStatus_Success;
0567 }
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578 void PDM_TransferAbortReceive(PDM_Type *base, pdm_handle_t *handle)
0579 {
0580 assert(handle != NULL);
0581
0582
0583 PDM_DisableInterrupts(base, (uint32_t)kPDM_FIFOInterruptEnable | (uint32_t)kPDM_ErrorInterruptEnable);
0584 PDM_Enable(base, false);
0585 handle->state = kStatus_PDM_Idle;
0586
0587 (void)memset(handle->pdmQueue, 0, sizeof(pdm_transfer_t) * PDM_XFER_QUEUE_SIZE);
0588 handle->queueDriver = 0;
0589 handle->queueUser = 0;
0590 }
0591
0592
0593
0594
0595
0596
0597
0598 void PDM_TransferHandleIRQ(PDM_Type *base, pdm_handle_t *handle)
0599 {
0600 assert(handle != NULL);
0601
0602 #if (defined FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ && FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ)
0603 uint32_t status = 0U;
0604
0605 #if (defined(FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ) && (FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ == 1U))
0606 if (PDM_GetStatus(base) & PDM_STAT_LOWFREQF_MASK)
0607 {
0608 PDM_ClearStatus(base, PDM_STAT_LOWFREQF_MASK);
0609 if (handle->callback != NULL)
0610 {
0611 (handle->callback)(base, handle, kStatus_PDM_CLK_LOW, handle->userData);
0612 }
0613 }
0614 #endif
0615 status = PDM_GetFifoStatus(base);
0616 if (status != 0U)
0617 {
0618 PDM_ClearFIFOStatus(base, status);
0619 if (handle->callback != NULL)
0620 {
0621 (handle->callback)(base, handle, kStatus_PDM_FIFO_ERROR, handle->userData);
0622 }
0623 }
0624
0625 #if !(defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL)
0626 status = PDM_GetOutputStatus(base);
0627 if (status != 0U)
0628 {
0629 PDM_ClearOutputStatus(base, status);
0630 if (handle->callback != NULL)
0631 {
0632 (handle->callback)(base, handle, kStatus_PDM_Output_ERROR, handle->userData);
0633 }
0634 }
0635 #endif
0636 #endif
0637
0638
0639 if (((base->STAT & 0xFFU) != 0U) && (handle->channelNums != 0U) &&
0640 ((base->CTRL_1 & PDM_CTRL_1_DISEL_MASK) == (0x2UL << PDM_CTRL_1_DISEL_SHIFT)))
0641 {
0642 PDM_ClearStatus(base, 0xFFU);
0643
0644 uint8_t size = (uint8_t)MIN((handle->pdmQueue[handle->queueDriver].dataSize),
0645 ((uint32_t)handle->watermark * handle->channelNums * handle->format));
0646
0647 PDM_ReadFifo(base, handle->startChannel, handle->channelNums,
0648 (uint8_t *)(uint32_t)handle->pdmQueue[handle->queueDriver].data,
0649 ((size_t)size / handle->channelNums / handle->format), handle->format);
0650
0651
0652 handle->pdmQueue[handle->queueDriver].dataSize -= size;
0653 handle->pdmQueue[handle->queueDriver].data = &(handle->pdmQueue[handle->queueDriver].data[size]);
0654 }
0655
0656
0657 if (handle->pdmQueue[handle->queueDriver].dataSize == 0U)
0658 {
0659 handle->pdmQueue[handle->queueDriver].data = NULL;
0660 handle->queueDriver = (handle->queueDriver + 1U) % PDM_XFER_QUEUE_SIZE;
0661 if (handle->callback != NULL)
0662 {
0663 (handle->callback)(base, handle, kStatus_PDM_Idle, handle->userData);
0664 }
0665 }
0666
0667
0668 if (handle->pdmQueue[handle->queueDriver].data == NULL)
0669 {
0670 PDM_TransferAbortReceive(base, handle);
0671 }
0672 }
0673
0674 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705 void PDM_SetHwvadInEnvelopeBasedMode(PDM_Type *base,
0706 const pdm_hwvad_config_t *hwvadConfig,
0707 const pdm_hwvad_noise_filter_t *noiseConfig,
0708 const pdm_hwvad_zero_cross_detector_t *zcdConfig,
0709 uint32_t signalGain)
0710 {
0711 assert(hwvadConfig != NULL);
0712 assert(noiseConfig != NULL);
0713
0714 uint32_t i = 0U;
0715
0716 PDM_SetHwvadConfig(base, hwvadConfig);
0717 PDM_SetHwvadSignalFilterConfig(base, true, signalGain);
0718 PDM_SetHwvadNoiseFilterConfig(base, noiseConfig);
0719 PDM_EnableHwvad(base, true);
0720
0721 if (NULL != zcdConfig)
0722 {
0723 PDM_SetHwvadZeroCrossDetectorConfig(base, zcdConfig);
0724 }
0725
0726 PDM_Enable(base, true);
0727
0728 while (PDM_GetHwvadInitialFlag(base) != 0U)
0729 {
0730 }
0731
0732 for (i = 0; i < 3U; i++)
0733 {
0734
0735 PDM_SetHwvadInternalFilterStatus(base, kPDM_HwvadInternalFilterInitial);
0736 }
0737
0738 PDM_SetHwvadInternalFilterStatus(base, kPDM_HwvadInternalFilterNormalOperation);
0739 }
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771 void PDM_SetHwvadInEnergyBasedMode(PDM_Type *base,
0772 const pdm_hwvad_config_t *hwvadConfig,
0773 const pdm_hwvad_noise_filter_t *noiseConfig,
0774 const pdm_hwvad_zero_cross_detector_t *zcdConfig,
0775 uint32_t signalGain)
0776 {
0777 assert(hwvadConfig != NULL);
0778 assert(noiseConfig != NULL);
0779
0780 PDM_SetHwvadConfig(base, hwvadConfig);
0781
0782 base->VAD0_SCONFIG = PDM_VAD0_SCONFIG_VADSGAIN(signalGain);
0783 PDM_SetHwvadNoiseFilterConfig(base, noiseConfig);
0784 PDM_EnableHwvad(base, true);
0785
0786 if (NULL != zcdConfig)
0787 {
0788 PDM_SetHwvadZeroCrossDetectorConfig(base, zcdConfig);
0789 }
0790
0791 PDM_Enable(base, true);
0792 }
0793
0794
0795
0796
0797
0798
0799
0800 void PDM_SetHwvadConfig(PDM_Type *base, const pdm_hwvad_config_t *config)
0801 {
0802 assert(config != NULL);
0803
0804 uint32_t ctrl1 = base->VAD0_CTRL_1;
0805
0806
0807 ctrl1 &= ~(PDM_VAD0_CTRL_1_VADCHSEL_MASK | PDM_VAD0_CTRL_1_VADCICOSR_MASK | PDM_VAD0_CTRL_1_VADINITT_MASK);
0808 ctrl1 |= (PDM_VAD0_CTRL_1_VADCHSEL(config->channel) | PDM_VAD0_CTRL_1_VADCICOSR(config->cicOverSampleRate) |
0809 PDM_VAD0_CTRL_1_VADINITT(config->initializeTime));
0810 base->VAD0_CTRL_1 = ctrl1;
0811
0812
0813 base->VAD0_CTRL_2 =
0814 (PDM_VAD0_CTRL_2_VADFRENDIS((config->enableFrameEnergy == true) ? 0U : 1U) |
0815 PDM_VAD0_CTRL_2_VADPREFEN(config->enablePreFilter) | PDM_VAD0_CTRL_2_VADFRAMET(config->frameTime) |
0816 PDM_VAD0_CTRL_2_VADINPGAIN(config->inputGain) | PDM_VAD0_CTRL_2_VADHPF(config->cutOffFreq));
0817 }
0818
0819
0820
0821
0822
0823
0824
0825
0826 void PDM_SetHwvadSignalFilterConfig(PDM_Type *base, bool enableMaxBlock, uint32_t signalGain)
0827 {
0828 uint32_t signalConfig = base->VAD0_SCONFIG;
0829
0830 signalConfig &= ~(PDM_VAD0_SCONFIG_VADSMAXEN_MASK | PDM_VAD0_SCONFIG_VADSGAIN_MASK);
0831 signalConfig |= (PDM_VAD0_SCONFIG_VADSMAXEN(enableMaxBlock) | PDM_VAD0_SCONFIG_VADSGAIN(signalGain)) |
0832 PDM_VAD0_SCONFIG_VADSFILEN_MASK;
0833 base->VAD0_SCONFIG = signalConfig;
0834 }
0835
0836
0837
0838
0839
0840
0841
0842 void PDM_SetHwvadNoiseFilterConfig(PDM_Type *base, const pdm_hwvad_noise_filter_t *config)
0843 {
0844 assert(config != NULL);
0845
0846 base->VAD0_NCONFIG =
0847 (PDM_VAD0_NCONFIG_VADNFILAUTO(config->enableAutoNoiseFilter) |
0848 PDM_VAD0_NCONFIG_VADNOREN(config->enableNoiseDetectOR) | PDM_VAD0_NCONFIG_VADNMINEN(config->enableNoiseMin) |
0849 PDM_VAD0_NCONFIG_VADNDECEN(config->enableNoiseDecimation) |
0850 PDM_VAD0_NCONFIG_VADNFILADJ(config->noiseFilterAdjustment) | PDM_VAD0_NCONFIG_VADNGAIN(config->noiseGain));
0851 }
0852
0853
0854
0855
0856
0857
0858
0859 void PDM_SetHwvadZeroCrossDetectorConfig(PDM_Type *base, const pdm_hwvad_zero_cross_detector_t *config)
0860 {
0861 assert(config != NULL);
0862
0863 uint32_t zcd = (base->VAD0_ZCD & (~(PDM_VAD0_ZCD_VADZCDTH_MASK | PDM_VAD0_ZCD_VADZCDADJ_MASK |
0864 PDM_VAD0_ZCD_VADZCDAUTO_MASK | PDM_VAD0_ZCD_VADZCDAND_MASK)));
0865
0866 zcd |= (PDM_VAD0_ZCD_VADZCDTH(config->threshold) | PDM_VAD0_ZCD_VADZCDADJ(config->adjustmentThreshold) |
0867 PDM_VAD0_ZCD_VADZCDAUTO(config->enableAutoThreshold) | PDM_VAD0_ZCD_VADZCDAND(config->zcdAnd)) |
0868 PDM_VAD0_ZCD_VADZCDEN_MASK;
0869
0870 base->VAD0_ZCD = zcd;
0871 }
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884 void PDM_EnableHwvadInterruptCallback(PDM_Type *base, pdm_hwvad_callback_t vadCallback, void *userData, bool enable)
0885 {
0886 uint32_t instance = PDM_GetInstance(base);
0887
0888 if (enable)
0889 {
0890 PDM_EnableHwvadInterrupts(base, (uint32_t)kPDM_HwvadErrorInterruptEnable | (uint32_t)kPDM_HwvadInterruptEnable);
0891 NVIC_ClearPendingIRQ(PDM_HWVAD_EVENT_IRQn);
0892 (void)EnableIRQ(PDM_HWVAD_EVENT_IRQn);
0893 #if !(defined FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ && FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ)
0894 NVIC_ClearPendingIRQ(PDM_HWVAD_ERROR_IRQn);
0895 (void)EnableIRQ(PDM_HWVAD_ERROR_IRQn);
0896 #endif
0897 s_pdm_hwvad_notification[instance].callback = vadCallback;
0898 s_pdm_hwvad_notification[instance].userData = userData;
0899 }
0900 else
0901 {
0902 PDM_DisableHwvadInterrupts(base,
0903 (uint32_t)kPDM_HwvadErrorInterruptEnable | (uint32_t)kPDM_HwvadInterruptEnable);
0904 (void)DisableIRQ(PDM_HWVAD_EVENT_IRQn);
0905 #if !(defined FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ && FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ)
0906 (void)DisableIRQ(PDM_HWVAD_ERROR_IRQn);
0907 NVIC_ClearPendingIRQ(PDM_HWVAD_ERROR_IRQn);
0908 #endif
0909 s_pdm_hwvad_notification[instance].callback = NULL;
0910 s_pdm_hwvad_notification[instance].userData = NULL;
0911 NVIC_ClearPendingIRQ(PDM_HWVAD_EVENT_IRQn);
0912 }
0913 }
0914
0915 #if (defined PDM)
0916 void PDM_HWVAD_EVENT_DriverIRQHandler(void);
0917 void PDM_HWVAD_EVENT_DriverIRQHandler(void)
0918 {
0919 if ((PDM_GetHwvadInterruptStatusFlags(PDM) & (uint32_t)kPDM_HwvadStatusVoiceDetectFlag) != 0U)
0920 {
0921 PDM_ClearHwvadInterruptStatusFlags(PDM, (uint32_t)kPDM_HwvadStatusVoiceDetectFlag);
0922 if (s_pdm_hwvad_notification[0].callback != NULL)
0923 {
0924 s_pdm_hwvad_notification[0].callback(kStatus_PDM_HWVAD_VoiceDetected, s_pdm_hwvad_notification[0].userData);
0925 }
0926 }
0927 #if (defined FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ && FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ)
0928 else
0929 {
0930 PDM_ClearHwvadInterruptStatusFlags(PDM, (uint32_t)kPDM_HwvadStatusInputSaturation);
0931 if (s_pdm_hwvad_notification[0].callback != NULL)
0932 {
0933 s_pdm_hwvad_notification[0].callback(kStatus_PDM_HWVAD_Error, s_pdm_hwvad_notification[0].userData);
0934 }
0935 }
0936 #endif
0937 SDK_ISR_EXIT_BARRIER;
0938 }
0939
0940 #if !(defined FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ && FSL_FEATURE_PDM_HAS_NO_INDEPENDENT_ERROR_IRQ)
0941 void PDM_HWVAD_ERROR_DriverIRQHandler(void);
0942 void PDM_HWVAD_ERROR_DriverIRQHandler(void)
0943 {
0944 PDM_ClearHwvadInterruptStatusFlags(PDM, (uint32_t)kPDM_HwvadStatusInputSaturation);
0945 if (s_pdm_hwvad_notification[0].callback != NULL)
0946 {
0947 s_pdm_hwvad_notification[0].callback(kStatus_PDM_HWVAD_Error, s_pdm_hwvad_notification[0].userData);
0948 }
0949 SDK_ISR_EXIT_BARRIER;
0950 }
0951 #endif
0952 #endif
0953 #endif
0954
0955 #if defined(PDM)
0956 void PDM_EVENT_DriverIRQHandler(void);
0957 void PDM_EVENT_DriverIRQHandler(void)
0958 {
0959 assert(s_pdmHandle[0] != NULL);
0960 s_pdmIsr(PDM, s_pdmHandle[0]);
0961 SDK_ISR_EXIT_BARRIER;
0962 }
0963 #endif