//***************************************************************************** // //! @file am_hal_pdm.h //! //! @brief HAL implementation for the PDM module. //! //! @addtogroup pdm3 PDM - Pulse Density Modulated Functions //! @ingroup apollo3_hal //! @{ // //***************************************************************************** //***************************************************************************** // // Copyright (c) 2024, Ambiq Micro, Inc. // 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. // // 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 release_sdk_3_2_0-dd5f40c14b 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; //! Gain am_hal_pdm_gain_e eRightGain; //! Decimation Rate uint32_t ui32DecimationRate; //! Filters bool bHighPassEnable; //! Filters 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; bool bDoNotStartPdm; } am_hal_pdm_config_t; //***************************************************************************** // //! DMA transfer structure // //***************************************************************************** typedef struct { uint32_t ui32TargetAddr; // //! second buffer when double buffering // uint32_t ui32TargetAddrReverse; // //! when double buffering, if this is non zero, it is the addres //! of the buffer with data //! it should be zeroed once the data is read from the buffer // uint32_t ui32BufferWithDataAddr; // //! number of byes for each DMA transfer // uint32_t ui32TotalCount; // //! start DMA transfer in ISR to keep data flowing // volatile bool bRestartDMA; uint8_t align[3]; //! longword align struct } am_hal_pdm_transfer_t; typedef struct { uint32_t isrStat; uint32_t dmaStat; } am_hal_interupt_service_msg_t; //***************************************************************************** // //! @brief Initialization function //! //! @param ui32Module //! @param ppHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_initialize(uint32_t ui32Module, void **ppHandle); //***************************************************************************** // //! @brief De-Initialization function //! //! @param pHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_deinitialize(void *pHandle); //***************************************************************************** // //! @brief Power control function //! //! @param pHandle //! @param ePowerState //! @param bRetainState //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_power_control(void *pHandle, am_hal_sysctrl_power_state_e ePowerState, bool bRetainState); //***************************************************************************** // //! @brief Configure the PDM //! //! @param pHandle //! @param psConfig //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_configure(void *pHandle, const am_hal_pdm_config_t *psConfig); // Enable/Disable //***************************************************************************** // //! @brief Enable the PDM //! //! @param pHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_enable(void *pHandle); //***************************************************************************** // //! @brief Disable the PDM //! //! @param pHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_disable(void *pHandle); //***************************************************************************** // //! @brief setup dma parameters, //! this will not start a DMA transfer //! //! @param pHandle //! //! @return // //***************************************************************************** extern uint32_t am_hal_dma_param_setup(void *pHandle, am_hal_pdm_transfer_t *pDmaCfg); //***************************************************************************** // //! @brief start dma with perviously setup parameters //! //! @param pHandle //! //! @return // //***************************************************************************** extern uint32_t am_hal_dma_restart(void *pHandle); //***************************************************************************** // //! @brief Setup and start a DMA transaction from the PDM directly to SRAM //! //! @param pHandle //! @param pDmaCfg DMA config params //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_dma_start(void *pHandle, am_hal_pdm_transfer_t *pDmaCfg); //***************************************************************************** // //! @brief Set FIFOTHR Value //! //! @param pHandle - handle for the interface. //! @param value - value for the threshold. //! //! @return AM_HAL_STATUS_SUCCESS // //***************************************************************************** uint32_t am_hal_pdm_fifo_threshold_setup(void *pHandle, uint32_t value); //***************************************************************************** // //! @brief PDM DMA Get Buffer //! //! @param pHandle - handle for the interface. //! //! @return Pointer to the DMA Buffer // //***************************************************************************** extern uint32_t am_hal_pdm_dma_get_buffer(void *pHandle); //***************************************************************************** //***************************************************************************** // //! @brief Flush the PDM FIFO //! //! @param pHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_fifo_flush(void *pHandle); //***************************************************************************** // //! @brief Enable PDM passthrough to the I2S slave. //! //! @param pHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_i2s_enable(void *pHandle); //***************************************************************************** // //! @brief Disable PDM passthrough to the I2S slave. //! //! @param pHandle //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_i2s_disable(void *pHandle); //***************************************************************************** // //! @brief Interrupt enable //! //! @param pHandle //! @param ui32IntMask //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_interrupt_enable(void *pHandle, uint32_t ui32IntMask); //***************************************************************************** // //! @brief Interrupt disable //! //! @param pHandle //! @param ui32IntMask //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_interrupt_disable(void *pHandle, uint32_t ui32IntMask); //***************************************************************************** // //! @brief Interrupt clear //! //! @param pHandle //! @param ui32IntMask //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_interrupt_clear(void *pHandle, uint32_t ui32IntMask); //***************************************************************************** // //! @brief Returns the interrupt status //! //! @param pHandle //! @param pui32Status //! @param bEnabledOnly //! @return uint32_t // //***************************************************************************** extern uint32_t am_hal_pdm_interrupt_status_get(void *pHandle, uint32_t *pui32Status, bool bEnabledOnly); //***************************************************************************** // //! @brief PDM Interrupt Service Routine //! //! @details This is called from an ISR, this will manage //! double buffered PDM dma transfers //! //! @param pHandle - handle for the module instance. //! @param ptIsrData - returns module status //! @param pTransferCfg - Pointer to the PDM Config //! //! @return AM_HAL_STATUS_SUCCESS // //***************************************************************************** extern uint32_t am_hal_pdm_interrupt_service(void *pHandle, am_hal_interupt_service_msg_t *ptIsrData, am_hal_pdm_transfer_t* pTransferCfg); #ifdef __cplusplus } #endif #endif // AM_HAL_PDM_H //***************************************************************************** // // End Doxygen group. //! @} // //*****************************************************************************