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, 9, 1)) /*!< Version 2.9.1 */
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 #if defined(FSL_FEATURE_PDM_HAS_DECIMATION_FILTER_BYPASS) && FSL_FEATURE_PDM_HAS_DECIMATION_FILTER_BYPASS
268 bool enableFilterBypass; /*!< Switchable bypass path for the decimation filter */
269 #endif
270 uint8_t fifoWatermark; /*!< Watermark value for FIFO */
271 pdm_df_quality_mode_t qualityMode; /*!< Quality mode */
272 uint8_t cicOverSampleRate; /*!< CIC filter over sampling rate */
273 } pdm_config_t;
274
275 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
276 /*! @brief PDM voice activity detector interrupt type */
277 enum _pdm_hwvad_interrupt_enable
278 {
279 kPDM_HwvadErrorInterruptEnable = PDM_VAD0_CTRL_1_VADERIE_MASK, /*!< PDM channel HWVAD error interrupt enable. */
280 kPDM_HwvadInterruptEnable = PDM_VAD0_CTRL_1_VADIE_MASK, /*!< PDM channel HWVAD interrupt */
281 };
282
283 /*! @brief The PDM hwvad interrupt status flag */
284 enum _pdm_hwvad_int_status
285 {
286 kPDM_HwvadStatusInputSaturation = PDM_VAD0_STAT_VADINSATF_MASK, /*!< HWVAD saturation condition */
287 kPDM_HwvadStatusVoiceDetectFlag = PDM_VAD0_STAT_VADIF_MASK, /*!< HWVAD voice detect interrupt triggered */
288 };
289
290 /*! @brief High pass filter configure cut-off frequency*/
291 typedef enum _pdm_hwvad_hpf_config
292 {
293 kPDM_HwvadHpfBypassed = 0x0U, /*!< High-pass filter bypass */
294 kPDM_HwvadHpfCutOffFreq1750Hz = 0x1U, /*!< High-pass filter cut off frequency 1750HZ */
295 kPDM_HwvadHpfCutOffFreq215Hz = 0x2U, /*!< High-pass filter cut off frequency 215HZ */
296 kPDM_HwvadHpfCutOffFreq102Hz = 0x3U, /*!< High-pass filter cut off frequency 102HZ */
297 } pdm_hwvad_hpf_config_t;
298
299 /*! @brief HWVAD internal filter status */
300 typedef enum _pdm_hwvad_filter_status
301 {
302 kPDM_HwvadInternalFilterNormalOperation = 0U, /*!< internal filter ready for normal operation */
303 kPDM_HwvadInternalFilterInitial = PDM_VAD0_CTRL_1_VADST10_MASK, /*!< interla filter are initial */
304 } pdm_hwvad_filter_status_t;
305
306 /*! @brief PDM voice activity detector user configuration structure */
307 typedef struct _pdm_hwvad_config
308 {
309 uint8_t channel; /*!< Which channel uses voice activity detector */
310 uint8_t initializeTime; /*!< Number of frames or samples to initialize voice activity detector. */
311 uint8_t cicOverSampleRate; /*!< CIC filter over sampling rate */
312
313 uint8_t inputGain; /*!< Voice activity detector input gain */
314 uint32_t frameTime; /*!< Voice activity frame time */
315 pdm_hwvad_hpf_config_t cutOffFreq; /*!< High pass filter cut off frequency */
316 bool enableFrameEnergy; /*!< If frame energy enabled, true means enable */
317 bool enablePreFilter; /*!< If pre-filter enabled */
318 } pdm_hwvad_config_t;
319
320 /*! @brief PDM voice activity detector noise filter user configuration structure */
321 typedef struct _pdm_hwvad_noise_filter
322 {
323 bool enableAutoNoiseFilter; /*!< If noise fileter automatically activated, true means enable */
324 bool enableNoiseMin; /*!< If Noise minimum block enabled, true means enabled */
325 bool enableNoiseDecimation; /*!< If enable noise input decimation */
326 bool enableNoiseDetectOR; /*!< Enables a OR logic in the output of minimum noise estimator block */
327 uint32_t noiseFilterAdjustment; /*!< The adjustment value of the noise filter */
328 uint32_t noiseGain; /*!< Gain value for the noise energy or envelope estimated */
329 } pdm_hwvad_noise_filter_t;
330
331 /*! @brief PDM voice activity detector zero cross detector result */
332 typedef enum _pdm_hwvad_zcd_result
333 {
334 kPDM_HwvadResultOREnergyBasedDetection =
335 0U, /*!< zero cross detector result will be OR with energy based detection */
336 kPDM_HwvadResultANDEnergyBasedDetection =
337 1U, /*!< zero cross detector result will be AND with energy based detection */
338 } pdm_hwvad_zcd_result_t;
339
340 /*! @brief PDM voice activity detector zero cross detector configuration structure */
341 typedef struct _pdm_hwvad_zero_cross_detector
342 {
343 bool enableAutoThreshold; /*!< If ZCD auto-threshold enabled, true means enabled. */
344 pdm_hwvad_zcd_result_t zcdAnd; /*!< Is ZCD result is AND'ed with energy-based detection, false means OR'ed */
345 uint32_t threshold; /*!< The adjustment value of the noise filter */
346 uint32_t adjustmentThreshold; /*!< Gain value for the noise energy or envelope estimated */
347 } pdm_hwvad_zero_cross_detector_t;
348 #endif
349
350 /*! @brief PDM SDMA transfer structure */
351 typedef struct _pdm_transfer
352 {
353 volatile uint8_t *data; /*!< Data start address to transfer. */
354 volatile size_t dataSize; /*!< Total Transfer bytes size. */
355 } pdm_transfer_t;
356
357 /*! @brief PDM handle */
358 typedef struct _pdm_handle pdm_handle_t;
359
360 /*! @brief PDM transfer callback prototype */
361 typedef void (*pdm_transfer_callback_t)(PDM_Type *base, pdm_handle_t *handle, status_t status, void *userData);
362
363 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
364 /*! @brief PDM HWVAD callback prototype */
365 typedef void (*pdm_hwvad_callback_t)(status_t status, void *userData);
366 /*! @brief PDM HWVAD notification structure */
367 typedef struct _pdm_hwvad_notification
368 {
369 pdm_hwvad_callback_t callback;
370 void *userData;
371 } pdm_hwvad_notification_t;
372 #endif
373
374 /*! @brief PDM handle structure */
375 struct _pdm_handle
376 {
377 uint32_t state; /*!< Transfer status */
378 pdm_transfer_callback_t callback; /*!< Callback function called at transfer event*/
379 void *userData; /*!< Callback parameter passed to callback function*/
380
381 pdm_transfer_t pdmQueue[PDM_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
382 size_t transferSize[PDM_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
383 volatile uint8_t queueUser; /*!< Index for user to queue transfer */
384 volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
385
386 uint32_t format; /*!< data format */
387 uint8_t watermark; /*!< Watermark value */
388 uint8_t startChannel; /*!< end channel */
389 uint8_t channelNums; /*!< Enabled channel number */
390 };
391
392 /*******************************************************************************
393 * API
394 ******************************************************************************/
395
396 #if defined(__cplusplus)
397 extern "C" {
398 #endif /*_cplusplus*/
399
400 /*!
401 * @name Initialization and deinitialization
402 * @{
403 */
404
405 /*!
406 * @brief Initializes the PDM peripheral.
407 *
408 * Ungates the PDM clock, resets the module, and configures PDM with a configuration structure.
409 * The configuration structure can be custom filled or set with default values by
410 * PDM_GetDefaultConfig().
411 *
412 * @note This API should be called at the beginning of the application to use
413 * the PDM driver. Otherwise, accessing the PDM module can cause a hard fault
414 * because the clock is not enabled.
415 *
416 * @param base PDM base pointer
417 * @param config PDM configuration structure.
418 */
419 void PDM_Init(PDM_Type *base, const pdm_config_t *config);
420
421 /*!
422 * @brief De-initializes the PDM peripheral.
423 *
424 * This API gates the PDM clock. The PDM module can't operate unless PDM_Init
425 * is called to enable the clock.
426 *
427 * @param base PDM base pointer
428 */
429 void PDM_Deinit(PDM_Type *base);
430
431 /*!
432 * @brief Resets the PDM module.
433 *
434 * @param base PDM base pointer
435 */
PDM_Reset(PDM_Type * base)436 static inline void PDM_Reset(PDM_Type *base)
437 {
438 base->CTRL_1 |= PDM_CTRL_1_SRES_MASK;
439 }
440
441 /*!
442 * @brief Enables/disables PDM interface.
443 *
444 * @param base PDM base pointer
445 * @param enable True means PDM interface is enabled, false means PDM interface is disabled.
446 */
PDM_Enable(PDM_Type * base,bool enable)447 static inline void PDM_Enable(PDM_Type *base, bool enable)
448 {
449 if (enable)
450 {
451 base->CTRL_1 |= PDM_CTRL_1_PDMIEN_MASK;
452 }
453 else
454 {
455 base->CTRL_1 &= ~PDM_CTRL_1_PDMIEN_MASK;
456 }
457 }
458
459 #if !(defined(FSL_FEATURE_PDM_HAS_NO_DOZEN) && FSL_FEATURE_PDM_HAS_NO_DOZEN)
460 /*!
461 * @brief Enables/disables DOZE.
462 *
463 * @param base PDM base pointer
464 * @param enable True means the module will enter Disable/Low Leakage mode when ipg_doze is asserted, false means the
465 * module will not enter Disable/Low Leakage mode when ipg_doze is asserted.
466 */
PDM_EnableDoze(PDM_Type * base,bool enable)467 static inline void PDM_EnableDoze(PDM_Type *base, bool enable)
468 {
469 if (enable)
470 {
471 base->CTRL_1 |= PDM_CTRL_1_DOZEN_MASK;
472 }
473 else
474 {
475 base->CTRL_1 &= ~PDM_CTRL_1_DOZEN_MASK;
476 }
477 }
478 #endif
479 /*!
480 * @brief Enables/disables debug mode for PDM.
481 * The PDM interface cannot enter debug mode once in Disable/Low Leakage or Low Power mode.
482 * @param base PDM base pointer
483 * @param enable True means PDM interface enter debug mode, false means PDM interface in normal mode.
484 */
PDM_EnableDebugMode(PDM_Type * base,bool enable)485 static inline void PDM_EnableDebugMode(PDM_Type *base, bool enable)
486 {
487 if (enable)
488 {
489 base->CTRL_1 |= PDM_CTRL_1_DBG_MASK;
490 }
491 else
492 {
493 base->CTRL_1 &= ~PDM_CTRL_1_DBG_MASK;
494 }
495 }
496
497 /*!
498 * @brief Enables/disables PDM interface in debug mode.
499 *
500 * @param base PDM base pointer
501 * @param enable True means PDM interface is enabled debug mode, false means PDM interface is disabled after
502 * after completing the current frame in debug mode.
503 */
PDM_EnableInDebugMode(PDM_Type * base,bool enable)504 static inline void PDM_EnableInDebugMode(PDM_Type *base, bool enable)
505 {
506 if (enable)
507 {
508 base->CTRL_1 |= PDM_CTRL_1_DBGE_MASK;
509 }
510 else
511 {
512 base->CTRL_1 &= ~PDM_CTRL_1_DBGE_MASK;
513 }
514 }
515
516 /*!
517 * @brief Enables/disables PDM interface disable/Low Leakage mode.
518 *
519 * @param base PDM base pointer
520 * @param enable True means PDM interface is in disable/low leakage mode, False means PDM interface is in normal mode.
521 */
PDM_EnterLowLeakageMode(PDM_Type * base,bool enable)522 static inline void PDM_EnterLowLeakageMode(PDM_Type *base, bool enable)
523 {
524 if (enable)
525 {
526 base->CTRL_1 |= PDM_CTRL_1_MDIS_MASK;
527 }
528 else
529 {
530 base->CTRL_1 &= ~PDM_CTRL_1_MDIS_MASK;
531 }
532 }
533
534 /*!
535 * @brief Enables/disables the PDM channel.
536 *
537 * @param base PDM base pointer
538 * @param channel PDM channel number need to enable or disable.
539 * @param enable True means enable PDM channel, false means disable.
540 */
PDM_EnableChannel(PDM_Type * base,uint8_t channel,bool enable)541 static inline void PDM_EnableChannel(PDM_Type *base, uint8_t channel, bool enable)
542 {
543 if (enable)
544 {
545 base->CTRL_1 |= (1UL << channel);
546 }
547 else
548 {
549 base->CTRL_1 &= ~(1UL << channel);
550 }
551 }
552
553 /*!
554 * @brief PDM one channel configurations.
555 *
556 * @param base PDM base pointer
557 * @param config PDM channel configurations.
558 * @param channel channel number.
559 * after completing the current frame in debug mode.
560 */
561 void PDM_SetChannelConfig(PDM_Type *base, uint32_t channel, const pdm_channel_config_t *config);
562
563 /*!
564 * @brief PDM set sample rate.
565 *
566 * @note This function is depend on the configuration of the PDM and PDM channel, so the correct call sequence is
567 * @code
568 * PDM_Init(base, pdmConfig)
569 * PDM_SetChannelConfig(base, channel, &channelConfig)
570 * PDM_SetSampleRateConfig(base, source, sampleRate)
571 * @endcode
572 * @param base PDM base pointer
573 * @param sourceClock_HZ PDM source clock frequency.
574 * @param sampleRate_HZ PDM sample rate.
575 */
576 status_t PDM_SetSampleRateConfig(PDM_Type *base, uint32_t sourceClock_HZ, uint32_t sampleRate_HZ);
577
578 /*!
579 * @brief PDM set sample rate.
580 *
581 * @deprecated Do not use this function. It has been superceded by @ref PDM_SetSampleRateConfig
582 * @param base PDM base pointer
583 * @param enableChannelMask PDM channel enable mask.
584 * @param qualityMode quality mode.
585 * @param osr cic oversample rate
586 * @param clkDiv clock divider
587 */
588 status_t PDM_SetSampleRate(
589 PDM_Type *base, uint32_t enableChannelMask, pdm_df_quality_mode_t qualityMode, uint8_t osr, uint32_t clkDiv);
590
591 /*!
592 * @brief Get the instance number for PDM.
593 *
594 * @param base PDM base pointer.
595 */
596 uint32_t PDM_GetInstance(PDM_Type *base);
597 /*! @} */
598
599 /*!
600 * @name Status
601 * @{
602 */
603
604 /*!
605 * @brief Gets the PDM internal status flag.
606 * Use the Status Mask in _pdm_internal_status to get the status value needed
607 * @param base PDM base pointer
608 * @return PDM status flag value.
609 */
PDM_GetStatus(PDM_Type * base)610 static inline uint32_t PDM_GetStatus(PDM_Type *base)
611 {
612 return base->STAT;
613 }
614
615 /*!
616 * @brief Gets the PDM FIFO status flag.
617 * Use the Status Mask in _pdm_fifo_status to get the status value needed
618 * @param base PDM base pointer
619 * @return FIFO status.
620 */
PDM_GetFifoStatus(PDM_Type * base)621 static inline uint32_t PDM_GetFifoStatus(PDM_Type *base)
622 {
623 return base->FIFO_STAT;
624 }
625
626 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
627 /*!
628 * @brief Gets the PDM Range status flag.
629 * Use the Status Mask in _pdm_range_status to get the status value needed
630 * @param base PDM base pointer
631 * @return output status.
632 */
PDM_GetRangeStatus(PDM_Type * base)633 static inline uint32_t PDM_GetRangeStatus(PDM_Type *base)
634 {
635 return base->RANGE_STAT;
636 }
637 #else
638 /*!
639 * @brief Gets the PDM output status flag.
640 * Use the Status Mask in _pdm_output_status to get the status value needed
641 * @param base PDM base pointer
642 * @return output status.
643 */
PDM_GetOutputStatus(PDM_Type * base)644 static inline uint32_t PDM_GetOutputStatus(PDM_Type *base)
645 {
646 return base->OUT_STAT;
647 }
648 #endif
649
650 /*!
651 * @brief Clears the PDM Tx status.
652 *
653 * @param base PDM base pointer
654 * @param mask State mask. It can be a combination of the status between kPDM_StatusFrequencyLow and
655 * kPDM_StatusCh7FifoDataAvaliable.
656 */
PDM_ClearStatus(PDM_Type * base,uint32_t mask)657 static inline void PDM_ClearStatus(PDM_Type *base, uint32_t mask)
658 {
659 base->STAT = mask;
660 }
661
662 /*!
663 * @brief Clears the PDM Tx status.
664 *
665 * @param base PDM base pointer
666 * @param mask State mask.It can be a combination of the status in _pdm_fifo_status.
667 */
PDM_ClearFIFOStatus(PDM_Type * base,uint32_t mask)668 static inline void PDM_ClearFIFOStatus(PDM_Type *base, uint32_t mask)
669 {
670 base->FIFO_STAT = mask;
671 }
672
673 #if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
674 /*!
675 * @brief Clears the PDM range status.
676 *
677 * @param base PDM base pointer
678 * @param mask State mask. It can be a combination of the status in _pdm_range_status.
679 */
PDM_ClearRangeStatus(PDM_Type * base,uint32_t mask)680 static inline void PDM_ClearRangeStatus(PDM_Type *base, uint32_t mask)
681 {
682 base->RANGE_STAT = mask;
683 }
684 #else
685 /*!
686 * @brief Clears the PDM output status.
687 *
688 * @param base PDM base pointer
689 * @param mask State mask. It can be a combination of the status in _pdm_output_status.
690 */
PDM_ClearOutputStatus(PDM_Type * base,uint32_t mask)691 static inline void PDM_ClearOutputStatus(PDM_Type *base, uint32_t mask)
692 {
693 base->OUT_STAT = mask;
694 }
695 #endif
696
697 /*! @} */
698
699 /*!
700 * @name Interrupts
701 * @{
702 */
703
704 /*!
705 * @brief Enables the PDM interrupt requests.
706 *
707 * @param base PDM base pointer
708 * @param mask interrupt source
709 * The parameter can be a combination of the following sources if defined.
710 * @arg kPDM_ErrorInterruptEnable
711 * @arg kPDM_FIFOInterruptEnable
712 */
713 void PDM_EnableInterrupts(PDM_Type *base, uint32_t mask);
714
715 /*!
716 * @brief Disables the PDM interrupt requests.
717 *
718 * @param base PDM base pointer
719 * @param mask interrupt source
720 * The parameter can be a combination of the following sources if defined.
721 * @arg kPDM_ErrorInterruptEnable
722 * @arg kPDM_FIFOInterruptEnable
723 */
PDM_DisableInterrupts(PDM_Type * base,uint32_t mask)724 static inline void PDM_DisableInterrupts(PDM_Type *base, uint32_t mask)
725 {
726 base->CTRL_1 &= ~mask;
727 }
728
729 /*! @} */
730
731 /*!
732 * @name DMA Control
733 * @{
734 */
735
736 /*!
737 * @brief Enables/disables the PDM DMA requests.
738 *
739 * @param base PDM base pointer
740 * @param enable True means enable DMA, false means disable DMA.
741 */
PDM_EnableDMA(PDM_Type * base,bool enable)742 static inline void PDM_EnableDMA(PDM_Type *base, bool enable)
743 {
744 if (enable)
745 {
746 base->CTRL_1 = (base->CTRL_1 & (~PDM_CTRL_1_DISEL_MASK)) | PDM_CTRL_1_DISEL(0x1U);
747 }
748 else
749 {
750 base->CTRL_1 &= ~PDM_CTRL_1_DISEL_MASK;
751 }
752 }
753
754 /*!
755 * @brief Gets the PDM data register address.
756 *
757 * This API is used to provide a transfer address for the PDM DMA transfer configuration.
758 *
759 * @param base PDM base pointer.
760 * @param channel Which data channel used.
761 * @return data register address.
762 */
PDM_GetDataRegisterAddress(PDM_Type * base,uint32_t channel)763 static inline uint32_t PDM_GetDataRegisterAddress(PDM_Type *base, uint32_t channel)
764 {
765 return (uint32_t)(&(base->DATACH)[channel]);
766 }
767
768 /*! @} */
769
770 /*!
771 * @name Bus Operations
772 * @{
773 */
774 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 2U)
775 /*!
776 * @brief Reads data from the PDM FIFO.
777 *
778 * @param base PDM base pointer.
779 * @param channel Data channel used.
780 * @return Data in PDM FIFO.
781 */
PDM_ReadData(PDM_Type * base,uint32_t channel)782 static inline int16_t PDM_ReadData(PDM_Type *base, uint32_t channel)
783 {
784 return (int16_t)(base->DATACH[channel]);
785 }
786
787 /*!
788 * @brief PDM read data non blocking.
789 * So the actually read data byte size in this function is (size * 2 * channelNums).
790 * @param base PDM base pointer.
791 * @param startChannel start channel number.
792 * @param channelNums total enabled channelnums.
793 * @param buffer received buffer address.
794 * @param size number of 16bit data to read.
795 */
796 void PDM_ReadNonBlocking(PDM_Type *base, uint32_t startChannel, uint32_t channelNums, int16_t *buffer, size_t size);
797 #endif
798
799 /*!
800 * @brief PDM read fifo.
801 * @note: This function support 16 bit only for IP version that only supports 16bit.
802 *
803 * @param base PDM base pointer.
804 * @param startChannel start channel number.
805 * @param channelNums total enabled channelnums.
806 * @param buffer received buffer address.
807 * @param size number of samples to read.
808 * @param dataWidth sample width.
809 */
810 void PDM_ReadFifo(
811 PDM_Type *base, uint32_t startChannel, uint32_t channelNums, void *buffer, size_t size, uint32_t dataWidth);
812
813 #if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 4U)
814 /*!
815 * @brief Reads data from the PDM FIFO.
816 *
817 * @param base PDM base pointer.
818 * @param channel Data channel used.
819 * @return Data in PDM FIFO.
820 */
PDM_ReadData(PDM_Type * base,uint32_t channel)821 static inline uint32_t PDM_ReadData(PDM_Type *base, uint32_t channel)
822 {
823 return base->DATACH[channel];
824 }
825 #endif
826
827 /*!
828 * @brief Set the PDM channel gain.
829 *
830 * Please note for different quality mode, the valid gain value is different, reference RM for detail.
831 * @param base PDM base pointer.
832 * @param channel PDM channel index.
833 * @param gain channel gain, the register gain value range is 0 - 15.
834 */
835 void PDM_SetChannelGain(PDM_Type *base, uint32_t channel, pdm_df_output_gain_t gain);
836
837 #if !(defined(FSL_FEATURE_PDM_HAS_NO_HWVAD) && FSL_FEATURE_PDM_HAS_NO_HWVAD)
838 /*! @} */
839
840 /*!
841 * @name Voice Activity Detector
842 * @{
843 */
844
845 /*!
846 * @brief Configure voice activity detector.
847 *
848 * @param base PDM base pointer
849 * @param config Voice activity detector configure structure pointer .
850 */
851 void PDM_SetHwvadConfig(PDM_Type *base, const pdm_hwvad_config_t *config);
852
853 /*!
854 * @brief PDM hwvad force output disable.
855 *
856 * @param base PDM base pointer
857 * @param enable true is output force disable, false is output not force.
858 */
PDM_ForceHwvadOutputDisable(PDM_Type * base,bool enable)859 static inline void PDM_ForceHwvadOutputDisable(PDM_Type *base, bool enable)
860 {
861 if (enable)
862 {
863 base->VAD0_CTRL_2 &= ~PDM_VAD0_CTRL_2_VADFOUTDIS_MASK;
864 }
865 else
866 {
867 base->VAD0_CTRL_2 |= PDM_VAD0_CTRL_2_VADFOUTDIS_MASK;
868 }
869 }
870
871 /*!
872 * @brief PDM hwvad reset.
873 * It will reset VADNDATA register and will clean all internal buffers, should be called when the PDM isn't running.
874 *
875 * @param base PDM base pointer
876 */
PDM_ResetHwvad(PDM_Type * base)877 static inline void PDM_ResetHwvad(PDM_Type *base)
878 {
879 base->VAD0_CTRL_1 |= PDM_VAD0_CTRL_1_VADRST_MASK;
880 }
881 /*!
882 * @brief Enable/Disable Voice activity detector.
883 * Should be called when the PDM isn't running.
884 * @param base PDM base pointer.
885 * @param enable True means enable voice activity detector, false means disable.
886 */
PDM_EnableHwvad(PDM_Type * base,bool enable)887 static inline void PDM_EnableHwvad(PDM_Type *base, bool enable)
888 {
889 if (enable)
890 {
891 base->VAD0_CTRL_1 |= PDM_VAD0_CTRL_1_VADEN_MASK;
892 }
893 else
894 {
895 base->VAD0_CTRL_1 &= ~PDM_VAD0_CTRL_1_VADEN_MASK;
896 }
897 }
898
899 /*!
900 * @brief Enables the PDM Voice Detector interrupt requests.
901 *
902 * @param base PDM base pointer
903 * @param mask interrupt source
904 * The parameter can be a combination of the following sources if defined.
905 * @arg kPDM_HWVADErrorInterruptEnable
906 * @arg kPDM_HWVADInterruptEnable
907 */
PDM_EnableHwvadInterrupts(PDM_Type * base,uint32_t mask)908 static inline void PDM_EnableHwvadInterrupts(PDM_Type *base, uint32_t mask)
909 {
910 base->VAD0_CTRL_1 |= mask;
911 }
912
913 /*!
914 * @brief Disables the PDM Voice Detector interrupt requests.
915 *
916 * @param base PDM base pointer
917 * @param mask interrupt source
918 * The parameter can be a combination of the following sources if defined.
919 * @arg kPDM_HWVADErrorInterruptEnable
920 * @arg kPDM_HWVADInterruptEnable
921 */
PDM_DisableHwvadInterrupts(PDM_Type * base,uint32_t mask)922 static inline void PDM_DisableHwvadInterrupts(PDM_Type *base, uint32_t mask)
923 {
924 base->VAD0_CTRL_1 &= ~mask;
925 }
926
927 /*!
928 * @brief Clears the PDM voice activity detector status flags.
929 *
930 * @param base PDM base pointer
931 * @param mask State mask,reference _pdm_hwvad_int_status.
932 */
PDM_ClearHwvadInterruptStatusFlags(PDM_Type * base,uint32_t mask)933 static inline void PDM_ClearHwvadInterruptStatusFlags(PDM_Type *base, uint32_t mask)
934 {
935 base->VAD0_STAT = mask;
936 }
937
938 /*!
939 * @brief Clears the PDM voice activity detector status flags.
940 *
941 * @param base PDM base pointer
942 * @return status, reference _pdm_hwvad_int_status
943 */
PDM_GetHwvadInterruptStatusFlags(PDM_Type * base)944 static inline uint32_t PDM_GetHwvadInterruptStatusFlags(PDM_Type *base)
945 {
946 return base->VAD0_STAT & (PDM_VAD0_STAT_VADIF_MASK | PDM_VAD0_STAT_VADINSATF_MASK);
947 }
948
949 /*!
950 * @brief Get the PDM voice activity detector initial flags.
951 *
952 * @param base PDM base pointer
953 * @return initial flag.
954 */
PDM_GetHwvadInitialFlag(PDM_Type * base)955 static inline uint32_t PDM_GetHwvadInitialFlag(PDM_Type *base)
956 {
957 return base->VAD0_STAT & PDM_VAD0_STAT_VADINITF_MASK;
958 }
959
960 #if !(defined(FSL_FEATURE_PDM_HAS_NO_VADEF) && (FSL_FEATURE_PDM_HAS_NO_VADEF))
961 /*!
962 * @brief Get the PDM voice activity detector voice detected flags.
963 * NOte: this flag is auto cleared when voice gone.
964 * @param base PDM base pointer
965 * @return voice detected flag.
966 */
PDM_GetHwvadVoiceDetectedFlag(PDM_Type * base)967 static inline uint32_t PDM_GetHwvadVoiceDetectedFlag(PDM_Type *base)
968 {
969 return base->VAD0_STAT & PDM_VAD0_STAT_VADEF_MASK;
970 }
971 #endif
972
973 /*!
974 * @brief Enables/disables voice activity detector signal filter.
975 *
976 * @param base PDM base pointer
977 * @param enable True means enable signal filter, false means disable.
978 */
PDM_EnableHwvadSignalFilter(PDM_Type * base,bool enable)979 static inline void PDM_EnableHwvadSignalFilter(PDM_Type *base, bool enable)
980 {
981 if (enable)
982 {
983 base->VAD0_SCONFIG |= PDM_VAD0_SCONFIG_VADSFILEN_MASK;
984 }
985 else
986 {
987 base->VAD0_SCONFIG &= ~PDM_VAD0_SCONFIG_VADSFILEN_MASK;
988 }
989 }
990
991 /*!
992 * @brief Configure voice activity detector signal filter.
993 *
994 * @param base PDM base pointer
995 * @param enableMaxBlock If signal maximum block enabled.
996 * @param signalGain Gain value for the signal energy.
997 */
998 void PDM_SetHwvadSignalFilterConfig(PDM_Type *base, bool enableMaxBlock, uint32_t signalGain);
999
1000 /*!
1001 * @brief Configure voice activity detector noise filter.
1002 *
1003 * @param base PDM base pointer
1004 * @param config Voice activity detector noise filter configure structure pointer .
1005 */
1006 void PDM_SetHwvadNoiseFilterConfig(PDM_Type *base, const pdm_hwvad_noise_filter_t *config);
1007
1008 /*!
1009 * @brief Enables/disables voice activity detector zero cross detector.
1010 *
1011 * @param base PDM base pointer
1012 * @param enable True means enable zero cross detector, false means disable.
1013 */
PDM_EnableHwvadZeroCrossDetector(PDM_Type * base,bool enable)1014 static inline void PDM_EnableHwvadZeroCrossDetector(PDM_Type *base, bool enable)
1015 {
1016 if (enable)
1017 {
1018 base->VAD0_ZCD |= PDM_VAD0_ZCD_VADZCDEN_MASK;
1019 }
1020 else
1021 {
1022 base->VAD0_ZCD &= ~PDM_VAD0_ZCD_VADZCDEN_MASK;
1023 }
1024 }
1025
1026 /*!
1027 * @brief Configure voice activity detector zero cross detector.
1028 *
1029 * @param base PDM base pointer
1030 * @param config Voice activity detector zero cross detector configure structure pointer .
1031 */
1032 void PDM_SetHwvadZeroCrossDetectorConfig(PDM_Type *base, const pdm_hwvad_zero_cross_detector_t *config);
1033
1034 /*!
1035 * @brief Reads noise data.
1036 *
1037 * @param base PDM base pointer.
1038 * @return Data in PDM noise data register.
1039 */
PDM_GetNoiseData(PDM_Type * base)1040 static inline uint16_t PDM_GetNoiseData(PDM_Type *base)
1041 {
1042 return (uint16_t)base->VAD0_NDATA;
1043 }
1044
1045 /*!
1046 * @brief set hwvad internal filter status .
1047 * Note: filter initial status should be asserted for two more cycles, then set it to normal operation.
1048 * @param base PDM base pointer.
1049 * @param status internal filter status.
1050 */
PDM_SetHwvadInternalFilterStatus(PDM_Type * base,pdm_hwvad_filter_status_t status)1051 static inline void PDM_SetHwvadInternalFilterStatus(PDM_Type *base, pdm_hwvad_filter_status_t status)
1052 {
1053 base->VAD0_CTRL_1 = (base->VAD0_CTRL_1 & (~PDM_VAD0_CTRL_1_VADST10_MASK)) | (uint32_t)status;
1054 }
1055
1056 /*!
1057 * @brief set HWVAD in envelope based mode .
1058 * Recommand configurations,
1059 * @code
1060 * static const pdm_hwvad_config_t hwvadConfig = {
1061 * .channel = 0,
1062 * .initializeTime = 10U,
1063 * .cicOverSampleRate = 0U,
1064 * .inputGain = 0U,
1065 * .frameTime = 10U,
1066 * .cutOffFreq = kPDM_HwvadHpfBypassed,
1067 * .enableFrameEnergy = false,
1068 * .enablePreFilter = true,
1069 };
1070
1071 * static const pdm_hwvad_noise_filter_t noiseFilterConfig = {
1072 * .enableAutoNoiseFilter = false,
1073 * .enableNoiseMin = true,
1074 * .enableNoiseDecimation = true,
1075 * .noiseFilterAdjustment = 0U,
1076 * .noiseGain = 7U,
1077 * .enableNoiseDetectOR = true,
1078 * };
1079 * @endcode
1080 * @param base PDM base pointer.
1081 * @param hwvadConfig internal filter status.
1082 * @param noiseConfig Voice activity detector noise filter configure structure pointer.
1083 * @param zcdConfig Voice activity detector zero cross detector configure structure pointer .
1084 * @param signalGain signal gain value.
1085 */
1086 void PDM_SetHwvadInEnvelopeBasedMode(PDM_Type *base,
1087 const pdm_hwvad_config_t *hwvadConfig,
1088 const pdm_hwvad_noise_filter_t *noiseConfig,
1089 const pdm_hwvad_zero_cross_detector_t *zcdConfig,
1090 uint32_t signalGain);
1091
1092 /*!
1093 * brief set HWVAD in energy based mode .
1094 * Recommand configurations,
1095 * code
1096 * static const pdm_hwvad_config_t hwvadConfig = {
1097 * .channel = 0,
1098 * .initializeTime = 10U,
1099 * .cicOverSampleRate = 0U,
1100 * .inputGain = 0U,
1101 * .frameTime = 10U,
1102 * .cutOffFreq = kPDM_HwvadHpfBypassed,
1103 * .enableFrameEnergy = true,
1104 * .enablePreFilter = true,
1105 };
1106
1107 * static const pdm_hwvad_noise_filter_t noiseFilterConfig = {
1108 * .enableAutoNoiseFilter = true,
1109 * .enableNoiseMin = false,
1110 * .enableNoiseDecimation = false,
1111 * .noiseFilterAdjustment = 0U,
1112 * .noiseGain = 7U,
1113 * .enableNoiseDetectOR = false,
1114 * };
1115 * code
1116 * param base PDM base pointer.
1117 * param hwvadConfig internal filter status.
1118 * param noiseConfig Voice activity detector noise filter configure structure pointer.
1119 * param zcdConfig Voice activity detector zero cross detector configure structure pointer .
1120 * param signalGain signal gain value, signal gain value should be properly according to application.
1121 */
1122 void PDM_SetHwvadInEnergyBasedMode(PDM_Type *base,
1123 const pdm_hwvad_config_t *hwvadConfig,
1124 const pdm_hwvad_noise_filter_t *noiseConfig,
1125 const pdm_hwvad_zero_cross_detector_t *zcdConfig,
1126 uint32_t signalGain);
1127
1128 /*!
1129 * @brief Enable/Disable hwvad callback.
1130
1131 * This function enable/disable the hwvad interrupt for the selected PDM peripheral.
1132 *
1133 * @param base Base address of the PDM peripheral.
1134 * @param vadCallback callback Pointer to store callback function, should be NULL when disable.
1135 * @param userData user data.
1136 * @param enable true is enable, false is disable.
1137 * @retval None.
1138 */
1139 void PDM_EnableHwvadInterruptCallback(PDM_Type *base, pdm_hwvad_callback_t vadCallback, void *userData, bool enable);
1140 /*! @} */
1141 #endif
1142
1143 /*!
1144 * @name Transactional
1145 * @{
1146 */
1147
1148 /*!
1149 * @brief Initializes the PDM handle.
1150 *
1151 * This function initializes the handle for the PDM transactional APIs. Call
1152 * this function once to get the handle initialized.
1153 *
1154 * @param base PDM base pointer.
1155 * @param handle PDM handle pointer.
1156 * @param callback Pointer to the user callback function.
1157 * @param userData User parameter passed to the callback function.
1158 */
1159 void PDM_TransferCreateHandle(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_callback_t callback, void *userData);
1160
1161 /*!
1162 * @brief PDM set channel transfer config.
1163 *
1164 * @param base PDM base pointer.
1165 * @param handle PDM handle pointer.
1166 * @param channel PDM channel.
1167 * @param config channel config.
1168 * @param format data format, support data width configurations,_pdm_data_width.
1169 * @retval kStatus_PDM_ChannelConfig_Failed or kStatus_Success.
1170 */
1171 status_t PDM_TransferSetChannelConfig(
1172 PDM_Type *base, pdm_handle_t *handle, uint32_t channel, const pdm_channel_config_t *config, uint32_t format);
1173
1174 /*!
1175 * @brief Performs an interrupt non-blocking receive transfer on PDM.
1176 *
1177 * @note This API returns immediately after the transfer initiates.
1178 * Call the PDM_RxGetTransferStatusIRQ to poll the transfer status and check whether
1179 * the transfer is finished. If the return status is not kStatus_PDM_Busy, the transfer
1180 * is finished.
1181 *
1182 * @param base PDM base pointer
1183 * @param handle Pointer to the pdm_handle_t structure which stores the transfer state.
1184 * @param xfer Pointer to the pdm_transfer_t structure.
1185 * @retval kStatus_Success Successfully started the data receive.
1186 * @retval kStatus_PDM_Busy Previous receive still not finished.
1187 */
1188 status_t PDM_TransferReceiveNonBlocking(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_t *xfer);
1189
1190 /*!
1191 * @brief Aborts the current IRQ receive.
1192 *
1193 * @note This API can be called when an interrupt non-blocking transfer initiates
1194 * to abort the transfer early.
1195 *
1196 * @param base PDM base pointer
1197 * @param handle Pointer to the pdm_handle_t structure which stores the transfer state.
1198 */
1199 void PDM_TransferAbortReceive(PDM_Type *base, pdm_handle_t *handle);
1200
1201 /*!
1202 * @brief Tx interrupt handler.
1203 *
1204 * @param base PDM base pointer.
1205 * @param handle Pointer to the pdm_handle_t structure.
1206 */
1207 void PDM_TransferHandleIRQ(PDM_Type *base, pdm_handle_t *handle);
1208
1209 /*! @} */
1210
1211 #if defined(__cplusplus)
1212 }
1213 #endif /*_cplusplus*/
1214
1215 /*! @} */
1216
1217 #endif /* FSL_PDM_H_ */
1218