2022-10-23 23:45:43 -07:00

318 lines
11 KiB
C

//*****************************************************************************
//
//! @file am_hal_pdm.h
//!
//! @brief API for the PDM module
//!
//! @addtogroup
//! @ingroup
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2020, Ambiq Micro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef AM_HAL_PDM_H
#define AM_HAL_PDM_H
#ifdef __cplusplus
extern "C"
{
#endif
//*****************************************************************************
//
// CMSIS-style macro for handling a variable IOS module number.
//
//*****************************************************************************
#define AM_REG_PDM_NUM_MODULES 1
#define PDMn(n) ((PDM_Type*)(PDM_BASE + (n * (PDM_BASE - PDM_BASE))))
//*****************************************************************************
//
// DMA threshold minimum.
//
// The PDM DMA works best if its threshold value is set to a multiple of 4
// between 16 and 24, but it will technically allow threshold settings between
// 4 and 24. This macro sets the minimum threshold value that the HAL layer
// will allow.
//
//*****************************************************************************
#define AM_HAL_PDM_DMA_THRESHOLD_MIN 16
//*****************************************************************************
//
// PDM-specific error conditions.
//
//*****************************************************************************
typedef enum
{
//
// The PDM HAL will throw this error if it can't find a threshold value to
// match the total-count value passed in by a caller requesting a DMA
// transfer. The PDM hardware requires all DMA transactions to be evenly
// divisible in chunks of one FIFO size or smaller. Try changing your
// ui32TotalCount value to a more evenly divisible number.
//
AM_HAL_PDM_STATUS_BAD_TOTALCOUNT = AM_HAL_STATUS_MODULE_SPECIFIC_START,
}
am_hal_pdm_status_e;
//*****************************************************************************
//
// Gain settings.
//
//*****************************************************************************
typedef enum
{
AM_HAL_PDM_GAIN_P405DB = PDM_PCFG_PGALEFT_P405DB,
AM_HAL_PDM_GAIN_P390DB = PDM_PCFG_PGALEFT_P390DB,
AM_HAL_PDM_GAIN_P375DB = PDM_PCFG_PGALEFT_P375DB,
AM_HAL_PDM_GAIN_P360DB = PDM_PCFG_PGALEFT_P360DB,
AM_HAL_PDM_GAIN_P345DB = PDM_PCFG_PGALEFT_P345DB,
AM_HAL_PDM_GAIN_P330DB = PDM_PCFG_PGALEFT_P330DB,
AM_HAL_PDM_GAIN_P315DB = PDM_PCFG_PGALEFT_P315DB,
AM_HAL_PDM_GAIN_P300DB = PDM_PCFG_PGALEFT_P300DB,
AM_HAL_PDM_GAIN_P285DB = PDM_PCFG_PGALEFT_P285DB,
AM_HAL_PDM_GAIN_P270DB = PDM_PCFG_PGALEFT_P270DB,
AM_HAL_PDM_GAIN_P255DB = PDM_PCFG_PGALEFT_P255DB,
AM_HAL_PDM_GAIN_P240DB = PDM_PCFG_PGALEFT_P240DB,
AM_HAL_PDM_GAIN_P225DB = PDM_PCFG_PGALEFT_P225DB,
AM_HAL_PDM_GAIN_P210DB = PDM_PCFG_PGALEFT_P210DB,
AM_HAL_PDM_GAIN_P195DB = PDM_PCFG_PGALEFT_P195DB,
AM_HAL_PDM_GAIN_P180DB = PDM_PCFG_PGALEFT_P180DB,
AM_HAL_PDM_GAIN_P165DB = PDM_PCFG_PGALEFT_P165DB,
AM_HAL_PDM_GAIN_P150DB = PDM_PCFG_PGALEFT_P150DB,
AM_HAL_PDM_GAIN_P135DB = PDM_PCFG_PGALEFT_P135DB,
AM_HAL_PDM_GAIN_P120DB = PDM_PCFG_PGALEFT_P120DB,
AM_HAL_PDM_GAIN_P105DB = PDM_PCFG_PGALEFT_P105DB,
AM_HAL_PDM_GAIN_P90DB = PDM_PCFG_PGALEFT_P90DB,
AM_HAL_PDM_GAIN_P75DB = PDM_PCFG_PGALEFT_P75DB,
AM_HAL_PDM_GAIN_P60DB = PDM_PCFG_PGALEFT_P60DB,
AM_HAL_PDM_GAIN_P45DB = PDM_PCFG_PGALEFT_P45DB,
AM_HAL_PDM_GAIN_P30DB = PDM_PCFG_PGALEFT_P30DB,
AM_HAL_PDM_GAIN_P15DB = PDM_PCFG_PGALEFT_P15DB,
AM_HAL_PDM_GAIN_0DB = PDM_PCFG_PGALEFT_0DB,
AM_HAL_PDM_GAIN_M15DB = PDM_PCFG_PGALEFT_M15DB,
AM_HAL_PDM_GAIN_M300DB = PDM_PCFG_PGALEFT_M300DB,
AM_HAL_PDM_GAIN_M45DB = PDM_PCFG_PGALEFT_M45DB,
AM_HAL_PDM_GAIN_M60DB = PDM_PCFG_PGALEFT_M60DB,
}
am_hal_pdm_gain_e;
//*****************************************************************************
//
// Clock Source selection.
//
//*****************************************************************************
typedef enum
{
AM_HAL_PDM_INTERNAL_CLK = PDM_VCFG_SELAP_INTERNAL,
AM_HAL_PDM_I2S_CLK = PDM_VCFG_SELAP_I2S,
}
am_hal_pdm_clksrc_e;
//*****************************************************************************
//
// PDM internal clock speed selection.
//
//*****************************************************************************
typedef enum
{
AM_HAL_PDM_CLK_DISABLE = PDM_VCFG_PDMCLKSEL_DISABLE,
AM_HAL_PDM_CLK_12MHZ = PDM_VCFG_PDMCLKSEL_12MHz,
AM_HAL_PDM_CLK_6MHZ = PDM_VCFG_PDMCLKSEL_6MHz,
AM_HAL_PDM_CLK_3MHZ = PDM_VCFG_PDMCLKSEL_3MHz,
AM_HAL_PDM_CLK_1_5MHZ = PDM_VCFG_PDMCLKSEL_1_5MHz,
AM_HAL_PDM_CLK_750KHZ = PDM_VCFG_PDMCLKSEL_750KHz,
AM_HAL_PDM_CLK_375KHZ = PDM_VCFG_PDMCLKSEL_375KHz,
AM_HAL_PDM_CLK_187KHZ = PDM_VCFG_PDMCLKSEL_187KHz,
}
am_hal_pdm_clkspd_e;
//*****************************************************************************
//
// PDM clock divider setting.
//
//*****************************************************************************
typedef enum
{
AM_HAL_PDM_MCLKDIV_4 = PDM_PCFG_MCLKDIV_MCKDIV4,
AM_HAL_PDM_MCLKDIV_3 = PDM_PCFG_MCLKDIV_MCKDIV3,
AM_HAL_PDM_MCLKDIV_2 = PDM_PCFG_MCLKDIV_MCKDIV2,
AM_HAL_PDM_MCLKDIV_1 = PDM_PCFG_MCLKDIV_MCKDIV1,
}
am_hal_pdm_mclkdiv_e;
//*****************************************************************************
//
// PCM Channel Select.
//
//*****************************************************************************
typedef enum
{
AM_HAL_PDM_CHANNEL_LEFT = PDM_VCFG_CHSET_LEFT,
AM_HAL_PDM_CHANNEL_RIGHT = PDM_VCFG_CHSET_RIGHT,
AM_HAL_PDM_CHANNEL_STEREO = PDM_VCFG_CHSET_STEREO,
}
am_hal_pdm_chset_e;
//*****************************************************************************
//
// PDM power state settings.
//
//*****************************************************************************
#define AM_HAL_PDM_POWER_ON AM_HAL_SYSCTRL_WAKE
#define AM_HAL_PDM_POWER_OFF AM_HAL_SYSCTRL_NORMALSLEEP
//*****************************************************************************
//
// PDM interrupts.
//
//*****************************************************************************
#define AM_HAL_PDM_INT_DERR PDM_INTSTAT_DERR_Msk
#define AM_HAL_PDM_INT_DCMP PDM_INTSTAT_DCMP_Msk
#define AM_HAL_PDM_INT_UNDFL PDM_INTSTAT_UNDFL_Msk
#define AM_HAL_PDM_INT_OVF PDM_INTSTAT_OVF_Msk
#define AM_HAL_PDM_INT_THR PDM_INTSTAT_THR_Msk
//*****************************************************************************
//
// Configuration structure for the PDM
//
//*****************************************************************************
typedef struct
{
// Clock
am_hal_pdm_mclkdiv_e eClkDivider;
// Gain
am_hal_pdm_gain_e eLeftGain;
am_hal_pdm_gain_e eRightGain;
// Decimation Rate
uint32_t ui32DecimationRate;
// Filters
bool bHighPassEnable;
uint32_t ui32HighPassCutoff;
// PDMCLKSEL
am_hal_pdm_clkspd_e ePDMClkSpeed;
// BCLKINV
bool bInvertI2SBCLK;
// SELAP
am_hal_pdm_clksrc_e ePDMClkSource;
// DMICKDEL
bool bPDMSampleDelay;
// PCMPACK
bool bDataPacking;
// CHSET
am_hal_pdm_chset_e ePCMChannels;
uint32_t ui32GainChangeDelay;
bool bI2SEnable;
bool bSoftMute;
bool bLRSwap;
}
am_hal_pdm_config_t;
//*****************************************************************************
//
// DMA transfer structure
//
//*****************************************************************************
typedef struct
{
uint32_t ui32TargetAddr;
uint32_t ui32TotalCount;
}
am_hal_pdm_transfer_t;
// Init/De-init.
extern uint32_t am_hal_pdm_initialize(uint32_t ui32Module, void **ppHandle);
extern uint32_t am_hal_pdm_deinitialize(void *pHandle);
// Power
extern uint32_t am_hal_pdm_power_control(void *pHandle, am_hal_sysctrl_power_state_e ePowerState, bool bRetainState);
// Config
extern uint32_t am_hal_pdm_configure(void *pHandle, am_hal_pdm_config_t *psConfig);
// Enable/Disable
extern uint32_t am_hal_pdm_enable(void *pHandle);
extern uint32_t am_hal_pdm_disable(void *pHandle);
// Gather PDM data.
extern uint32_t am_hal_pdm_dma_start(void *pHandle, am_hal_pdm_transfer_t *pDmaCfg);
// Flush the PDM FIFO.
extern uint32_t am_hal_pdm_fifo_flush(void *pHandle);
// I2S Passthrough
extern uint32_t am_hal_pdm_i2s_enable(void *pHandle);
extern uint32_t am_hal_pdm_i2s_disable(void *pHandle);
// Interrupts.
extern uint32_t am_hal_pdm_interrupt_enable(void *pHandle, uint32_t ui32IntMask);
extern uint32_t am_hal_pdm_interrupt_disable(void *pHandle, uint32_t ui32IntMask);
extern uint32_t am_hal_pdm_interrupt_clear(void *pHandle, uint32_t ui32IntMask);
extern uint32_t am_hal_pdm_interrupt_status_get(void *pHandle, uint32_t *pui32Status, bool bEnabledOnly);
#ifdef __cplusplus
}
#endif
#endif // AM_HAL_PDM_H
//*****************************************************************************
//
// End Doxygen group.
//! @}
//
//*****************************************************************************