1 /*
2 * Copyright (c) 2018, Freescale Semiconductor, Inc.
3 * Copyright 2019-2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #ifndef _FSL_PDM_H_
10 #define _FSL_PDM_H_
11
12 #include "fsl_common.h"
13
14 /*!
15 * @addtogroup pdm_driver PDM Driver
16 * @{
17 */
18
19 /*******************************************************************************
20 * Definitions
21 ******************************************************************************/
22
23 /*! @name Driver version */
24 /*@{*/
25 #define FSL_PDM_DRIVER_VERSION (MAKE_VERSION(2, 8, 0)) /*!< Version 2.8.0 */
26 /*@}*/
27
28 /*! @brief PDM XFER QUEUE SIZE */
29 #define PDM_XFER_QUEUE_SIZE (4U)
30
31 /*! @brief PDM return status*/
32 enum
33 {
34 kStatus_PDM_Busy = MAKE_STATUS(kStatusGroup_PDM, 0), /*!< PDM is busy. */
35 #if (defined(FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ) && (FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ == 1U))
36 kStatus_PDM_CLK_LOW = MAKE_STATUS(kStatusGroup_PDM, 1), /*!< PDM clock frequency low */
37 #endif
38 kStatus_PDM_FIFO_ERROR = MAKE_STATUS(kStatusGroup_PDM, 2), /*!< PDM FIFO underrun or overflow */
39 kStatus_PDM_QueueFull = MAKE_STATUS(kStatusGroup_PDM, 3), /*!< PDM FIFO underrun or overflow */
40 kStatus_PDM_Idle = MAKE_STATUS(kStatusGroup_PDM, 4), /*!< PDM is idle */
41 kStatus_PDM_Output_ERROR = MAKE_STATUS(kStatusGroup_PDM, 5), /*!< PDM is output error */
42 kStatus_PDM_ChannelConfig_Failed = MAKE_STATUS(kStatusGroup_PDM, 6), /*!< PDM channel config failed */
43 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
44 kStatus_PDM_HWVAD_VoiceDetected = MAKE_STATUS(kStatusGroup_PDM, 7), /*!< PDM hwvad voice detected */
45 kStatus_PDM_HWVAD_Error = MAKE_STATUS(kStatusGroup_PDM, 8), /*!< PDM hwvad error */
46 #endif
47 };
48
49 /*! @brief The PDM interrupt enable flag */
50 enum _pdm_interrupt_enable
51 {
52 kPDM_ErrorInterruptEnable = PDM_CTRL_1_ERREN_MASK, /*!< PDM channel error interrupt enable. */
53 kPDM_FIFOInterruptEnable = PDM_CTRL_1_DISEL(2U), /*!< PDM channel FIFO interrupt */
54 };
55
56 /*! @brief The PDM status */
57 enum _pdm_internal_status
58 {
59 kPDM_StatusDfBusyFlag = (int)PDM_STAT_BSY_FIL_MASK, /*!< Decimation filter is busy processing data */
60 #if !(defined(FSL_FEATURE_PDM_HAS_NO_FIR_RDY) && FSL_FEATURE_PDM_HAS_NO_FIR_RDY)
61 kPDM_StatusFIRFilterReady = PDM_STAT_FIR_RDY_MASK, /*!< FIR filter data is ready */
62 #endif
63 #if (defined(FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ) && (FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ == 1U))
64 kPDM_StatusFrequencyLow = PDM_STAT_LOWFREQF_MASK, /*!< Mic app clock frequency not high enough */
65 #endif
66 kPDM_StatusCh0FifoDataAvaliable = PDM_STAT_CH0F_MASK, /*!< channel 0 fifo data reached watermark level */
67 kPDM_StatusCh1FifoDataAvaliable = PDM_STAT_CH1F_MASK, /*!< channel 1 fifo data reached watermark level */
68 kPDM_StatusCh2FifoDataAvaliable = PDM_STAT_CH2F_MASK, /*!< channel 2 fifo data reached watermark level */
69 kPDM_StatusCh3FifoDataAvaliable = PDM_STAT_CH3F_MASK, /*!< channel 3 fifo data reached watermark level */
70 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
71 kPDM_StatusCh4FifoDataAvaliable = PDM_STAT_CH4F_MASK, /*!< channel 4 fifo data reached watermark level */
72 kPDM_StatusCh5FifoDataAvaliable = PDM_STAT_CH5F_MASK, /*!< channel 5 fifo data reached watermark level */
73 kPDM_StatusCh6FifoDataAvaliable = PDM_STAT_CH6F_MASK, /*!< channel 6 fifo data reached watermark level */
74 kPDM_StatusCh7FifoDataAvaliable = PDM_STAT_CH7F_MASK, /*!< channel 7 fifo data reached watermark level */
75 #endif
76 };
77
78 /*! @brief PDM channel enable mask */
79 enum _pdm_channel_enable_mask
80 {
81 kPDM_EnableChannel0 = PDM_STAT_CH0F_MASK, /*!< channgel 0 enable mask */
82 kPDM_EnableChannel1 = PDM_STAT_CH1F_MASK, /*!< channgel 1 enable mask */
83 kPDM_EnableChannel2 = PDM_STAT_CH2F_MASK, /*!< channgel 2 enable mask */
84 kPDM_EnableChannel3 = PDM_STAT_CH3F_MASK, /*!< channgel 3 enable mask */
85 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
86 kPDM_EnableChannel4 = PDM_STAT_CH4F_MASK, /*!< channgel 4 enable mask */
87 kPDM_EnableChannel5 = PDM_STAT_CH5F_MASK, /*!< channgel 5 enable mask */
88 kPDM_EnableChannel6 = PDM_STAT_CH6F_MASK, /*!< channgel 6 enable mask */
89 kPDM_EnableChannel7 = PDM_STAT_CH7F_MASK, /*!< channgel 7 enable mask */
90
91 kPDM_EnableChannelAll = kPDM_EnableChannel0 | kPDM_EnableChannel1 | kPDM_EnableChannel2 | kPDM_EnableChannel3 |
92 kPDM_EnableChannel4 | kPDM_EnableChannel5 | kPDM_EnableChannel6 | kPDM_EnableChannel7,
93 #else
94 kPDM_EnableChannelAll = kPDM_EnableChannel0 | kPDM_EnableChannel1 | kPDM_EnableChannel2 | kPDM_EnableChannel3,
95 #endif
96 };
97
98 /*! @brief The PDM fifo status */
99 enum _pdm_fifo_status
100 {
101 kPDM_FifoStatusUnderflowCh0 = PDM_FIFO_STAT_FIFOUND0_MASK, /*!< channel0 fifo status underflow */
102 kPDM_FifoStatusUnderflowCh1 = PDM_FIFO_STAT_FIFOUND1_MASK, /*!< channel1 fifo status underflow */
103 kPDM_FifoStatusUnderflowCh2 = PDM_FIFO_STAT_FIFOUND2_MASK, /*!< channel2 fifo status underflow */
104 kPDM_FifoStatusUnderflowCh3 = PDM_FIFO_STAT_FIFOUND3_MASK, /*!< channel3 fifo status underflow */
105 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
106 kPDM_FifoStatusUnderflowCh4 = PDM_FIFO_STAT_FIFOUND4_MASK, /*!< channel4 fifo status underflow */
107 kPDM_FifoStatusUnderflowCh5 = PDM_FIFO_STAT_FIFOUND5_MASK, /*!< channel5 fifo status underflow */
108 kPDM_FifoStatusUnderflowCh6 = PDM_FIFO_STAT_FIFOUND6_MASK, /*!< channel6 fifo status underflow */
109 kPDM_FifoStatusUnderflowCh7 = PDM_FIFO_STAT_FIFOUND6_MASK, /*!< channel7 fifo status underflow */
110 #endif
111
112 kPDM_FifoStatusOverflowCh0 = PDM_FIFO_STAT_FIFOOVF0_MASK, /*!< channel0 fifo status overflow */
113 kPDM_FifoStatusOverflowCh1 = PDM_FIFO_STAT_FIFOOVF1_MASK, /*!< channel1 fifo status overflow */
114 kPDM_FifoStatusOverflowCh2 = PDM_FIFO_STAT_FIFOOVF2_MASK, /*!< channel2 fifo status overflow */
115 kPDM_FifoStatusOverflowCh3 = PDM_FIFO_STAT_FIFOOVF3_MASK, /*!< channel3 fifo status overflow */
116 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
117 kPDM_FifoStatusOverflowCh4 = PDM_FIFO_STAT_FIFOOVF4_MASK, /*!< channel4 fifo status overflow */
118 kPDM_FifoStatusOverflowCh5 = PDM_FIFO_STAT_FIFOOVF5_MASK, /*!< channel5 fifo status overflow */
119 kPDM_FifoStatusOverflowCh6 = PDM_FIFO_STAT_FIFOOVF6_MASK, /*!< channel6 fifo status overflow */
120 kPDM_FifoStatusOverflowCh7 = PDM_FIFO_STAT_FIFOOVF7_MASK, /*!< channel7 fifo status overflow */
121 #endif
122 };
123
124 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
125 /*! @brief The PDM output status */
126 enum _pdm_range_status
127 {
128 kPDM_RangeStatusUnderFlowCh0 = PDM_RANGE_STAT_RANGEUNF0_MASK, /*!< channel0 range status underflow */
129 kPDM_RangeStatusUnderFlowCh1 = PDM_RANGE_STAT_RANGEUNF1_MASK, /*!< channel1 range status underflow */
130 kPDM_RangeStatusUnderFlowCh2 = PDM_RANGE_STAT_RANGEUNF2_MASK, /*!< channel2 range status underflow */
131 kPDM_RangeStatusUnderFlowCh3 = PDM_RANGE_STAT_RANGEUNF3_MASK, /*!< channel3 range status underflow */
132 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
133 kPDM_RangeStatusUnderFlowCh4 = PDM_RANGE_STAT_RANGEUNF4_MASK, /*!< channel4 range status underflow */
134 kPDM_RangeStatusUnderFlowCh5 = PDM_RANGE_STAT_RANGEUNF5_MASK, /*!< channel5 range status underflow */
135 kPDM_RangeStatusUnderFlowCh6 = PDM_RANGE_STAT_RANGEUNF6_MASK, /*!< channel6 range status underflow */
136 kPDM_RangeStatusUnderFlowCh7 = PDM_RANGE_STAT_RANGEUNF7_MASK, /*!< channel7 range status underflow */
137 #endif
138 kPDM_RangeStatusOverFlowCh0 = PDM_RANGE_STAT_RANGEOVF0_MASK, /*!< channel0 range status overflow */
139 kPDM_RangeStatusOverFlowCh1 = PDM_RANGE_STAT_RANGEOVF1_MASK, /*!< channel1 range status overflow */
140 kPDM_RangeStatusOverFlowCh2 = PDM_RANGE_STAT_RANGEOVF2_MASK, /*!< channel2 range status overflow */
141 kPDM_RangeStatusOverFlowCh3 = PDM_RANGE_STAT_RANGEOVF3_MASK, /*!< channel3 range status overflow */
142 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
143 kPDM_RangeStatusOverFlowCh4 = PDM_RANGE_STAT_RANGEOVF4_MASK, /*!< channel4 range status overflow */
144 kPDM_RangeStatusOverFlowCh5 = PDM_RANGE_STAT_RANGEOVF5_MASK, /*!< channel5 range status overflow */
145 kPDM_RangeStatusOverFlowCh6 = PDM_RANGE_STAT_RANGEOVF6_MASK, /*!< channel6 range status overflow */
146 kPDM_RangeStatusOverFlowCh7 = PDM_RANGE_STAT_RANGEOVF7_MASK, /*!< channel7 range status overflow */
147 #endif
148 };
149 #else
150 /*! @brief The PDM output status */
151 enum _pdm_output_status
152 {
153 kPDM_OutputStatusUnderFlowCh0 = PDM_OUT_STAT_OUTUNF0_MASK, /*!< channel0 output status underflow */
154 kPDM_OutputStatusUnderFlowCh1 = PDM_OUT_STAT_OUTUNF1_MASK, /*!< channel1 output status underflow */
155 kPDM_OutputStatusUnderFlowCh2 = PDM_OUT_STAT_OUTUNF2_MASK, /*!< channel2 output status underflow */
156 kPDM_OutputStatusUnderFlowCh3 = PDM_OUT_STAT_OUTUNF3_MASK, /*!< channel3 output status underflow */
157 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
158 kPDM_OutputStatusUnderFlowCh4 = PDM_OUT_STAT_OUTUNF4_MASK, /*!< channel4 output status underflow */
159 kPDM_OutputStatusUnderFlowCh5 = PDM_OUT_STAT_OUTUNF5_MASK, /*!< channel5 output status underflow */
160 kPDM_OutputStatusUnderFlowCh6 = PDM_OUT_STAT_OUTUNF6_MASK, /*!< channel6 output status underflow */
161 kPDM_OutputStatusUnderFlowCh7 = PDM_OUT_STAT_OUTUNF7_MASK, /*!< channel7 output status underflow */
162 #endif
163 kPDM_OutputStatusOverFlowCh0 = PDM_OUT_STAT_OUTOVF0_MASK, /*!< channel0 output status overflow */
164 kPDM_OutputStatusOverFlowCh1 = PDM_OUT_STAT_OUTOVF1_MASK, /*!< channel1 output status overflow */
165 kPDM_OutputStatusOverFlowCh2 = PDM_OUT_STAT_OUTOVF2_MASK, /*!< channel2 output status overflow */
166 kPDM_OutputStatusOverFlowCh3 = PDM_OUT_STAT_OUTOVF3_MASK, /*!< channel3 output status overflow */
167 #if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
168 kPDM_OutputStatusOverFlowCh4 = PDM_OUT_STAT_OUTOVF4_MASK, /*!< channel4 output status overflow */
169 kPDM_OutputStatusOverFlowCh5 = PDM_OUT_STAT_OUTOVF5_MASK, /*!< channel5 output status overflow */
170 kPDM_OutputStatusOverFlowCh6 = PDM_OUT_STAT_OUTOVF6_MASK, /*!< channel6 output status overflow */
171 kPDM_OutputStatusOverFlowCh7 = PDM_OUT_STAT_OUTOVF7_MASK, /*!< channel7 output status overflow */
172 #endif
173 };
174 #endif
175
176 #if (defined(FSL_FEATURE_PDM_HAS_DC_OUT_CTRL) && (FSL_FEATURE_PDM_HAS_DC_OUT_CTRL))
177 /*! @brief PDM DC remover configurations */
178 typedef enum _pdm_dc_remover
179 {
180 kPDM_DcRemoverCutOff20Hz = 0U, /*!< DC remover cut off 20HZ */
181 kPDM_DcRemoverCutOff13Hz = 1U, /*!< DC remover cut off 13.3HZ */
182 kPDM_DcRemoverCutOff40Hz = 2U, /*!< DC remover cut off 40HZ */
183 kPDM_DcRemoverBypass = 3U, /*!< DC remover bypass */
184 } pdm_dc_remover_t;
185 #else
186 /*! @brief PDM DC remover configurations */
187 typedef enum _pdm_dc_remover
188 {
189 kPDM_DcRemoverCutOff21Hz = 0U, /*!< DC remover cut off 21HZ */
190 kPDM_DcRemoverCutOff83Hz = 1U, /*!< DC remover cut off 83HZ */
191 kPDM_DcRemoverCutOff152Hz = 2U, /*!< DC remover cut off 152HZ */
192 kPDM_DcRemoverBypass = 3U, /*!< DC remover bypass */
193 } pdm_dc_remover_t;
194 #endif
195
196 /*! @brief PDM decimation filter quality mode */
197 typedef enum _pdm_df_quality_mode
198 {
199 kPDM_QualityModeMedium = 0U, /*!< quality mode memdium */
200 kPDM_QualityModeHigh = 1U, /*!< quality mode high */
201 kPDM_QualityModeLow = 7U, /*!< quality mode low */
202 kPDM_QualityModeVeryLow0 = 6U, /*!< quality mode very low0 */
203 kPDM_QualityModeVeryLow1 = 5U, /*!< quality mode very low1 */
204 kPDM_QualityModeVeryLow2 = 4U, /*!< quality mode very low2 */
205 } pdm_df_quality_mode_t;
206
207 /*! @brief PDM quality mode K factor */
208 enum _pdm_qulaity_mode_k_factor
209 {
210 kPDM_QualityModeHighKFactor = 1U, /*!< high quality mode K factor = 1 / 2 */
211 kPDM_QualityModeMediumKFactor = 2U, /*!< medium/very low0 quality mode K factor = 2 / 2 */
212 kPDM_QualityModeLowKFactor = 4U, /*!< low/very low1 quality mode K factor = 4 / 2 */
213 kPDM_QualityModeVeryLow2KFactor = 8U, /*!< very low2 quality mode K factor = 8 / 2 */
214 };
215
216 /*! @brief PDM decimation filter output gain */
217 typedef enum _pdm_df_output_gain
218 {
219 kPDM_DfOutputGain0 = 0U, /*!< Decimation filter output gain 0 */
220 kPDM_DfOutputGain1 = 1U, /*!< Decimation filter output gain 1 */
221 kPDM_DfOutputGain2 = 2U, /*!< Decimation filter output gain 2 */
222 kPDM_DfOutputGain3 = 3U, /*!< Decimation filter output gain 3 */
223 kPDM_DfOutputGain4 = 4U, /*!< Decimation filter output gain 4 */
224 kPDM_DfOutputGain5 = 5U, /*!< Decimation filter output gain 5 */
225 kPDM_DfOutputGain6 = 6U, /*!< Decimation filter output gain 6 */
226 kPDM_DfOutputGain7 = 7U, /*!< Decimation filter output gain 7 */
227 kPDM_DfOutputGain8 = 8U, /*!< Decimation filter output gain 8 */
228 kPDM_DfOutputGain9 = 9U, /*!< Decimation filter output gain 9 */
229 kPDM_DfOutputGain10 = 0xAU, /*!< Decimation filter output gain 10 */
230 kPDM_DfOutputGain11 = 0xBU, /*!< Decimation filter output gain 11 */
231 kPDM_DfOutputGain12 = 0xCU, /*!< Decimation filter output gain 12 */
232 kPDM_DfOutputGain13 = 0xDU, /*!< Decimation filter output gain 13 */
233 kPDM_DfOutputGain14 = 0xEU, /*!< Decimation filter output gain 14 */
234 kPDM_DfOutputGain15 = 0xFU, /*!< Decimation filter output gain 15 */
235 } pdm_df_output_gain_t;
236
237 /*! @brief PDM data width */
238 enum _pdm_data_width
239 {
240 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH != 2U)
241 kPDM_DataWwidth24 = 3U, /*!< PDM data width 24bit */
242 kPDM_DataWwidth32 = 4U, /*!< PDM data width 32bit */
243 #else
244 kPDM_DataWdith16 = 2U, /*!< PDM data width 16bit */
245 #endif
246 };
247
248 /*! @brief PDM channel configurations */
249 typedef struct _pdm_channel_config
250 {
251 #if (defined(FSL_FEATURE_PDM_HAS_DC_OUT_CTRL) && (FSL_FEATURE_PDM_HAS_DC_OUT_CTRL))
252 pdm_dc_remover_t outputCutOffFreq; /*!< PDM output DC remover cut off frequency */
253 #endif
254
255 #if !(defined(FSL_FEATURE_PDM_DC_CTRL_VALUE_FIXED) && (FSL_FEATURE_PDM_DC_CTRL_VALUE_FIXED))
256 pdm_dc_remover_t cutOffFreq; /*!< DC remover cut off frequency */
257 #endif
258
259 pdm_df_output_gain_t gain; /*!< Decimation Filter Output Gain */
260 } pdm_channel_config_t;
261
262 /*! @brief PDM user configuration structure */
263 typedef struct _pdm_config
264 {
265 bool
266 enableDoze; /*!< This module will enter disable/low leakage mode if DOZEN is active with ipg_doze is asserted */
267 uint8_t fifoWatermark; /*!< Watermark value for FIFO */
268 pdm_df_quality_mode_t qualityMode; /*!< Quality mode */
269 uint8_t cicOverSampleRate; /*!< CIC filter over sampling rate */
270 } pdm_config_t;
271
272 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
273 /*! @brief PDM voice activity detector interrupt type */
274 enum _pdm_hwvad_interrupt_enable
275 {
276 kPDM_HwvadErrorInterruptEnable = PDM_VAD0_CTRL_1_VADERIE_MASK, /*!< PDM channel HWVAD error interrupt enable. */
277 kPDM_HwvadInterruptEnable = PDM_VAD0_CTRL_1_VADIE_MASK, /*!< PDM channel HWVAD interrupt */
278 };
279
280 /*! @brief The PDM hwvad interrupt status flag */
281 enum _pdm_hwvad_int_status
282 {
283 kPDM_HwvadStatusInputSaturation = PDM_VAD0_STAT_VADINSATF_MASK, /*!< HWVAD saturation condition */
284 kPDM_HwvadStatusVoiceDetectFlag = PDM_VAD0_STAT_VADIF_MASK, /*!< HWVAD voice detect interrupt triggered */
285 };
286
287 /*! @brief High pass filter configure cut-off frequency*/
288 typedef enum _pdm_hwvad_hpf_config
289 {
290 kPDM_HwvadHpfBypassed = 0x0U, /*!< High-pass filter bypass */
291 kPDM_HwvadHpfCutOffFreq1750Hz = 0x1U, /*!< High-pass filter cut off frequency 1750HZ */
292 kPDM_HwvadHpfCutOffFreq215Hz = 0x2U, /*!< High-pass filter cut off frequency 215HZ */
293 kPDM_HwvadHpfCutOffFreq102Hz = 0x3U, /*!< High-pass filter cut off frequency 102HZ */
294 } pdm_hwvad_hpf_config_t;
295
296 /*! @brief HWVAD internal filter status */
297 typedef enum _pdm_hwvad_filter_status
298 {
299 kPDM_HwvadInternalFilterNormalOperation = 0U, /*!< internal filter ready for normal operation */
300 kPDM_HwvadInternalFilterInitial = PDM_VAD0_CTRL_1_VADST10_MASK, /*!< interla filter are initial */
301 } pdm_hwvad_filter_status_t;
302
303 /*! @brief PDM voice activity detector user configuration structure */
304 typedef struct _pdm_hwvad_config
305 {
306 uint8_t channel; /*!< Which channel uses voice activity detector */
307 uint8_t initializeTime; /*!< Number of frames or samples to initialize voice activity detector. */
308 uint8_t cicOverSampleRate; /*!< CIC filter over sampling rate */
309
310 uint8_t inputGain; /*!< Voice activity detector input gain */
311 uint32_t frameTime; /*!< Voice activity frame time */
312 pdm_hwvad_hpf_config_t cutOffFreq; /*!< High pass filter cut off frequency */
313 bool enableFrameEnergy; /*!< If frame energy enabled, true means enable */
314 bool enablePreFilter; /*!< If pre-filter enabled */
315 } pdm_hwvad_config_t;
316
317 /*! @brief PDM voice activity detector noise filter user configuration structure */
318 typedef struct _pdm_hwvad_noise_filter
319 {
320 bool enableAutoNoiseFilter; /*!< If noise fileter automatically activated, true means enable */
321 bool enableNoiseMin; /*!< If Noise minimum block enabled, true means enabled */
322 bool enableNoiseDecimation; /*!< If enable noise input decimation */
323 bool enableNoiseDetectOR; /*!< Enables a OR logic in the output of minimum noise estimator block */
324 uint32_t noiseFilterAdjustment; /*!< The adjustment value of the noise filter */
325 uint32_t noiseGain; /*!< Gain value for the noise energy or envelope estimated */
326 } pdm_hwvad_noise_filter_t;
327
328 /*! @brief PDM voice activity detector zero cross detector result */
329 typedef enum _pdm_hwvad_zcd_result
330 {
331 kPDM_HwvadResultOREnergyBasedDetection =
332 0U, /*!< zero cross detector result will be OR with energy based detection */
333 kPDM_HwvadResultANDEnergyBasedDetection =
334 1U, /*!< zero cross detector result will be AND with energy based detection */
335 } pdm_hwvad_zcd_result_t;
336
337 /*! @brief PDM voice activity detector zero cross detector configuration structure */
338 typedef struct _pdm_hwvad_zero_cross_detector
339 {
340 bool enableAutoThreshold; /*!< If ZCD auto-threshold enabled, true means enabled. */
341 pdm_hwvad_zcd_result_t zcdAnd; /*!< Is ZCD result is AND'ed with energy-based detection, false means OR'ed */
342 uint32_t threshold; /*!< The adjustment value of the noise filter */
343 uint32_t adjustmentThreshold; /*!< Gain value for the noise energy or envelope estimated */
344 } pdm_hwvad_zero_cross_detector_t;
345 #endif
346
347 /*! @brief PDM SDMA transfer structure */
348 typedef struct _pdm_transfer
349 {
350 volatile uint8_t *data; /*!< Data start address to transfer. */
351 volatile size_t dataSize; /*!< Total Transfer bytes size. */
352 } pdm_transfer_t;
353
354 /*! @brief PDM handle */
355 typedef struct _pdm_handle pdm_handle_t;
356
357 /*! @brief PDM transfer callback prototype */
358 typedef void (*pdm_transfer_callback_t)(PDM_Type *base, pdm_handle_t *handle, status_t status, void *userData);
359
360 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
361 /*! @brief PDM HWVAD callback prototype */
362 typedef void (*pdm_hwvad_callback_t)(status_t status, void *userData);
363 /*! @brief PDM HWVAD notification structure */
364 typedef struct _pdm_hwvad_notification
365 {
366 pdm_hwvad_callback_t callback;
367 void *userData;
368 } pdm_hwvad_notification_t;
369 #endif
370
371 /*! @brief PDM handle structure */
372 struct _pdm_handle
373 {
374 uint32_t state; /*!< Transfer status */
375 pdm_transfer_callback_t callback; /*!< Callback function called at transfer event*/
376 void *userData; /*!< Callback parameter passed to callback function*/
377
378 pdm_transfer_t pdmQueue[PDM_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
379 size_t transferSize[PDM_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
380 volatile uint8_t queueUser; /*!< Index for user to queue transfer */
381 volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
382
383 uint32_t format; /*!< data format */
384 uint8_t watermark; /*!< Watermark value */
385 uint8_t startChannel; /*!< end channel */
386 uint8_t channelNums; /*!< Enabled channel number */
387 };
388
389 /*******************************************************************************
390 * API
391 ******************************************************************************/
392
393 #if defined(__cplusplus)
394 extern "C" {
395 #endif /*_cplusplus*/
396
397 /*!
398 * @name Initialization and deinitialization
399 * @{
400 */
401
402 /*!
403 * @brief Initializes the PDM peripheral.
404 *
405 * Ungates the PDM clock, resets the module, and configures PDM with a configuration structure.
406 * The configuration structure can be custom filled or set with default values by
407 * PDM_GetDefaultConfig().
408 *
409 * @note This API should be called at the beginning of the application to use
410 * the PDM driver. Otherwise, accessing the PDM module can cause a hard fault
411 * because the clock is not enabled.
412 *
413 * @param base PDM base pointer
414 * @param config PDM configuration structure.
415 */
416 void PDM_Init(PDM_Type *base, const pdm_config_t *config);
417
418 /*!
419 * @brief De-initializes the PDM peripheral.
420 *
421 * This API gates the PDM clock. The PDM module can't operate unless PDM_Init
422 * is called to enable the clock.
423 *
424 * @param base PDM base pointer
425 */
426 void PDM_Deinit(PDM_Type *base);
427
428 /*!
429 * @brief Resets the PDM module.
430 *
431 * @param base PDM base pointer
432 */
PDM_Reset(PDM_Type * base)433 static inline void PDM_Reset(PDM_Type *base)
434 {
435 base->CTRL_1 |= PDM_CTRL_1_SRES_MASK;
436 }
437
438 /*!
439 * @brief Enables/disables PDM interface.
440 *
441 * @param base PDM base pointer
442 * @param enable True means PDM interface is enabled, false means PDM interface is disabled.
443 */
PDM_Enable(PDM_Type * base,bool enable)444 static inline void PDM_Enable(PDM_Type *base, bool enable)
445 {
446 if (enable)
447 {
448 base->CTRL_1 |= PDM_CTRL_1_PDMIEN_MASK;
449 }
450 else
451 {
452 base->CTRL_1 &= ~PDM_CTRL_1_PDMIEN_MASK;
453 }
454 }
455
456 /*!
457 * @brief Enables/disables DOZE.
458 *
459 * @param base PDM base pointer
460 * @param enable True means the module will enter Disable/Low Leakage mode when ipg_doze is asserted, false means the
461 * module will not enter Disable/Low Leakage mode when ipg_doze is asserted.
462 */
PDM_EnableDoze(PDM_Type * base,bool enable)463 static inline void PDM_EnableDoze(PDM_Type *base, bool enable)
464 {
465 if (enable)
466 {
467 base->CTRL_1 |= PDM_CTRL_1_DOZEN_MASK;
468 }
469 else
470 {
471 base->CTRL_1 &= ~PDM_CTRL_1_DOZEN_MASK;
472 }
473 }
474
475 /*!
476 * @brief Enables/disables debug mode for PDM.
477 * The PDM interface cannot enter debug mode once in Disable/Low Leakage or Low Power mode.
478 * @param base PDM base pointer
479 * @param enable True means PDM interface enter debug mode, false means PDM interface in normal mode.
480 */
PDM_EnableDebugMode(PDM_Type * base,bool enable)481 static inline void PDM_EnableDebugMode(PDM_Type *base, bool enable)
482 {
483 if (enable)
484 {
485 base->CTRL_1 |= PDM_CTRL_1_DBG_MASK;
486 }
487 else
488 {
489 base->CTRL_1 &= ~PDM_CTRL_1_DBG_MASK;
490 }
491 }
492
493 /*!
494 * @brief Enables/disables PDM interface in debug mode.
495 *
496 * @param base PDM base pointer
497 * @param enable True means PDM interface is enabled debug mode, false means PDM interface is disabled after
498 * after completing the current frame in debug mode.
499 */
PDM_EnableInDebugMode(PDM_Type * base,bool enable)500 static inline void PDM_EnableInDebugMode(PDM_Type *base, bool enable)
501 {
502 if (enable)
503 {
504 base->CTRL_1 |= PDM_CTRL_1_DBGE_MASK;
505 }
506 else
507 {
508 base->CTRL_1 &= ~PDM_CTRL_1_DBGE_MASK;
509 }
510 }
511
512 /*!
513 * @brief Enables/disables PDM interface disable/Low Leakage mode.
514 *
515 * @param base PDM base pointer
516 * @param enable True means PDM interface is in disable/low leakage mode, False means PDM interface is in normal mode.
517 */
PDM_EnterLowLeakageMode(PDM_Type * base,bool enable)518 static inline void PDM_EnterLowLeakageMode(PDM_Type *base, bool enable)
519 {
520 if (enable)
521 {
522 base->CTRL_1 |= PDM_CTRL_1_MDIS_MASK;
523 }
524 else
525 {
526 base->CTRL_1 &= ~PDM_CTRL_1_MDIS_MASK;
527 }
528 }
529
530 /*!
531 * @brief Enables/disables the PDM channel.
532 *
533 * @param base PDM base pointer
534 * @param channel PDM channel number need to enable or disable.
535 * @param enable True means enable PDM channel, false means disable.
536 */
PDM_EnableChannel(PDM_Type * base,uint8_t channel,bool enable)537 static inline void PDM_EnableChannel(PDM_Type *base, uint8_t channel, bool enable)
538 {
539 if (enable)
540 {
541 base->CTRL_1 |= (1UL << channel);
542 }
543 else
544 {
545 base->CTRL_1 &= ~(1UL << channel);
546 }
547 }
548
549 /*!
550 * @brief PDM one channel configurations.
551 *
552 * @param base PDM base pointer
553 * @param config PDM channel configurations.
554 * @param channel channel number.
555 * after completing the current frame in debug mode.
556 */
557 void PDM_SetChannelConfig(PDM_Type *base, uint32_t channel, const pdm_channel_config_t *config);
558
559 /*!
560 * @brief PDM set sample rate.
561 *
562 * @note This function is depend on the configuration of the PDM and PDM channel, so the correct call sequence is
563 * @code
564 * PDM_Init(base, pdmConfig)
565 * PDM_SetChannelConfig(base, channel, &channelConfig)
566 * PDM_SetSampleRateConfig(base, source, sampleRate)
567 * @endcode
568 * @param base PDM base pointer
569 * @param sourceClock_HZ PDM source clock frequency.
570 * @param sampleRate_HZ PDM sample rate.
571 */
572 status_t PDM_SetSampleRateConfig(PDM_Type *base, uint32_t sourceClock_HZ, uint32_t sampleRate_HZ);
573
574 /*!
575 * @brief PDM set sample rate.
576 *
577 * @deprecated Do not use this function. It has been superceded by @ref PDM_SetSampleRateConfig
578 * @param base PDM base pointer
579 * @param enableChannelMask PDM channel enable mask.
580 * @param qualityMode quality mode.
581 * @param osr cic oversample rate
582 * @param clkDiv clock divider
583 */
584 status_t PDM_SetSampleRate(
585 PDM_Type *base, uint32_t enableChannelMask, pdm_df_quality_mode_t qualityMode, uint8_t osr, uint32_t clkDiv);
586
587 /*!
588 * @brief Get the instance number for PDM.
589 *
590 * @param base PDM base pointer.
591 */
592 uint32_t PDM_GetInstance(PDM_Type *base);
593 /*! @} */
594
595 /*!
596 * @name Status
597 * @{
598 */
599
600 /*!
601 * @brief Gets the PDM internal status flag.
602 * Use the Status Mask in _pdm_internal_status to get the status value needed
603 * @param base PDM base pointer
604 * @return PDM status flag value.
605 */
PDM_GetStatus(PDM_Type * base)606 static inline uint32_t PDM_GetStatus(PDM_Type *base)
607 {
608 return base->STAT;
609 }
610
611 /*!
612 * @brief Gets the PDM FIFO status flag.
613 * Use the Status Mask in _pdm_fifo_status to get the status value needed
614 * @param base PDM base pointer
615 * @return FIFO status.
616 */
PDM_GetFifoStatus(PDM_Type * base)617 static inline uint32_t PDM_GetFifoStatus(PDM_Type *base)
618 {
619 return base->FIFO_STAT;
620 }
621
622 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
623 /*!
624 * @brief Gets the PDM Range status flag.
625 * Use the Status Mask in _pdm_range_status to get the status value needed
626 * @param base PDM base pointer
627 * @return output status.
628 */
PDM_GetRangeStatus(PDM_Type * base)629 static inline uint32_t PDM_GetRangeStatus(PDM_Type *base)
630 {
631 return base->RANGE_STAT;
632 }
633 #else
634 /*!
635 * @brief Gets the PDM output status flag.
636 * Use the Status Mask in _pdm_output_status to get the status value needed
637 * @param base PDM base pointer
638 * @return output status.
639 */
PDM_GetOutputStatus(PDM_Type * base)640 static inline uint32_t PDM_GetOutputStatus(PDM_Type *base)
641 {
642 return base->OUT_STAT;
643 }
644 #endif
645
646 /*!
647 * @brief Clears the PDM Tx status.
648 *
649 * @param base PDM base pointer
650 * @param mask State mask. It can be a combination of the status between kPDM_StatusFrequencyLow and
651 * kPDM_StatusCh7FifoDataAvaliable.
652 */
PDM_ClearStatus(PDM_Type * base,uint32_t mask)653 static inline void PDM_ClearStatus(PDM_Type *base, uint32_t mask)
654 {
655 base->STAT = mask;
656 }
657
658 /*!
659 * @brief Clears the PDM Tx status.
660 *
661 * @param base PDM base pointer
662 * @param mask State mask.It can be a combination of the status in _pdm_fifo_status.
663 */
PDM_ClearFIFOStatus(PDM_Type * base,uint32_t mask)664 static inline void PDM_ClearFIFOStatus(PDM_Type *base, uint32_t mask)
665 {
666 base->FIFO_STAT = mask;
667 }
668
669 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
670 /*!
671 * @brief Clears the PDM range status.
672 *
673 * @param base PDM base pointer
674 * @param mask State mask. It can be a combination of the status in _pdm_range_status.
675 */
PDM_ClearRangeStatus(PDM_Type * base,uint32_t mask)676 static inline void PDM_ClearRangeStatus(PDM_Type *base, uint32_t mask)
677 {
678 base->RANGE_STAT = mask;
679 }
680 #else
681 /*!
682 * @brief Clears the PDM output status.
683 *
684 * @param base PDM base pointer
685 * @param mask State mask. It can be a combination of the status in _pdm_output_status.
686 */
PDM_ClearOutputStatus(PDM_Type * base,uint32_t mask)687 static inline void PDM_ClearOutputStatus(PDM_Type *base, uint32_t mask)
688 {
689 base->OUT_STAT = mask;
690 }
691 #endif
692
693 /*! @} */
694
695 /*!
696 * @name Interrupts
697 * @{
698 */
699
700 /*!
701 * @brief Enables the PDM interrupt requests.
702 *
703 * @param base PDM base pointer
704 * @param mask interrupt source
705 * The parameter can be a combination of the following sources if defined.
706 * @arg kPDM_ErrorInterruptEnable
707 * @arg kPDM_FIFOInterruptEnable
708 */
709 void PDM_EnableInterrupts(PDM_Type *base, uint32_t mask);
710
711 /*!
712 * @brief Disables the PDM interrupt requests.
713 *
714 * @param base PDM base pointer
715 * @param mask interrupt source
716 * The parameter can be a combination of the following sources if defined.
717 * @arg kPDM_ErrorInterruptEnable
718 * @arg kPDM_FIFOInterruptEnable
719 */
PDM_DisableInterrupts(PDM_Type * base,uint32_t mask)720 static inline void PDM_DisableInterrupts(PDM_Type *base, uint32_t mask)
721 {
722 base->CTRL_1 &= ~mask;
723 }
724
725 /*! @} */
726
727 /*!
728 * @name DMA Control
729 * @{
730 */
731
732 /*!
733 * @brief Enables/disables the PDM DMA requests.
734 *
735 * @param base PDM base pointer
736 * @param enable True means enable DMA, false means disable DMA.
737 */
PDM_EnableDMA(PDM_Type * base,bool enable)738 static inline void PDM_EnableDMA(PDM_Type *base, bool enable)
739 {
740 if (enable)
741 {
742 base->CTRL_1 = (base->CTRL_1 & (~PDM_CTRL_1_DISEL_MASK)) | PDM_CTRL_1_DISEL(0x1U);
743 }
744 else
745 {
746 base->CTRL_1 &= ~PDM_CTRL_1_DISEL_MASK;
747 }
748 }
749
750 /*!
751 * @brief Gets the PDM data register address.
752 *
753 * This API is used to provide a transfer address for the PDM DMA transfer configuration.
754 *
755 * @param base PDM base pointer.
756 * @param channel Which data channel used.
757 * @return data register address.
758 */
PDM_GetDataRegisterAddress(PDM_Type * base,uint32_t channel)759 static inline uint32_t PDM_GetDataRegisterAddress(PDM_Type *base, uint32_t channel)
760 {
761 return (uint32_t)(&(base->DATACH)[channel]);
762 }
763
764 /*! @} */
765
766 /*!
767 * @name Bus Operations
768 * @{
769 */
770 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 2U)
771 /*!
772 * @brief Reads data from the PDM FIFO.
773 *
774 * @param base PDM base pointer.
775 * @param channel Data channel used.
776 * @return Data in PDM FIFO.
777 */
PDM_ReadData(PDM_Type * base,uint32_t channel)778 static inline int16_t PDM_ReadData(PDM_Type *base, uint32_t channel)
779 {
780 return (int16_t)(base->DATACH[channel]);
781 }
782
783 /*!
784 * @brief PDM read data non blocking.
785 * So the actually read data byte size in this function is (size * 2 * channelNums).
786 * @param base PDM base pointer.
787 * @param startChannel start channel number.
788 * @param channelNums total enabled channelnums.
789 * @param buffer received buffer address.
790 * @param size number of 16bit data to read.
791 */
792 void PDM_ReadNonBlocking(PDM_Type *base, uint32_t startChannel, uint32_t channelNums, int16_t *buffer, size_t size);
793 #endif
794
795 /*!
796 * @brief PDM read fifo.
797 * @note: This function support 16 bit only for IP version that only supports 16bit.
798 *
799 * @param base PDM base pointer.
800 * @param startChannel start channel number.
801 * @param channelNums total enabled channelnums.
802 * @param buffer received buffer address.
803 * @param size number of samples to read.
804 * @param dataWidth sample width.
805 */
806 void PDM_ReadFifo(
807 PDM_Type *base, uint32_t startChannel, uint32_t channelNums, void *buffer, size_t size, uint32_t dataWidth);
808
809 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 4U)
810 /*!
811 * @brief Reads data from the PDM FIFO.
812 *
813 * @param base PDM base pointer.
814 * @param channel Data channel used.
815 * @return Data in PDM FIFO.
816 */
PDM_ReadData(PDM_Type * base,uint32_t channel)817 static inline uint32_t PDM_ReadData(PDM_Type *base, uint32_t channel)
818 {
819 return base->DATACH[channel];
820 }
821 #endif
822
823 /*!
824 * @brief Set the PDM channel gain.
825 *
826 * Please note for different quality mode, the valid gain value is different, reference RM for detail.
827 * @param base PDM base pointer.
828 * @param channel PDM channel index.
829 * @param gain channel gain, the register gain value range is 0 - 15.
830 */
831 void PDM_SetChannelGain(PDM_Type *base, uint32_t channel, pdm_df_output_gain_t gain);
832
833 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
834 /*! @} */
835
836 /*!
837 * @name Voice Activity Detector
838 * @{
839 */
840
841 /*!
842 * @brief Configure voice activity detector.
843 *
844 * @param base PDM base pointer
845 * @param config Voice activity detector configure structure pointer .
846 */
847 void PDM_SetHwvadConfig(PDM_Type *base, const pdm_hwvad_config_t *config);
848
849 /*!
850 * @brief PDM hwvad force output disable.
851 *
852 * @param base PDM base pointer
853 * @param enable true is output force disable, false is output not force.
854 */
PDM_ForceHwvadOutputDisable(PDM_Type * base,bool enable)855 static inline void PDM_ForceHwvadOutputDisable(PDM_Type *base, bool enable)
856 {
857 if (enable)
858 {
859 base->VAD0_CTRL_2 &= ~PDM_VAD0_CTRL_2_VADFOUTDIS_MASK;
860 }
861 else
862 {
863 base->VAD0_CTRL_2 |= PDM_VAD0_CTRL_2_VADFOUTDIS_MASK;
864 }
865 }
866
867 /*!
868 * @brief PDM hwvad reset.
869 * It will reset VADNDATA register and will clean all internal buffers, should be called when the PDM isn't running.
870 *
871 * @param base PDM base pointer
872 */
PDM_ResetHwvad(PDM_Type * base)873 static inline void PDM_ResetHwvad(PDM_Type *base)
874 {
875 base->VAD0_CTRL_1 |= PDM_VAD0_CTRL_1_VADRST_MASK;
876 }
877 /*!
878 * @brief Enable/Disable Voice activity detector.
879 * Should be called when the PDM isn't running.
880 * @param base PDM base pointer.
881 * @param enable True means enable voice activity detector, false means disable.
882 */
PDM_EnableHwvad(PDM_Type * base,bool enable)883 static inline void PDM_EnableHwvad(PDM_Type *base, bool enable)
884 {
885 if (enable)
886 {
887 base->VAD0_CTRL_1 |= PDM_VAD0_CTRL_1_VADEN_MASK;
888 }
889 else
890 {
891 base->VAD0_CTRL_1 &= ~PDM_VAD0_CTRL_1_VADEN_MASK;
892 }
893 }
894
895 /*!
896 * @brief Enables the PDM Voice Detector interrupt requests.
897 *
898 * @param base PDM base pointer
899 * @param mask interrupt source
900 * The parameter can be a combination of the following sources if defined.
901 * @arg kPDM_HWVADErrorInterruptEnable
902 * @arg kPDM_HWVADInterruptEnable
903 */
PDM_EnableHwvadInterrupts(PDM_Type * base,uint32_t mask)904 static inline void PDM_EnableHwvadInterrupts(PDM_Type *base, uint32_t mask)
905 {
906 base->VAD0_CTRL_1 |= mask;
907 }
908
909 /*!
910 * @brief Disables the PDM Voice Detector interrupt requests.
911 *
912 * @param base PDM base pointer
913 * @param mask interrupt source
914 * The parameter can be a combination of the following sources if defined.
915 * @arg kPDM_HWVADErrorInterruptEnable
916 * @arg kPDM_HWVADInterruptEnable
917 */
PDM_DisableHwvadInterrupts(PDM_Type * base,uint32_t mask)918 static inline void PDM_DisableHwvadInterrupts(PDM_Type *base, uint32_t mask)
919 {
920 base->VAD0_CTRL_1 &= ~mask;
921 }
922
923 /*!
924 * @brief Clears the PDM voice activity detector status flags.
925 *
926 * @param base PDM base pointer
927 * @param mask State mask,reference _pdm_hwvad_int_status.
928 */
PDM_ClearHwvadInterruptStatusFlags(PDM_Type * base,uint32_t mask)929 static inline void PDM_ClearHwvadInterruptStatusFlags(PDM_Type *base, uint32_t mask)
930 {
931 base->VAD0_STAT = mask;
932 }
933
934 /*!
935 * @brief Clears the PDM voice activity detector status flags.
936 *
937 * @param base PDM base pointer
938 * @return status, reference _pdm_hwvad_int_status
939 */
PDM_GetHwvadInterruptStatusFlags(PDM_Type * base)940 static inline uint32_t PDM_GetHwvadInterruptStatusFlags(PDM_Type *base)
941 {
942 return base->VAD0_STAT & (PDM_VAD0_STAT_VADIF_MASK | PDM_VAD0_STAT_VADINSATF_MASK);
943 }
944
945 /*!
946 * @brief Get the PDM voice activity detector initial flags.
947 *
948 * @param base PDM base pointer
949 * @return initial flag.
950 */
PDM_GetHwvadInitialFlag(PDM_Type * base)951 static inline uint32_t PDM_GetHwvadInitialFlag(PDM_Type *base)
952 {
953 return base->VAD0_STAT & PDM_VAD0_STAT_VADINITF_MASK;
954 }
955
956 #if !(defined(FSL_FEATURE_PDM_HAS_NO_VADEF) && (FSL_FEATURE_PDM_HAS_NO_VADEF))
957 /*!
958 * @brief Get the PDM voice activity detector voice detected flags.
959 * NOte: this flag is auto cleared when voice gone.
960 * @param base PDM base pointer
961 * @return voice detected flag.
962 */
PDM_GetHwvadVoiceDetectedFlag(PDM_Type * base)963 static inline uint32_t PDM_GetHwvadVoiceDetectedFlag(PDM_Type *base)
964 {
965 return base->VAD0_STAT & PDM_VAD0_STAT_VADEF_MASK;
966 }
967 #endif
968
969 /*!
970 * @brief Enables/disables voice activity detector signal filter.
971 *
972 * @param base PDM base pointer
973 * @param enable True means enable signal filter, false means disable.
974 */
PDM_EnableHwvadSignalFilter(PDM_Type * base,bool enable)975 static inline void PDM_EnableHwvadSignalFilter(PDM_Type *base, bool enable)
976 {
977 if (enable)
978 {
979 base->VAD0_SCONFIG |= PDM_VAD0_SCONFIG_VADSFILEN_MASK;
980 }
981 else
982 {
983 base->VAD0_SCONFIG &= ~PDM_VAD0_SCONFIG_VADSFILEN_MASK;
984 }
985 }
986
987 /*!
988 * @brief Configure voice activity detector signal filter.
989 *
990 * @param base PDM base pointer
991 * @param enableMaxBlock If signal maximum block enabled.
992 * @param signalGain Gain value for the signal energy.
993 */
994 void PDM_SetHwvadSignalFilterConfig(PDM_Type *base, bool enableMaxBlock, uint32_t signalGain);
995
996 /*!
997 * @brief Configure voice activity detector noise filter.
998 *
999 * @param base PDM base pointer
1000 * @param config Voice activity detector noise filter configure structure pointer .
1001 */
1002 void PDM_SetHwvadNoiseFilterConfig(PDM_Type *base, const pdm_hwvad_noise_filter_t *config);
1003
1004 /*!
1005 * @brief Enables/disables voice activity detector zero cross detector.
1006 *
1007 * @param base PDM base pointer
1008 * @param enable True means enable zero cross detector, false means disable.
1009 */
PDM_EnableHwvadZeroCrossDetector(PDM_Type * base,bool enable)1010 static inline void PDM_EnableHwvadZeroCrossDetector(PDM_Type *base, bool enable)
1011 {
1012 if (enable)
1013 {
1014 base->VAD0_ZCD |= PDM_VAD0_ZCD_VADZCDEN_MASK;
1015 }
1016 else
1017 {
1018 base->VAD0_ZCD &= ~PDM_VAD0_ZCD_VADZCDEN_MASK;
1019 }
1020 }
1021
1022 /*!
1023 * @brief Configure voice activity detector zero cross detector.
1024 *
1025 * @param base PDM base pointer
1026 * @param config Voice activity detector zero cross detector configure structure pointer .
1027 */
1028 void PDM_SetHwvadZeroCrossDetectorConfig(PDM_Type *base, const pdm_hwvad_zero_cross_detector_t *config);
1029
1030 /*!
1031 * @brief Reads noise data.
1032 *
1033 * @param base PDM base pointer.
1034 * @return Data in PDM noise data register.
1035 */
PDM_GetNoiseData(PDM_Type * base)1036 static inline uint16_t PDM_GetNoiseData(PDM_Type *base)
1037 {
1038 return (uint16_t)base->VAD0_NDATA;
1039 }
1040
1041 /*!
1042 * @brief set hwvad internal filter status .
1043 * Note: filter initial status should be asserted for two more cycles, then set it to normal operation.
1044 * @param base PDM base pointer.
1045 * @param status internal filter status.
1046 */
PDM_SetHwvadInternalFilterStatus(PDM_Type * base,pdm_hwvad_filter_status_t status)1047 static inline void PDM_SetHwvadInternalFilterStatus(PDM_Type *base, pdm_hwvad_filter_status_t status)
1048 {
1049 base->VAD0_CTRL_1 = (base->VAD0_CTRL_1 & (~PDM_VAD0_CTRL_1_VADST10_MASK)) | (uint32_t)status;
1050 }
1051
1052 /*!
1053 * @brief set HWVAD in envelope based mode .
1054 * Recommand configurations,
1055 * @code
1056 * static const pdm_hwvad_config_t hwvadConfig = {
1057 * .channel = 0,
1058 * .initializeTime = 10U,
1059 * .cicOverSampleRate = 0U,
1060 * .inputGain = 0U,
1061 * .frameTime = 10U,
1062 * .cutOffFreq = kPDM_HwvadHpfBypassed,
1063 * .enableFrameEnergy = false,
1064 * .enablePreFilter = true,
1065 };
1066
1067 * static const pdm_hwvad_noise_filter_t noiseFilterConfig = {
1068 * .enableAutoNoiseFilter = false,
1069 * .enableNoiseMin = true,
1070 * .enableNoiseDecimation = true,
1071 * .noiseFilterAdjustment = 0U,
1072 * .noiseGain = 7U,
1073 * .enableNoiseDetectOR = true,
1074 * };
1075 * @endcode
1076 * @param base PDM base pointer.
1077 * @param hwvadConfig internal filter status.
1078 * @param noiseConfig Voice activity detector noise filter configure structure pointer.
1079 * @param zcdConfig Voice activity detector zero cross detector configure structure pointer .
1080 * @param signalGain signal gain value.
1081 */
1082 void PDM_SetHwvadInEnvelopeBasedMode(PDM_Type *base,
1083 const pdm_hwvad_config_t *hwvadConfig,
1084 const pdm_hwvad_noise_filter_t *noiseConfig,
1085 const pdm_hwvad_zero_cross_detector_t *zcdConfig,
1086 uint32_t signalGain);
1087
1088 /*!
1089 * brief set HWVAD in energy based mode .
1090 * Recommand configurations,
1091 * code
1092 * static const pdm_hwvad_config_t hwvadConfig = {
1093 * .channel = 0,
1094 * .initializeTime = 10U,
1095 * .cicOverSampleRate = 0U,
1096 * .inputGain = 0U,
1097 * .frameTime = 10U,
1098 * .cutOffFreq = kPDM_HwvadHpfBypassed,
1099 * .enableFrameEnergy = true,
1100 * .enablePreFilter = true,
1101 };
1102
1103 * static const pdm_hwvad_noise_filter_t noiseFilterConfig = {
1104 * .enableAutoNoiseFilter = true,
1105 * .enableNoiseMin = false,
1106 * .enableNoiseDecimation = false,
1107 * .noiseFilterAdjustment = 0U,
1108 * .noiseGain = 7U,
1109 * .enableNoiseDetectOR = false,
1110 * };
1111 * code
1112 * param base PDM base pointer.
1113 * param hwvadConfig internal filter status.
1114 * param noiseConfig Voice activity detector noise filter configure structure pointer.
1115 * param zcdConfig Voice activity detector zero cross detector configure structure pointer .
1116 * param signalGain signal gain value, signal gain value should be properly according to application.
1117 */
1118 void PDM_SetHwvadInEnergyBasedMode(PDM_Type *base,
1119 const pdm_hwvad_config_t *hwvadConfig,
1120 const pdm_hwvad_noise_filter_t *noiseConfig,
1121 const pdm_hwvad_zero_cross_detector_t *zcdConfig,
1122 uint32_t signalGain);
1123
1124 /*!
1125 * @brief Enable/Disable hwvad callback.
1126
1127 * This function enable/disable the hwvad interrupt for the selected PDM peripheral.
1128 *
1129 * @param base Base address of the PDM peripheral.
1130 * @param vadCallback callback Pointer to store callback function, should be NULL when disable.
1131 * @param userData user data.
1132 * @param enable true is enable, false is disable.
1133 * @retval None.
1134 */
1135 void PDM_EnableHwvadInterruptCallback(PDM_Type *base, pdm_hwvad_callback_t vadCallback, void *userData, bool enable);
1136 /*! @} */
1137 #endif
1138
1139 /*!
1140 * @name Transactional
1141 * @{
1142 */
1143
1144 /*!
1145 * @brief Initializes the PDM handle.
1146 *
1147 * This function initializes the handle for the PDM transactional APIs. Call
1148 * this function once to get the handle initialized.
1149 *
1150 * @param base PDM base pointer.
1151 * @param handle PDM handle pointer.
1152 * @param callback Pointer to the user callback function.
1153 * @param userData User parameter passed to the callback function.
1154 */
1155 void PDM_TransferCreateHandle(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_callback_t callback, void *userData);
1156
1157 /*!
1158 * @brief PDM set channel transfer config.
1159 *
1160 * @param base PDM base pointer.
1161 * @param handle PDM handle pointer.
1162 * @param channel PDM channel.
1163 * @param config channel config.
1164 * @param format data format, support data width configurations,_pdm_data_width.
1165 * @retval kStatus_PDM_ChannelConfig_Failed or kStatus_Success.
1166 */
1167 status_t PDM_TransferSetChannelConfig(
1168 PDM_Type *base, pdm_handle_t *handle, uint32_t channel, const pdm_channel_config_t *config, uint32_t format);
1169
1170 /*!
1171 * @brief Performs an interrupt non-blocking receive transfer on PDM.
1172 *
1173 * @note This API returns immediately after the transfer initiates.
1174 * Call the PDM_RxGetTransferStatusIRQ to poll the transfer status and check whether
1175 * the transfer is finished. If the return status is not kStatus_PDM_Busy, the transfer
1176 * is finished.
1177 *
1178 * @param base PDM base pointer
1179 * @param handle Pointer to the pdm_handle_t structure which stores the transfer state.
1180 * @param xfer Pointer to the pdm_transfer_t structure.
1181 * @retval kStatus_Success Successfully started the data receive.
1182 * @retval kStatus_PDM_Busy Previous receive still not finished.
1183 */
1184 status_t PDM_TransferReceiveNonBlocking(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_t *xfer);
1185
1186 /*!
1187 * @brief Aborts the current IRQ receive.
1188 *
1189 * @note This API can be called when an interrupt non-blocking transfer initiates
1190 * to abort the transfer early.
1191 *
1192 * @param base PDM base pointer
1193 * @param handle Pointer to the pdm_handle_t structure which stores the transfer state.
1194 */
1195 void PDM_TransferAbortReceive(PDM_Type *base, pdm_handle_t *handle);
1196
1197 /*!
1198 * @brief Tx interrupt handler.
1199 *
1200 * @param base PDM base pointer.
1201 * @param handle Pointer to the pdm_handle_t structure.
1202 */
1203 void PDM_TransferHandleIRQ(PDM_Type *base, pdm_handle_t *handle);
1204
1205 /*! @} */
1206
1207 #if defined(__cplusplus)
1208 }
1209 #endif /*_cplusplus*/
1210
1211 /*! @} */
1212
1213 #endif /* _FSL_PDM_H_ */
1214