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