2022-05-19 14:06:35 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018, Freescale Semiconductor, Inc.
|
|
|
|
* Copyright 2019-2020 NXP
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _FSL_PDM_H_
|
|
|
|
#define _FSL_PDM_H_
|
|
|
|
|
|
|
|
#include "fsl_common.h"
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @addtogroup pdm_driver PDM Driver
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Definitions
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/*! @name Driver version */
|
|
|
|
/*@{*/
|
2022-08-13 15:22:12 +08:00
|
|
|
#define FSL_PDM_DRIVER_VERSION (MAKE_VERSION(2, 7, 1)) /*!< Version 2.7.1 */
|
2022-05-19 14:06:35 +08:00
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
/*! @brief PDM XFER QUEUE SIZE */
|
|
|
|
#define PDM_XFER_QUEUE_SIZE (4U)
|
|
|
|
|
|
|
|
/*! @brief PDM return status*/
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
kStatus_PDM_Busy = MAKE_STATUS(kStatusGroup_PDM, 0), /*!< PDM is busy. */
|
|
|
|
#if (defined(FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ) && (FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ == 1U))
|
|
|
|
kStatus_PDM_CLK_LOW = MAKE_STATUS(kStatusGroup_PDM, 1), /*!< PDM clock frequency low */
|
|
|
|
#endif
|
|
|
|
kStatus_PDM_FIFO_ERROR = MAKE_STATUS(kStatusGroup_PDM, 2), /*!< PDM FIFO underrun or overflow */
|
|
|
|
kStatus_PDM_QueueFull = MAKE_STATUS(kStatusGroup_PDM, 3), /*!< PDM FIFO underrun or overflow */
|
|
|
|
kStatus_PDM_Idle = MAKE_STATUS(kStatusGroup_PDM, 4), /*!< PDM is idle */
|
|
|
|
kStatus_PDM_Output_ERROR = MAKE_STATUS(kStatusGroup_PDM, 5), /*!< PDM is output error */
|
|
|
|
kStatus_PDM_ChannelConfig_Failed = MAKE_STATUS(kStatusGroup_PDM, 6), /*!< PDM channel config failed */
|
|
|
|
kStatus_PDM_HWVAD_VoiceDetected = MAKE_STATUS(kStatusGroup_PDM, 7), /*!< PDM hwvad voice detected */
|
|
|
|
kStatus_PDM_HWVAD_Error = MAKE_STATUS(kStatusGroup_PDM, 8), /*!< PDM hwvad error */
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief The PDM interrupt enable flag */
|
|
|
|
enum _pdm_interrupt_enable
|
|
|
|
{
|
|
|
|
kPDM_ErrorInterruptEnable = PDM_CTRL_1_ERREN_MASK, /*!< PDM channel error interrupt enable. */
|
|
|
|
kPDM_FIFOInterruptEnable = PDM_CTRL_1_DISEL(2U), /*!< PDM channel FIFO interrupt */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief The PDM status */
|
|
|
|
enum _pdm_internal_status
|
|
|
|
{
|
|
|
|
kPDM_StatusDfBusyFlag = (int)PDM_STAT_BSY_FIL_MASK, /*!< Decimation filter is busy processing data */
|
|
|
|
kPDM_StatusFIRFilterReady = PDM_STAT_FIR_RDY_MASK, /*!< FIR filter data is ready */
|
|
|
|
#if (defined(FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ) && (FSL_FEATURE_PDM_HAS_STATUS_LOW_FREQ == 1U))
|
|
|
|
kPDM_StatusFrequencyLow = PDM_STAT_LOWFREQF_MASK, /*!< Mic app clock frequency not high enough */
|
|
|
|
#endif
|
|
|
|
kPDM_StatusCh0FifoDataAvaliable = PDM_STAT_CH0F_MASK, /*!< channel 0 fifo data reached watermark level */
|
|
|
|
kPDM_StatusCh1FifoDataAvaliable = PDM_STAT_CH1F_MASK, /*!< channel 1 fifo data reached watermark level */
|
|
|
|
kPDM_StatusCh2FifoDataAvaliable = PDM_STAT_CH2F_MASK, /*!< channel 2 fifo data reached watermark level */
|
|
|
|
kPDM_StatusCh3FifoDataAvaliable = PDM_STAT_CH3F_MASK, /*!< channel 3 fifo data reached watermark level */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_StatusCh4FifoDataAvaliable = PDM_STAT_CH4F_MASK, /*!< channel 4 fifo data reached watermark level */
|
|
|
|
kPDM_StatusCh5FifoDataAvaliable = PDM_STAT_CH5F_MASK, /*!< channel 5 fifo data reached watermark level */
|
|
|
|
kPDM_StatusCh6FifoDataAvaliable = PDM_STAT_CH6F_MASK, /*!< channel 6 fifo data reached watermark level */
|
|
|
|
kPDM_StatusCh7FifoDataAvaliable = PDM_STAT_CH7F_MASK, /*!< channel 7 fifo data reached watermark level */
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief PDM channel enable mask */
|
|
|
|
enum _pdm_channel_enable_mask
|
|
|
|
{
|
|
|
|
kPDM_EnableChannel0 = PDM_STAT_CH0F_MASK, /*!< channgel 0 enable mask */
|
|
|
|
kPDM_EnableChannel1 = PDM_STAT_CH1F_MASK, /*!< channgel 1 enable mask */
|
|
|
|
kPDM_EnableChannel2 = PDM_STAT_CH2F_MASK, /*!< channgel 2 enable mask */
|
|
|
|
kPDM_EnableChannel3 = PDM_STAT_CH3F_MASK, /*!< channgel 3 enable mask */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_EnableChannel4 = PDM_STAT_CH4F_MASK, /*!< channgel 4 enable mask */
|
|
|
|
kPDM_EnableChannel5 = PDM_STAT_CH5F_MASK, /*!< channgel 5 enable mask */
|
|
|
|
kPDM_EnableChannel6 = PDM_STAT_CH6F_MASK, /*!< channgel 6 enable mask */
|
|
|
|
kPDM_EnableChannel7 = PDM_STAT_CH7F_MASK, /*!< channgel 7 enable mask */
|
|
|
|
|
|
|
|
kPDM_EnableChannelAll = kPDM_EnableChannel0 | kPDM_EnableChannel1 | kPDM_EnableChannel2 | kPDM_EnableChannel3 |
|
|
|
|
kPDM_EnableChannel4 | kPDM_EnableChannel5 | kPDM_EnableChannel6 | kPDM_EnableChannel7,
|
|
|
|
#else
|
|
|
|
kPDM_EnableChannelAll = kPDM_EnableChannel0 | kPDM_EnableChannel1 | kPDM_EnableChannel2 | kPDM_EnableChannel3,
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief The PDM fifo status */
|
|
|
|
enum _pdm_fifo_status
|
|
|
|
{
|
|
|
|
kPDM_FifoStatusUnderflowCh0 = PDM_FIFO_STAT_FIFOUND0_MASK, /*!< channel0 fifo status underflow */
|
|
|
|
kPDM_FifoStatusUnderflowCh1 = PDM_FIFO_STAT_FIFOUND1_MASK, /*!< channel1 fifo status underflow */
|
|
|
|
kPDM_FifoStatusUnderflowCh2 = PDM_FIFO_STAT_FIFOUND2_MASK, /*!< channel2 fifo status underflow */
|
|
|
|
kPDM_FifoStatusUnderflowCh3 = PDM_FIFO_STAT_FIFOUND3_MASK, /*!< channel3 fifo status underflow */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_FifoStatusUnderflowCh4 = PDM_FIFO_STAT_FIFOUND4_MASK, /*!< channel4 fifo status underflow */
|
|
|
|
kPDM_FifoStatusUnderflowCh5 = PDM_FIFO_STAT_FIFOUND5_MASK, /*!< channel5 fifo status underflow */
|
|
|
|
kPDM_FifoStatusUnderflowCh6 = PDM_FIFO_STAT_FIFOUND6_MASK, /*!< channel6 fifo status underflow */
|
|
|
|
kPDM_FifoStatusUnderflowCh7 = PDM_FIFO_STAT_FIFOUND6_MASK, /*!< channel7 fifo status underflow */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
kPDM_FifoStatusOverflowCh0 = PDM_FIFO_STAT_FIFOOVF0_MASK, /*!< channel0 fifo status overflow */
|
|
|
|
kPDM_FifoStatusOverflowCh1 = PDM_FIFO_STAT_FIFOOVF1_MASK, /*!< channel1 fifo status overflow */
|
|
|
|
kPDM_FifoStatusOverflowCh2 = PDM_FIFO_STAT_FIFOOVF2_MASK, /*!< channel2 fifo status overflow */
|
|
|
|
kPDM_FifoStatusOverflowCh3 = PDM_FIFO_STAT_FIFOOVF3_MASK, /*!< channel3 fifo status overflow */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_FifoStatusOverflowCh4 = PDM_FIFO_STAT_FIFOOVF4_MASK, /*!< channel4 fifo status overflow */
|
|
|
|
kPDM_FifoStatusOverflowCh5 = PDM_FIFO_STAT_FIFOOVF5_MASK, /*!< channel5 fifo status overflow */
|
|
|
|
kPDM_FifoStatusOverflowCh6 = PDM_FIFO_STAT_FIFOOVF6_MASK, /*!< channel6 fifo status overflow */
|
|
|
|
kPDM_FifoStatusOverflowCh7 = PDM_FIFO_STAT_FIFOOVF7_MASK, /*!< channel7 fifo status overflow */
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
|
|
|
|
/*! @brief The PDM output status */
|
|
|
|
enum _pdm_range_status
|
|
|
|
{
|
|
|
|
kPDM_RangeStatusUnderFlowCh0 = PDM_RANGE_STAT_RANGEUNF0_MASK, /*!< channel0 range status underflow */
|
|
|
|
kPDM_RangeStatusUnderFlowCh1 = PDM_RANGE_STAT_RANGEUNF1_MASK, /*!< channel1 range status underflow */
|
|
|
|
kPDM_RangeStatusUnderFlowCh2 = PDM_RANGE_STAT_RANGEUNF2_MASK, /*!< channel2 range status underflow */
|
|
|
|
kPDM_RangeStatusUnderFlowCh3 = PDM_RANGE_STAT_RANGEUNF3_MASK, /*!< channel3 range status underflow */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_RangeStatusUnderFlowCh4 = PDM_RANGE_STAT_RANGEUNF4_MASK, /*!< channel4 range status underflow */
|
|
|
|
kPDM_RangeStatusUnderFlowCh5 = PDM_RANGE_STAT_RANGEUNF5_MASK, /*!< channel5 range status underflow */
|
|
|
|
kPDM_RangeStatusUnderFlowCh6 = PDM_RANGE_STAT_RANGEUNF6_MASK, /*!< channel6 range status underflow */
|
|
|
|
kPDM_RangeStatusUnderFlowCh7 = PDM_RANGE_STAT_RANGEUNF7_MASK, /*!< channel7 range status underflow */
|
|
|
|
#endif
|
|
|
|
kPDM_RangeStatusOverFlowCh0 = PDM_RANGE_STAT_RANGEOVF0_MASK, /*!< channel0 range status overflow */
|
|
|
|
kPDM_RangeStatusOverFlowCh1 = PDM_RANGE_STAT_RANGEOVF1_MASK, /*!< channel1 range status overflow */
|
|
|
|
kPDM_RangeStatusOverFlowCh2 = PDM_RANGE_STAT_RANGEOVF2_MASK, /*!< channel2 range status overflow */
|
|
|
|
kPDM_RangeStatusOverFlowCh3 = PDM_RANGE_STAT_RANGEOVF3_MASK, /*!< channel3 range status overflow */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_RangeStatusOverFlowCh4 = PDM_RANGE_STAT_RANGEOVF4_MASK, /*!< channel4 range status overflow */
|
|
|
|
kPDM_RangeStatusOverFlowCh5 = PDM_RANGE_STAT_RANGEOVF5_MASK, /*!< channel5 range status overflow */
|
|
|
|
kPDM_RangeStatusOverFlowCh6 = PDM_RANGE_STAT_RANGEOVF6_MASK, /*!< channel6 range status overflow */
|
|
|
|
kPDM_RangeStatusOverFlowCh7 = PDM_RANGE_STAT_RANGEOVF7_MASK, /*!< channel7 range status overflow */
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
/*! @brief The PDM output status */
|
|
|
|
enum _pdm_output_status
|
|
|
|
{
|
|
|
|
kPDM_OutputStatusUnderFlowCh0 = PDM_OUT_STAT_OUTUNF0_MASK, /*!< channel0 output status underflow */
|
|
|
|
kPDM_OutputStatusUnderFlowCh1 = PDM_OUT_STAT_OUTUNF1_MASK, /*!< channel1 output status underflow */
|
|
|
|
kPDM_OutputStatusUnderFlowCh2 = PDM_OUT_STAT_OUTUNF2_MASK, /*!< channel2 output status underflow */
|
|
|
|
kPDM_OutputStatusUnderFlowCh3 = PDM_OUT_STAT_OUTUNF3_MASK, /*!< channel3 output status underflow */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_OutputStatusUnderFlowCh4 = PDM_OUT_STAT_OUTUNF4_MASK, /*!< channel4 output status underflow */
|
|
|
|
kPDM_OutputStatusUnderFlowCh5 = PDM_OUT_STAT_OUTUNF5_MASK, /*!< channel5 output status underflow */
|
|
|
|
kPDM_OutputStatusUnderFlowCh6 = PDM_OUT_STAT_OUTUNF6_MASK, /*!< channel6 output status underflow */
|
|
|
|
kPDM_OutputStatusUnderFlowCh7 = PDM_OUT_STAT_OUTUNF7_MASK, /*!< channel7 output status underflow */
|
|
|
|
#endif
|
|
|
|
kPDM_OutputStatusOverFlowCh0 = PDM_OUT_STAT_OUTOVF0_MASK, /*!< channel0 output status overflow */
|
|
|
|
kPDM_OutputStatusOverFlowCh1 = PDM_OUT_STAT_OUTOVF1_MASK, /*!< channel1 output status overflow */
|
|
|
|
kPDM_OutputStatusOverFlowCh2 = PDM_OUT_STAT_OUTOVF2_MASK, /*!< channel2 output status overflow */
|
|
|
|
kPDM_OutputStatusOverFlowCh3 = PDM_OUT_STAT_OUTOVF3_MASK, /*!< channel3 output status overflow */
|
|
|
|
#if !defined(FSL_FEATURE_PDM_CHANNEL_NUM) || (FSL_FEATURE_PDM_CHANNEL_NUM == 8U)
|
|
|
|
kPDM_OutputStatusOverFlowCh4 = PDM_OUT_STAT_OUTOVF4_MASK, /*!< channel4 output status overflow */
|
|
|
|
kPDM_OutputStatusOverFlowCh5 = PDM_OUT_STAT_OUTOVF5_MASK, /*!< channel5 output status overflow */
|
|
|
|
kPDM_OutputStatusOverFlowCh6 = PDM_OUT_STAT_OUTOVF6_MASK, /*!< channel6 output status overflow */
|
|
|
|
kPDM_OutputStatusOverFlowCh7 = PDM_OUT_STAT_OUTOVF7_MASK, /*!< channel7 output status overflow */
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if (defined(FSL_FEATURE_PDM_HAS_DC_OUT_CTRL) && (FSL_FEATURE_PDM_HAS_DC_OUT_CTRL))
|
|
|
|
/*! @brief PDM DC remover configurations */
|
|
|
|
typedef enum _pdm_dc_remover
|
|
|
|
{
|
|
|
|
kPDM_DcRemoverCutOff20Hz = 0U, /*!< DC remover cut off 20HZ */
|
|
|
|
kPDM_DcRemoverCutOff13Hz = 1U, /*!< DC remover cut off 13.3HZ */
|
|
|
|
kPDM_DcRemoverCutOff40Hz = 2U, /*!< DC remover cut off 40HZ */
|
|
|
|
kPDM_DcRemoverBypass = 3U, /*!< DC remover bypass */
|
|
|
|
} pdm_dc_remover_t;
|
|
|
|
#else
|
|
|
|
/*! @brief PDM DC remover configurations */
|
|
|
|
typedef enum _pdm_dc_remover
|
|
|
|
{
|
|
|
|
kPDM_DcRemoverCutOff21Hz = 0U, /*!< DC remover cut off 21HZ */
|
|
|
|
kPDM_DcRemoverCutOff83Hz = 1U, /*!< DC remover cut off 83HZ */
|
|
|
|
kPDM_DcRemoverCutOff152Hz = 2U, /*!< DC remover cut off 152HZ */
|
|
|
|
kPDM_DcRemoverBypass = 3U, /*!< DC remover bypass */
|
|
|
|
} pdm_dc_remover_t;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*! @brief PDM decimation filter quality mode */
|
|
|
|
typedef enum _pdm_df_quality_mode
|
|
|
|
{
|
|
|
|
kPDM_QualityModeMedium = 0U, /*!< quality mode memdium */
|
|
|
|
kPDM_QualityModeHigh = 1U, /*!< quality mode high */
|
|
|
|
kPDM_QualityModeLow = 7U, /*!< quality mode low */
|
|
|
|
kPDM_QualityModeVeryLow0 = 6U, /*!< quality mode very low0 */
|
|
|
|
kPDM_QualityModeVeryLow1 = 5U, /*!< quality mode very low1 */
|
|
|
|
kPDM_QualityModeVeryLow2 = 4U, /*!< quality mode very low2 */
|
|
|
|
} pdm_df_quality_mode_t;
|
|
|
|
|
|
|
|
/*! @brief PDM quality mode K factor */
|
|
|
|
enum _pdm_qulaity_mode_k_factor
|
|
|
|
{
|
|
|
|
kPDM_QualityModeHighKFactor = 1U, /*!< high quality mode K factor = 1 / 2 */
|
|
|
|
kPDM_QualityModeMediumKFactor = 2U, /*!< medium/very low0 quality mode K factor = 2 / 2 */
|
|
|
|
kPDM_QualityModeLowKFactor = 4U, /*!< low/very low1 quality mode K factor = 4 / 2 */
|
|
|
|
kPDM_QualityModeVeryLow2KFactor = 8U, /*!< very low2 quality mode K factor = 8 / 2 */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief PDM decimation filter output gain */
|
|
|
|
typedef enum _pdm_df_output_gain
|
|
|
|
{
|
|
|
|
kPDM_DfOutputGain0 = 0U, /*!< Decimation filter output gain 0 */
|
|
|
|
kPDM_DfOutputGain1 = 1U, /*!< Decimation filter output gain 1 */
|
|
|
|
kPDM_DfOutputGain2 = 2U, /*!< Decimation filter output gain 2 */
|
|
|
|
kPDM_DfOutputGain3 = 3U, /*!< Decimation filter output gain 3 */
|
|
|
|
kPDM_DfOutputGain4 = 4U, /*!< Decimation filter output gain 4 */
|
|
|
|
kPDM_DfOutputGain5 = 5U, /*!< Decimation filter output gain 5 */
|
|
|
|
kPDM_DfOutputGain6 = 6U, /*!< Decimation filter output gain 6 */
|
|
|
|
kPDM_DfOutputGain7 = 7U, /*!< Decimation filter output gain 7 */
|
|
|
|
kPDM_DfOutputGain8 = 8U, /*!< Decimation filter output gain 8 */
|
|
|
|
kPDM_DfOutputGain9 = 9U, /*!< Decimation filter output gain 9 */
|
|
|
|
kPDM_DfOutputGain10 = 0xAU, /*!< Decimation filter output gain 10 */
|
|
|
|
kPDM_DfOutputGain11 = 0xBU, /*!< Decimation filter output gain 11 */
|
|
|
|
kPDM_DfOutputGain12 = 0xCU, /*!< Decimation filter output gain 12 */
|
|
|
|
kPDM_DfOutputGain13 = 0xDU, /*!< Decimation filter output gain 13 */
|
|
|
|
kPDM_DfOutputGain14 = 0xEU, /*!< Decimation filter output gain 14 */
|
|
|
|
kPDM_DfOutputGain15 = 0xFU, /*!< Decimation filter output gain 15 */
|
|
|
|
} pdm_df_output_gain_t;
|
|
|
|
|
|
|
|
/*! @brief PDM data width */
|
|
|
|
enum _pdm_data_width
|
|
|
|
{
|
|
|
|
#if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH != 2U)
|
|
|
|
kPDM_DataWwidth24 = 3U, /*!< PDM data width 24bit */
|
|
|
|
kPDM_DataWwidth32 = 4U, /*!< PDM data width 32bit */
|
|
|
|
#else
|
|
|
|
kPDM_DataWdith16 = 2U, /*!< PDM data width 16bit */
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief PDM channel configurations */
|
|
|
|
typedef struct _pdm_channel_config
|
|
|
|
{
|
|
|
|
#if (defined(FSL_FEATURE_PDM_HAS_DC_OUT_CTRL) && (FSL_FEATURE_PDM_HAS_DC_OUT_CTRL))
|
|
|
|
pdm_dc_remover_t outputCutOffFreq; /*!< PDM output DC remover cut off frequency */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !(defined(FSL_FEATURE_PDM_DC_CTRL_VALUE_FIXED) && (FSL_FEATURE_PDM_DC_CTRL_VALUE_FIXED))
|
|
|
|
pdm_dc_remover_t cutOffFreq; /*!< DC remover cut off frequency */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pdm_df_output_gain_t gain; /*!< Decimation Filter Output Gain */
|
|
|
|
} pdm_channel_config_t;
|
|
|
|
|
|
|
|
/*! @brief PDM user configuration structure */
|
|
|
|
typedef struct _pdm_config
|
|
|
|
{
|
|
|
|
bool
|
|
|
|
enableDoze; /*!< This module will enter disable/low leakage mode if DOZEN is active with ipg_doze is asserted */
|
|
|
|
uint8_t fifoWatermark; /*!< Watermark value for FIFO */
|
|
|
|
pdm_df_quality_mode_t qualityMode; /*!< Quality mode */
|
|
|
|
uint8_t cicOverSampleRate; /*!< CIC filter over sampling rate */
|
|
|
|
} pdm_config_t;
|
|
|
|
|
|
|
|
/*! @brief PDM voice activity detector interrupt type */
|
|
|
|
enum _pdm_hwvad_interrupt_enable
|
|
|
|
{
|
|
|
|
kPDM_HwvadErrorInterruptEnable = PDM_VAD0_CTRL_1_VADERIE_MASK, /*!< PDM channel HWVAD error interrupt enable. */
|
|
|
|
kPDM_HwvadInterruptEnable = PDM_VAD0_CTRL_1_VADIE_MASK, /*!< PDM channel HWVAD interrupt */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief The PDM hwvad interrupt status flag */
|
|
|
|
enum _pdm_hwvad_int_status
|
|
|
|
{
|
|
|
|
kPDM_HwvadStatusInputSaturation = PDM_VAD0_STAT_VADINSATF_MASK, /*!< HWVAD saturation condition */
|
|
|
|
kPDM_HwvadStatusVoiceDetectFlag = PDM_VAD0_STAT_VADIF_MASK, /*!< HWVAD voice detect interrupt triggered */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! @brief High pass filter configure cut-off frequency*/
|
|
|
|
typedef enum _pdm_hwvad_hpf_config
|
|
|
|
{
|
|
|
|
kPDM_HwvadHpfBypassed = 0x0U, /*!< High-pass filter bypass */
|
|
|
|
kPDM_HwvadHpfCutOffFreq1750Hz = 0x1U, /*!< High-pass filter cut off frequency 1750HZ */
|
|
|
|
kPDM_HwvadHpfCutOffFreq215Hz = 0x2U, /*!< High-pass filter cut off frequency 215HZ */
|
|
|
|
kPDM_HwvadHpfCutOffFreq102Hz = 0x3U, /*!< High-pass filter cut off frequency 102HZ */
|
|
|
|
} pdm_hwvad_hpf_config_t;
|
|
|
|
|
|
|
|
/*! @brief HWVAD internal filter status */
|
|
|
|
typedef enum _pdm_hwvad_filter_status
|
|
|
|
{
|
|
|
|
kPDM_HwvadInternalFilterNormalOperation = 0U, /*!< internal filter ready for normal operation */
|
|
|
|
kPDM_HwvadInternalFilterInitial = PDM_VAD0_CTRL_1_VADST10_MASK, /*!< interla filter are initial */
|
|
|
|
} pdm_hwvad_filter_status_t;
|
|
|
|
|
|
|
|
/*! @brief PDM voice activity detector user configuration structure */
|
|
|
|
typedef struct _pdm_hwvad_config
|
|
|
|
{
|
|
|
|
uint8_t channel; /*!< Which channel uses voice activity detector */
|
|
|
|
uint8_t initializeTime; /*!< Number of frames or samples to initialize voice activity detector. */
|
|
|
|
uint8_t cicOverSampleRate; /*!< CIC filter over sampling rate */
|
|
|
|
|
|
|
|
uint8_t inputGain; /*!< Voice activity detector input gain */
|
|
|
|
uint32_t frameTime; /*!< Voice activity frame time */
|
|
|
|
pdm_hwvad_hpf_config_t cutOffFreq; /*!< High pass filter cut off frequency */
|
|
|
|
bool enableFrameEnergy; /*!< If frame energy enabled, true means enable */
|
|
|
|
bool enablePreFilter; /*!< If pre-filter enabled */
|
|
|
|
} pdm_hwvad_config_t;
|
|
|
|
|
|
|
|
/*! @brief PDM voice activity detector noise filter user configuration structure */
|
|
|
|
typedef struct _pdm_hwvad_noise_filter
|
|
|
|
{
|
|
|
|
bool enableAutoNoiseFilter; /*!< If noise fileter automatically activated, true means enable */
|
|
|
|
bool enableNoiseMin; /*!< If Noise minimum block enabled, true means enabled */
|
|
|
|
bool enableNoiseDecimation; /*!< If enable noise input decimation */
|
|
|
|
bool enableNoiseDetectOR; /*!< Enables a OR logic in the output of minimum noise estimator block */
|
|
|
|
uint32_t noiseFilterAdjustment; /*!< The adjustment value of the noise filter */
|
|
|
|
uint32_t noiseGain; /*!< Gain value for the noise energy or envelope estimated */
|
|
|
|
} pdm_hwvad_noise_filter_t;
|
|
|
|
|
|
|
|
/*! @brief PDM voice activity detector zero cross detector result */
|
|
|
|
typedef enum _pdm_hwvad_zcd_result
|
|
|
|
{
|
|
|
|
kPDM_HwvadResultOREnergyBasedDetection =
|
|
|
|
0U, /*!< zero cross detector result will be OR with energy based detection */
|
|
|
|
kPDM_HwvadResultANDEnergyBasedDetection =
|
|
|
|
1U, /*!< zero cross detector result will be AND with energy based detection */
|
|
|
|
} pdm_hwvad_zcd_result_t;
|
|
|
|
|
|
|
|
/*! @brief PDM voice activity detector zero cross detector configuration structure */
|
|
|
|
typedef struct _pdm_hwvad_zero_cross_detector
|
|
|
|
{
|
|
|
|
bool enableAutoThreshold; /*!< If ZCD auto-threshold enabled, true means enabled. */
|
|
|
|
pdm_hwvad_zcd_result_t zcdAnd; /*!< Is ZCD result is AND'ed with energy-based detection, false means OR'ed */
|
|
|
|
uint32_t threshold; /*!< The adjustment value of the noise filter */
|
|
|
|
uint32_t adjustmentThreshold; /*!< Gain value for the noise energy or envelope estimated */
|
|
|
|
} pdm_hwvad_zero_cross_detector_t;
|
|
|
|
|
|
|
|
/*! @brief PDM SDMA transfer structure */
|
|
|
|
typedef struct _pdm_transfer
|
|
|
|
{
|
|
|
|
volatile uint8_t *data; /*!< Data start address to transfer. */
|
|
|
|
volatile size_t dataSize; /*!< Total Transfer bytes size. */
|
|
|
|
} pdm_transfer_t;
|
|
|
|
|
|
|
|
/*! @brief PDM handle */
|
|
|
|
typedef struct _pdm_handle pdm_handle_t;
|
|
|
|
|
|
|
|
/*! @brief PDM transfer callback prototype */
|
|
|
|
typedef void (*pdm_transfer_callback_t)(PDM_Type *base, pdm_handle_t *handle, status_t status, void *userData);
|
|
|
|
|
|
|
|
/*! @brief PDM HWVAD callback prototype */
|
|
|
|
typedef void (*pdm_hwvad_callback_t)(status_t status, void *userData);
|
|
|
|
/*! @brief PDM HWVAD notification structure */
|
|
|
|
typedef struct _pdm_hwvad_notification
|
|
|
|
{
|
|
|
|
pdm_hwvad_callback_t callback;
|
|
|
|
void *userData;
|
|
|
|
} pdm_hwvad_notification_t;
|
|
|
|
|
|
|
|
/*! @brief PDM handle structure */
|
|
|
|
struct _pdm_handle
|
|
|
|
{
|
|
|
|
uint32_t state; /*!< Transfer status */
|
|
|
|
pdm_transfer_callback_t callback; /*!< Callback function called at transfer event*/
|
|
|
|
void *userData; /*!< Callback parameter passed to callback function*/
|
|
|
|
|
|
|
|
pdm_transfer_t pdmQueue[PDM_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
|
|
|
|
size_t transferSize[PDM_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
|
|
|
|
volatile uint8_t queueUser; /*!< Index for user to queue transfer */
|
|
|
|
volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
|
|
|
|
|
|
|
|
uint32_t format; /*!< data format */
|
|
|
|
uint8_t watermark; /*!< Watermark value */
|
|
|
|
uint8_t startChannel; /*!< end channel */
|
|
|
|
uint8_t channelNums; /*!< Enabled channel number */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* API
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#if defined(__cplusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif /*_cplusplus*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name Initialization and deinitialization
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Initializes the PDM peripheral.
|
|
|
|
*
|
|
|
|
* Ungates the PDM clock, resets the module, and configures PDM with a configuration structure.
|
|
|
|
* The configuration structure can be custom filled or set with default values by
|
|
|
|
* PDM_GetDefaultConfig().
|
|
|
|
*
|
|
|
|
* @note This API should be called at the beginning of the application to use
|
|
|
|
* the PDM driver. Otherwise, accessing the PDM module can cause a hard fault
|
|
|
|
* because the clock is not enabled.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param config PDM configuration structure.
|
|
|
|
*/
|
|
|
|
void PDM_Init(PDM_Type *base, const pdm_config_t *config);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief De-initializes the PDM peripheral.
|
|
|
|
*
|
|
|
|
* This API gates the PDM clock. The PDM module can't operate unless PDM_Init
|
|
|
|
* is called to enable the clock.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
*/
|
|
|
|
void PDM_Deinit(PDM_Type *base);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Resets the PDM module.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
*/
|
|
|
|
static inline void PDM_Reset(PDM_Type *base)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= PDM_CTRL_1_SRES_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables PDM interface.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means PDM interface is enabled, false means PDM interface is disabled.
|
|
|
|
*/
|
|
|
|
static inline void PDM_Enable(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= PDM_CTRL_1_PDMIEN_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~PDM_CTRL_1_PDMIEN_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables DOZE.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means the module will enter Disable/Low Leakage mode when ipg_doze is asserted, false means the
|
|
|
|
* module will not enter Disable/Low Leakage mode when ipg_doze is asserted.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableDoze(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= PDM_CTRL_1_DOZEN_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~PDM_CTRL_1_DOZEN_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables debug mode for PDM.
|
|
|
|
* The PDM interface cannot enter debug mode once in Disable/Low Leakage or Low Power mode.
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means PDM interface enter debug mode, false means PDM interface in normal mode.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableDebugMode(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= PDM_CTRL_1_DBG_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~PDM_CTRL_1_DBG_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables PDM interface in debug mode.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means PDM interface is enabled debug mode, false means PDM interface is disabled after
|
|
|
|
* after completing the current frame in debug mode.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableInDebugMode(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= PDM_CTRL_1_DBGE_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~PDM_CTRL_1_DBGE_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables PDM interface disable/Low Leakage mode.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means PDM interface is in disable/low leakage mode, False means PDM interface is in normal mode.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnterLowLeakageMode(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= PDM_CTRL_1_MDIS_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~PDM_CTRL_1_MDIS_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables the PDM channel.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param channel PDM channel number need to enable or disable.
|
|
|
|
* @param enable True means enable PDM channel, false means disable.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableChannel(PDM_Type *base, uint8_t channel, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 |= (1UL << channel);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~(1UL << channel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM one channel configurations.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param config PDM channel configurations.
|
|
|
|
* @param channel channel number.
|
|
|
|
* after completing the current frame in debug mode.
|
|
|
|
*/
|
|
|
|
void PDM_SetChannelConfig(PDM_Type *base, uint32_t channel, const pdm_channel_config_t *config);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM set sample rate.
|
|
|
|
*
|
|
|
|
* @note This function is depend on the configuration of the PDM and PDM channel, so the correct call sequence is
|
|
|
|
* @code
|
|
|
|
* PDM_Init(base, pdmConfig)
|
|
|
|
* PDM_SetChannelConfig(base, channel, &channelConfig)
|
|
|
|
* PDM_SetSampleRateConfig(base, source, sampleRate)
|
|
|
|
* @endcode
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param sourceClock_HZ PDM source clock frequency.
|
|
|
|
* @param sampleRate_HZ PDM sample rate.
|
|
|
|
*/
|
|
|
|
status_t PDM_SetSampleRateConfig(PDM_Type *base, uint32_t sourceClock_HZ, uint32_t sampleRate_HZ);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM set sample rate.
|
|
|
|
*
|
|
|
|
* @deprecated Do not use this function. It has been superceded by @ref PDM_SetSampleRateConfig
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enableChannelMask PDM channel enable mask.
|
|
|
|
* @param qualityMode quality mode.
|
|
|
|
* @param osr cic oversample rate
|
|
|
|
* @param clkDiv clock divider
|
|
|
|
*/
|
|
|
|
status_t PDM_SetSampleRate(
|
|
|
|
PDM_Type *base, uint32_t enableChannelMask, pdm_df_quality_mode_t qualityMode, uint8_t osr, uint32_t clkDiv);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Get the instance number for PDM.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
*/
|
|
|
|
uint32_t PDM_GetInstance(PDM_Type *base);
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name Status
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Gets the PDM internal status flag.
|
|
|
|
* Use the Status Mask in _pdm_internal_status to get the status value needed
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return PDM status flag value.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetStatus(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->STAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Gets the PDM FIFO status flag.
|
|
|
|
* Use the Status Mask in _pdm_fifo_status to get the status value needed
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return FIFO status.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetFifoStatus(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->FIFO_STAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
|
|
|
|
/*!
|
|
|
|
* @brief Gets the PDM Range status flag.
|
|
|
|
* Use the Status Mask in _pdm_range_status to get the status value needed
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return output status.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetRangeStatus(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->RANGE_STAT;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/*!
|
|
|
|
* @brief Gets the PDM output status flag.
|
|
|
|
* Use the Status Mask in _pdm_output_status to get the status value needed
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return output status.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetOutputStatus(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->OUT_STAT;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Clears the PDM Tx status.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask State mask. It can be a combination of the status between kPDM_StatusFrequencyLow and
|
|
|
|
* kPDM_StatusCh7FifoDataAvaliable.
|
|
|
|
*/
|
|
|
|
static inline void PDM_ClearStatus(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->STAT = mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Clears the PDM Tx status.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask State mask.It can be a combination of the status in _pdm_fifo_status.
|
|
|
|
*/
|
|
|
|
static inline void PDM_ClearFIFOStatus(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->FIFO_STAT = mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_PDM_HAS_RANGE_CTRL) && FSL_FEATURE_PDM_HAS_RANGE_CTRL
|
|
|
|
/*!
|
|
|
|
* @brief Clears the PDM range status.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask State mask. It can be a combination of the status in _pdm_range_status.
|
|
|
|
*/
|
|
|
|
static inline void PDM_ClearRangeStatus(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->RANGE_STAT = mask;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/*!
|
|
|
|
* @brief Clears the PDM output status.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask State mask. It can be a combination of the status in _pdm_output_status.
|
|
|
|
*/
|
|
|
|
static inline void PDM_ClearOutputStatus(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->OUT_STAT = mask;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name Interrupts
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables the PDM interrupt requests.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask interrupt source
|
|
|
|
* The parameter can be a combination of the following sources if defined.
|
|
|
|
* @arg kPDM_ErrorInterruptEnable
|
|
|
|
* @arg kPDM_FIFOInterruptEnable
|
|
|
|
*/
|
|
|
|
void PDM_EnableInterrupts(PDM_Type *base, uint32_t mask);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Disables the PDM interrupt requests.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask interrupt source
|
|
|
|
* The parameter can be a combination of the following sources if defined.
|
|
|
|
* @arg kPDM_ErrorInterruptEnable
|
|
|
|
* @arg kPDM_FIFOInterruptEnable
|
|
|
|
*/
|
|
|
|
static inline void PDM_DisableInterrupts(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name DMA Control
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables the PDM DMA requests.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means enable DMA, false means disable DMA.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableDMA(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->CTRL_1 = (base->CTRL_1 & (~PDM_CTRL_1_DISEL_MASK)) | PDM_CTRL_1_DISEL(0x1U);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->CTRL_1 &= ~PDM_CTRL_1_DISEL_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Gets the PDM data register address.
|
|
|
|
*
|
|
|
|
* This API is used to provide a transfer address for the PDM DMA transfer configuration.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param channel Which data channel used.
|
|
|
|
* @return data register address.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetDataRegisterAddress(PDM_Type *base, uint32_t channel)
|
|
|
|
{
|
|
|
|
return (uint32_t)(&(base->DATACH)[channel]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name Bus Operations
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
#if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 2U)
|
|
|
|
/*!
|
|
|
|
* @brief Reads data from the PDM FIFO.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param channel Data channel used.
|
|
|
|
* @return Data in PDM FIFO.
|
|
|
|
*/
|
|
|
|
static inline int16_t PDM_ReadData(PDM_Type *base, uint32_t channel)
|
|
|
|
{
|
|
|
|
return (int16_t)(base->DATACH[channel]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM read data non blocking.
|
|
|
|
* So the actually read data byte size in this function is (size * 2 * channelNums).
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param startChannel start channel number.
|
|
|
|
* @param channelNums total enabled channelnums.
|
|
|
|
* @param buffer received buffer address.
|
|
|
|
* @param size number of 16bit data to read.
|
|
|
|
*/
|
|
|
|
void PDM_ReadNonBlocking(PDM_Type *base, uint32_t startChannel, uint32_t channelNums, int16_t *buffer, size_t size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM read fifo.
|
|
|
|
* @note: This function support 16 bit only for IP version that only supports 16bit.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param startChannel start channel number.
|
|
|
|
* @param channelNums total enabled channelnums.
|
|
|
|
* @param buffer received buffer address.
|
|
|
|
* @param size number of samples to read.
|
|
|
|
* @param dataWidth sample width.
|
|
|
|
*/
|
|
|
|
void PDM_ReadFifo(
|
|
|
|
PDM_Type *base, uint32_t startChannel, uint32_t channelNums, void *buffer, size_t size, uint32_t dataWidth);
|
|
|
|
|
|
|
|
#if defined(FSL_FEATURE_PDM_FIFO_WIDTH) && (FSL_FEATURE_PDM_FIFO_WIDTH == 4U)
|
|
|
|
/*!
|
|
|
|
* @brief Reads data from the PDM FIFO.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param channel Data channel used.
|
|
|
|
* @return Data in PDM FIFO.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_ReadData(PDM_Type *base, uint32_t channel)
|
|
|
|
{
|
|
|
|
return base->DATACH[channel];
|
|
|
|
}
|
|
|
|
#endif
|
2022-08-13 15:22:12 +08:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Set the PDM channel gain.
|
|
|
|
*
|
|
|
|
* Please note for different quality mode, the valid gain value is different, reference RM for detail.
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param channel PDM channel index.
|
|
|
|
* @param gain channel gain, the register gain value range is 0 - 15.
|
|
|
|
*/
|
|
|
|
void PDM_SetChannelGain(PDM_Type *base, uint32_t channel, pdm_df_output_gain_t gain);
|
|
|
|
|
2022-05-19 14:06:35 +08:00
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name Voice Activity Detector
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Configure voice activity detector.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param config Voice activity detector configure structure pointer .
|
|
|
|
*/
|
|
|
|
void PDM_SetHwvadConfig(PDM_Type *base, const pdm_hwvad_config_t *config);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM hwvad force output disable.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable true is output force disable, false is output not force.
|
|
|
|
*/
|
|
|
|
static inline void PDM_ForceHwvadOutputDisable(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_2 &= ~PDM_VAD0_CTRL_2_VADFOUTDIS_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_2 |= PDM_VAD0_CTRL_2_VADFOUTDIS_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM hwvad reset.
|
|
|
|
* It will reset VADNDATA register and will clean all internal buffers, should be called when the PDM isn't running.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
*/
|
|
|
|
static inline void PDM_ResetHwvad(PDM_Type *base)
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_1 |= PDM_VAD0_CTRL_1_VADRST_MASK;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief Enable/Disable Voice activity detector.
|
|
|
|
* Should be called when the PDM isn't running.
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param enable True means enable voice activity detector, false means disable.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableHwvad(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_1 |= PDM_VAD0_CTRL_1_VADEN_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_1 &= ~PDM_VAD0_CTRL_1_VADEN_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables the PDM Voice Detector interrupt requests.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask interrupt source
|
|
|
|
* The parameter can be a combination of the following sources if defined.
|
|
|
|
* @arg kPDM_HWVADErrorInterruptEnable
|
|
|
|
* @arg kPDM_HWVADInterruptEnable
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableHwvadInterrupts(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_1 |= mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Disables the PDM Voice Detector interrupt requests.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask interrupt source
|
|
|
|
* The parameter can be a combination of the following sources if defined.
|
|
|
|
* @arg kPDM_HWVADErrorInterruptEnable
|
|
|
|
* @arg kPDM_HWVADInterruptEnable
|
|
|
|
*/
|
|
|
|
static inline void PDM_DisableHwvadInterrupts(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_1 &= ~mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Clears the PDM voice activity detector status flags.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param mask State mask,reference _pdm_hwvad_int_status.
|
|
|
|
*/
|
|
|
|
static inline void PDM_ClearHwvadInterruptStatusFlags(PDM_Type *base, uint32_t mask)
|
|
|
|
{
|
|
|
|
base->VAD0_STAT = mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Clears the PDM voice activity detector status flags.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return status, reference _pdm_hwvad_int_status
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetHwvadInterruptStatusFlags(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->VAD0_STAT & (PDM_VAD0_STAT_VADIF_MASK | PDM_VAD0_STAT_VADINSATF_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Get the PDM voice activity detector initial flags.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return initial flag.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetHwvadInitialFlag(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->VAD0_STAT & PDM_VAD0_STAT_VADINITF_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Get the PDM voice activity detector voice detected flags.
|
|
|
|
* NOte: this flag is auto cleared when voice gone.
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @return voice detected flag.
|
|
|
|
*/
|
|
|
|
static inline uint32_t PDM_GetHwvadVoiceDetectedFlag(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return base->VAD0_STAT & PDM_VAD0_STAT_VADEF_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables voice activity detector signal filter.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means enable signal filter, false means disable.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableHwvadSignalFilter(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->VAD0_SCONFIG |= PDM_VAD0_SCONFIG_VADSFILEN_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->VAD0_SCONFIG &= ~PDM_VAD0_SCONFIG_VADSFILEN_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Configure voice activity detector signal filter.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enableMaxBlock If signal maximum block enabled.
|
|
|
|
* @param signalGain Gain value for the signal energy.
|
|
|
|
*/
|
|
|
|
void PDM_SetHwvadSignalFilterConfig(PDM_Type *base, bool enableMaxBlock, uint32_t signalGain);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Configure voice activity detector noise filter.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param config Voice activity detector noise filter configure structure pointer .
|
|
|
|
*/
|
|
|
|
void PDM_SetHwvadNoiseFilterConfig(PDM_Type *base, const pdm_hwvad_noise_filter_t *config);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enables/disables voice activity detector zero cross detector.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param enable True means enable zero cross detector, false means disable.
|
|
|
|
*/
|
|
|
|
static inline void PDM_EnableHwvadZeroCrossDetector(PDM_Type *base, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
base->VAD0_ZCD |= PDM_VAD0_ZCD_VADZCDEN_MASK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base->VAD0_ZCD &= ~PDM_VAD0_ZCD_VADZCDEN_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Configure voice activity detector zero cross detector.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param config Voice activity detector zero cross detector configure structure pointer .
|
|
|
|
*/
|
|
|
|
void PDM_SetHwvadZeroCrossDetectorConfig(PDM_Type *base, const pdm_hwvad_zero_cross_detector_t *config);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Reads noise data.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @return Data in PDM noise data register.
|
|
|
|
*/
|
|
|
|
static inline uint16_t PDM_GetNoiseData(PDM_Type *base)
|
|
|
|
{
|
|
|
|
return (uint16_t)base->VAD0_NDATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief set hwvad internal filter status .
|
|
|
|
* Note: filter initial status should be asserted for two more cycles, then set it to normal operation.
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param status internal filter status.
|
|
|
|
*/
|
|
|
|
static inline void PDM_SetHwvadInternalFilterStatus(PDM_Type *base, pdm_hwvad_filter_status_t status)
|
|
|
|
{
|
|
|
|
base->VAD0_CTRL_1 = (base->VAD0_CTRL_1 & (~PDM_VAD0_CTRL_1_VADST10_MASK)) | (uint32_t)status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief set HWVAD in envelope based mode .
|
|
|
|
* Recommand configurations,
|
|
|
|
* @code
|
|
|
|
* static const pdm_hwvad_config_t hwvadConfig = {
|
|
|
|
* .channel = 0,
|
|
|
|
* .initializeTime = 10U,
|
|
|
|
* .cicOverSampleRate = 0U,
|
|
|
|
* .inputGain = 0U,
|
|
|
|
* .frameTime = 10U,
|
|
|
|
* .cutOffFreq = kPDM_HwvadHpfBypassed,
|
|
|
|
* .enableFrameEnergy = false,
|
|
|
|
* .enablePreFilter = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
* static const pdm_hwvad_noise_filter_t noiseFilterConfig = {
|
|
|
|
* .enableAutoNoiseFilter = false,
|
|
|
|
* .enableNoiseMin = true,
|
|
|
|
* .enableNoiseDecimation = true,
|
|
|
|
* .noiseFilterAdjustment = 0U,
|
|
|
|
* .noiseGain = 7U,
|
|
|
|
* .enableNoiseDetectOR = true,
|
|
|
|
* };
|
|
|
|
* @endcode
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param hwvadConfig internal filter status.
|
|
|
|
* @param noiseConfig Voice activity detector noise filter configure structure pointer.
|
|
|
|
* @param zcdConfig Voice activity detector zero cross detector configure structure pointer .
|
|
|
|
* @param signalGain signal gain value.
|
|
|
|
*/
|
|
|
|
void PDM_SetHwvadInEnvelopeBasedMode(PDM_Type *base,
|
|
|
|
const pdm_hwvad_config_t *hwvadConfig,
|
|
|
|
const pdm_hwvad_noise_filter_t *noiseConfig,
|
|
|
|
const pdm_hwvad_zero_cross_detector_t *zcdConfig,
|
|
|
|
uint32_t signalGain);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* brief set HWVAD in energy based mode .
|
|
|
|
* Recommand configurations,
|
|
|
|
* code
|
|
|
|
* static const pdm_hwvad_config_t hwvadConfig = {
|
|
|
|
* .channel = 0,
|
|
|
|
* .initializeTime = 10U,
|
|
|
|
* .cicOverSampleRate = 0U,
|
|
|
|
* .inputGain = 0U,
|
|
|
|
* .frameTime = 10U,
|
|
|
|
* .cutOffFreq = kPDM_HwvadHpfBypassed,
|
|
|
|
* .enableFrameEnergy = true,
|
|
|
|
* .enablePreFilter = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
* static const pdm_hwvad_noise_filter_t noiseFilterConfig = {
|
|
|
|
* .enableAutoNoiseFilter = true,
|
|
|
|
* .enableNoiseMin = false,
|
|
|
|
* .enableNoiseDecimation = false,
|
|
|
|
* .noiseFilterAdjustment = 0U,
|
|
|
|
* .noiseGain = 7U,
|
|
|
|
* .enableNoiseDetectOR = false,
|
|
|
|
* };
|
|
|
|
* code
|
|
|
|
* param base PDM base pointer.
|
|
|
|
* param hwvadConfig internal filter status.
|
|
|
|
* param noiseConfig Voice activity detector noise filter configure structure pointer.
|
|
|
|
* param zcdConfig Voice activity detector zero cross detector configure structure pointer .
|
|
|
|
* param signalGain signal gain value, signal gain value should be properly according to application.
|
|
|
|
*/
|
|
|
|
void PDM_SetHwvadInEnergyBasedMode(PDM_Type *base,
|
|
|
|
const pdm_hwvad_config_t *hwvadConfig,
|
|
|
|
const pdm_hwvad_noise_filter_t *noiseConfig,
|
|
|
|
const pdm_hwvad_zero_cross_detector_t *zcdConfig,
|
|
|
|
uint32_t signalGain);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Enable/Disable hwvad callback.
|
|
|
|
|
|
|
|
* This function enable/disable the hwvad interrupt for the selected PDM peripheral.
|
|
|
|
*
|
|
|
|
* @param base Base address of the PDM peripheral.
|
|
|
|
* @param vadCallback callback Pointer to store callback function, should be NULL when disable.
|
|
|
|
* @param userData user data.
|
|
|
|
* @param enable true is enable, false is disable.
|
|
|
|
* @retval None.
|
|
|
|
*/
|
|
|
|
void PDM_EnableHwvadInterruptCallback(PDM_Type *base, pdm_hwvad_callback_t vadCallback, void *userData, bool enable);
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @name Transactional
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Initializes the PDM handle.
|
|
|
|
*
|
|
|
|
* This function initializes the handle for the PDM transactional APIs. Call
|
|
|
|
* this function once to get the handle initialized.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param handle PDM handle pointer.
|
|
|
|
* @param callback Pointer to the user callback function.
|
|
|
|
* @param userData User parameter passed to the callback function.
|
|
|
|
*/
|
|
|
|
void PDM_TransferCreateHandle(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_callback_t callback, void *userData);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief PDM set channel transfer config.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param handle PDM handle pointer.
|
|
|
|
* @param channel PDM channel.
|
|
|
|
* @param config channel config.
|
|
|
|
* @param format data format, support data width configurations,_pdm_data_width.
|
|
|
|
* @retval kStatus_PDM_ChannelConfig_Failed or kStatus_Success.
|
|
|
|
*/
|
|
|
|
status_t PDM_TransferSetChannelConfig(
|
|
|
|
PDM_Type *base, pdm_handle_t *handle, uint32_t channel, const pdm_channel_config_t *config, uint32_t format);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Performs an interrupt non-blocking receive transfer on PDM.
|
|
|
|
*
|
|
|
|
* @note This API returns immediately after the transfer initiates.
|
|
|
|
* Call the PDM_RxGetTransferStatusIRQ to poll the transfer status and check whether
|
|
|
|
* the transfer is finished. If the return status is not kStatus_PDM_Busy, the transfer
|
|
|
|
* is finished.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param handle Pointer to the pdm_handle_t structure which stores the transfer state.
|
|
|
|
* @param xfer Pointer to the pdm_transfer_t structure.
|
|
|
|
* @retval kStatus_Success Successfully started the data receive.
|
|
|
|
* @retval kStatus_PDM_Busy Previous receive still not finished.
|
|
|
|
*/
|
|
|
|
status_t PDM_TransferReceiveNonBlocking(PDM_Type *base, pdm_handle_t *handle, pdm_transfer_t *xfer);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Aborts the current IRQ receive.
|
|
|
|
*
|
|
|
|
* @note This API can be called when an interrupt non-blocking transfer initiates
|
|
|
|
* to abort the transfer early.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer
|
|
|
|
* @param handle Pointer to the pdm_handle_t structure which stores the transfer state.
|
|
|
|
*/
|
|
|
|
void PDM_TransferAbortReceive(PDM_Type *base, pdm_handle_t *handle);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Tx interrupt handler.
|
|
|
|
*
|
|
|
|
* @param base PDM base pointer.
|
|
|
|
* @param handle Pointer to the pdm_handle_t structure.
|
|
|
|
*/
|
|
|
|
void PDM_TransferHandleIRQ(PDM_Type *base, pdm_handle_t *handle);
|
|
|
|
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
#if defined(__cplusplus)
|
|
|
|
}
|
|
|
|
#endif /*_cplusplus*/
|
|
|
|
|
|
|
|
/*! @} */
|
|
|
|
|
|
|
|
#endif /* _FSL_PDM_H_ */
|