1 //***************************************************************************** 2 // 3 //! @file am_hal_pdm.h 4 //! 5 //! @brief HAL implementation for the PDM module. 6 //! 7 //! @addtogroup pdm3 PDM - Pulse Density Modulated Functions 8 //! @ingroup apollo3_hal 9 //! @{ 10 // 11 //***************************************************************************** 12 13 //***************************************************************************** 14 // 15 // Copyright (c) 2024, Ambiq Micro, Inc. 16 // All rights reserved. 17 // 18 // Redistribution and use in source and binary forms, with or without 19 // modification, are permitted provided that the following conditions are met: 20 // 21 // 1. Redistributions of source code must retain the above copyright notice, 22 // this list of conditions and the following disclaimer. 23 // 24 // 2. Redistributions in binary form must reproduce the above copyright 25 // notice, this list of conditions and the following disclaimer in the 26 // documentation and/or other materials provided with the distribution. 27 // 28 // 3. Neither the name of the copyright holder nor the names of its 29 // contributors may be used to endorse or promote products derived from this 30 // software without specific prior written permission. 31 // 32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 // POSSIBILITY OF SUCH DAMAGE. 43 // 44 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package. 45 // 46 //***************************************************************************** 47 48 #ifndef AM_HAL_PDM_H 49 #define AM_HAL_PDM_H 50 51 #ifdef __cplusplus 52 extern "C" 53 { 54 #endif 55 56 //***************************************************************************** 57 // 58 //! CMSIS-style macro for handling a variable IOS module number. 59 // 60 //***************************************************************************** 61 #define AM_REG_PDM_NUM_MODULES 1 62 #define PDMn(n) ((PDM_Type*)(PDM_BASE + (n * (PDM_BASE - PDM_BASE)))) 63 64 //***************************************************************************** 65 // 66 //! DMA threshold minimum. 67 //! 68 //! The PDM DMA works best if its threshold value is set to a multiple of 4 69 //! between 16 and 24, but it will technically allow threshold settings between 70 //! 4 and 24. This macro sets the minimum threshold value that the HAL layer 71 //! will allow. 72 // 73 //***************************************************************************** 74 #define AM_HAL_PDM_DMA_THRESHOLD_MIN 16 75 76 //***************************************************************************** 77 // 78 //! PDM-specific error conditions. 79 // 80 //***************************************************************************** 81 typedef enum 82 { 83 // 84 //! The PDM HAL will throw this error if it can't find a threshold value to 85 //! match the total-count value passed in by a caller requesting a DMA 86 //! transfer. The PDM hardware requires all DMA transactions to be evenly 87 //! divisible in chunks of one FIFO size or smaller. Try changing your 88 //! ui32TotalCount value to a more evenly divisible number. 89 // 90 AM_HAL_PDM_STATUS_BAD_TOTALCOUNT = AM_HAL_STATUS_MODULE_SPECIFIC_START, 91 } 92 am_hal_pdm_status_e; 93 94 //***************************************************************************** 95 // 96 //! Gain settings. 97 // 98 //***************************************************************************** 99 typedef enum 100 { 101 AM_HAL_PDM_GAIN_P405DB = PDM_PCFG_PGALEFT_P405DB, 102 AM_HAL_PDM_GAIN_P390DB = PDM_PCFG_PGALEFT_P390DB, 103 AM_HAL_PDM_GAIN_P375DB = PDM_PCFG_PGALEFT_P375DB, 104 AM_HAL_PDM_GAIN_P360DB = PDM_PCFG_PGALEFT_P360DB, 105 AM_HAL_PDM_GAIN_P345DB = PDM_PCFG_PGALEFT_P345DB, 106 AM_HAL_PDM_GAIN_P330DB = PDM_PCFG_PGALEFT_P330DB, 107 AM_HAL_PDM_GAIN_P315DB = PDM_PCFG_PGALEFT_P315DB, 108 AM_HAL_PDM_GAIN_P300DB = PDM_PCFG_PGALEFT_P300DB, 109 AM_HAL_PDM_GAIN_P285DB = PDM_PCFG_PGALEFT_P285DB, 110 AM_HAL_PDM_GAIN_P270DB = PDM_PCFG_PGALEFT_P270DB, 111 AM_HAL_PDM_GAIN_P255DB = PDM_PCFG_PGALEFT_P255DB, 112 AM_HAL_PDM_GAIN_P240DB = PDM_PCFG_PGALEFT_P240DB, 113 AM_HAL_PDM_GAIN_P225DB = PDM_PCFG_PGALEFT_P225DB, 114 AM_HAL_PDM_GAIN_P210DB = PDM_PCFG_PGALEFT_P210DB, 115 AM_HAL_PDM_GAIN_P195DB = PDM_PCFG_PGALEFT_P195DB, 116 AM_HAL_PDM_GAIN_P180DB = PDM_PCFG_PGALEFT_P180DB, 117 AM_HAL_PDM_GAIN_P165DB = PDM_PCFG_PGALEFT_P165DB, 118 AM_HAL_PDM_GAIN_P150DB = PDM_PCFG_PGALEFT_P150DB, 119 AM_HAL_PDM_GAIN_P135DB = PDM_PCFG_PGALEFT_P135DB, 120 AM_HAL_PDM_GAIN_P120DB = PDM_PCFG_PGALEFT_P120DB, 121 AM_HAL_PDM_GAIN_P105DB = PDM_PCFG_PGALEFT_P105DB, 122 AM_HAL_PDM_GAIN_P90DB = PDM_PCFG_PGALEFT_P90DB, 123 AM_HAL_PDM_GAIN_P75DB = PDM_PCFG_PGALEFT_P75DB, 124 AM_HAL_PDM_GAIN_P60DB = PDM_PCFG_PGALEFT_P60DB, 125 AM_HAL_PDM_GAIN_P45DB = PDM_PCFG_PGALEFT_P45DB, 126 AM_HAL_PDM_GAIN_P30DB = PDM_PCFG_PGALEFT_P30DB, 127 AM_HAL_PDM_GAIN_P15DB = PDM_PCFG_PGALEFT_P15DB, 128 AM_HAL_PDM_GAIN_0DB = PDM_PCFG_PGALEFT_0DB, 129 AM_HAL_PDM_GAIN_M15DB = PDM_PCFG_PGALEFT_M15DB, 130 AM_HAL_PDM_GAIN_M300DB = PDM_PCFG_PGALEFT_M300DB, 131 AM_HAL_PDM_GAIN_M45DB = PDM_PCFG_PGALEFT_M45DB, 132 AM_HAL_PDM_GAIN_M60DB = PDM_PCFG_PGALEFT_M60DB, 133 } 134 am_hal_pdm_gain_e; 135 136 //***************************************************************************** 137 // 138 //! Clock Source selection. 139 // 140 //***************************************************************************** 141 typedef enum 142 { 143 AM_HAL_PDM_INTERNAL_CLK = PDM_VCFG_SELAP_INTERNAL, 144 AM_HAL_PDM_I2S_CLK = PDM_VCFG_SELAP_I2S, 145 } 146 am_hal_pdm_clksrc_e; 147 148 //***************************************************************************** 149 // 150 //! PDM internal clock speed selection. 151 // 152 //***************************************************************************** 153 typedef enum 154 { 155 AM_HAL_PDM_CLK_DISABLE = PDM_VCFG_PDMCLKSEL_DISABLE, 156 AM_HAL_PDM_CLK_12MHZ = PDM_VCFG_PDMCLKSEL_12MHz, 157 AM_HAL_PDM_CLK_6MHZ = PDM_VCFG_PDMCLKSEL_6MHz, 158 AM_HAL_PDM_CLK_3MHZ = PDM_VCFG_PDMCLKSEL_3MHz, 159 AM_HAL_PDM_CLK_1_5MHZ = PDM_VCFG_PDMCLKSEL_1_5MHz, 160 AM_HAL_PDM_CLK_750KHZ = PDM_VCFG_PDMCLKSEL_750KHz, 161 AM_HAL_PDM_CLK_375KHZ = PDM_VCFG_PDMCLKSEL_375KHz, 162 AM_HAL_PDM_CLK_187KHZ = PDM_VCFG_PDMCLKSEL_187KHz, 163 } 164 am_hal_pdm_clkspd_e; 165 166 //***************************************************************************** 167 // 168 //! PDM clock divider setting. 169 // 170 //***************************************************************************** 171 typedef enum 172 { 173 AM_HAL_PDM_MCLKDIV_4 = PDM_PCFG_MCLKDIV_MCKDIV4, 174 AM_HAL_PDM_MCLKDIV_3 = PDM_PCFG_MCLKDIV_MCKDIV3, 175 AM_HAL_PDM_MCLKDIV_2 = PDM_PCFG_MCLKDIV_MCKDIV2, 176 AM_HAL_PDM_MCLKDIV_1 = PDM_PCFG_MCLKDIV_MCKDIV1, 177 } 178 am_hal_pdm_mclkdiv_e; 179 180 //***************************************************************************** 181 // 182 //! PCM Channel Select. 183 // 184 //***************************************************************************** 185 typedef enum 186 { 187 AM_HAL_PDM_CHANNEL_LEFT = PDM_VCFG_CHSET_LEFT, 188 AM_HAL_PDM_CHANNEL_RIGHT = PDM_VCFG_CHSET_RIGHT, 189 AM_HAL_PDM_CHANNEL_STEREO = PDM_VCFG_CHSET_STEREO, 190 } 191 am_hal_pdm_chset_e; 192 193 //***************************************************************************** 194 // 195 //! PDM power state settings. 196 // 197 //***************************************************************************** 198 #define AM_HAL_PDM_POWER_ON AM_HAL_SYSCTRL_WAKE 199 #define AM_HAL_PDM_POWER_OFF AM_HAL_SYSCTRL_NORMALSLEEP 200 201 //***************************************************************************** 202 // 203 //! PDM interrupts. 204 // 205 //***************************************************************************** 206 #define AM_HAL_PDM_INT_DERR PDM_INTSTAT_DERR_Msk 207 #define AM_HAL_PDM_INT_DCMP PDM_INTSTAT_DCMP_Msk 208 #define AM_HAL_PDM_INT_UNDFL PDM_INTSTAT_UNDFL_Msk 209 #define AM_HAL_PDM_INT_OVF PDM_INTSTAT_OVF_Msk 210 #define AM_HAL_PDM_INT_THR PDM_INTSTAT_THR_Msk 211 212 //***************************************************************************** 213 // 214 //! Configuration structure for the PDM 215 // 216 //***************************************************************************** 217 typedef struct 218 { 219 //! Clock 220 am_hal_pdm_mclkdiv_e eClkDivider; 221 222 //! Gain 223 am_hal_pdm_gain_e eLeftGain; 224 //! Gain 225 am_hal_pdm_gain_e eRightGain; 226 227 //! Decimation Rate 228 uint32_t ui32DecimationRate; 229 230 //! Filters 231 bool bHighPassEnable; 232 //! Filters 233 uint32_t ui32HighPassCutoff; 234 235 //! PDMCLKSEL 236 am_hal_pdm_clkspd_e ePDMClkSpeed; 237 238 //! BCLKINV 239 bool bInvertI2SBCLK; 240 241 //! SELAP 242 am_hal_pdm_clksrc_e ePDMClkSource; 243 244 //! DMICKDEL 245 bool bPDMSampleDelay; 246 247 //! PCMPACK 248 bool bDataPacking; 249 250 //! CHSET 251 am_hal_pdm_chset_e ePCMChannels; 252 253 uint32_t ui32GainChangeDelay; 254 255 bool bI2SEnable; 256 257 bool bSoftMute; 258 259 bool bLRSwap; 260 261 bool bDoNotStartPdm; 262 } 263 am_hal_pdm_config_t; 264 265 //***************************************************************************** 266 // 267 //! DMA transfer structure 268 // 269 //***************************************************************************** 270 typedef struct 271 { 272 uint32_t ui32TargetAddr; 273 // 274 //! second buffer when double buffering 275 // 276 uint32_t ui32TargetAddrReverse; 277 278 // 279 //! when double buffering, if this is non zero, it is the addres 280 //! of the buffer with data 281 //! it should be zeroed once the data is read from the buffer 282 // 283 uint32_t ui32BufferWithDataAddr; 284 285 // 286 //! number of byes for each DMA transfer 287 // 288 uint32_t ui32TotalCount; 289 290 // 291 //! start DMA transfer in ISR to keep data flowing 292 // 293 volatile bool bRestartDMA; 294 295 uint8_t align[3]; //! longword align struct 296 } 297 am_hal_pdm_transfer_t; 298 299 typedef struct 300 { 301 uint32_t isrStat; 302 uint32_t dmaStat; 303 304 } 305 am_hal_interupt_service_msg_t; 306 307 308 //***************************************************************************** 309 // 310 //! @brief Initialization function 311 //! 312 //! @param ui32Module 313 //! @param ppHandle 314 //! @return uint32_t 315 // 316 //***************************************************************************** 317 extern uint32_t am_hal_pdm_initialize(uint32_t ui32Module, void **ppHandle); 318 319 //***************************************************************************** 320 // 321 //! @brief De-Initialization function 322 //! 323 //! @param pHandle 324 //! @return uint32_t 325 // 326 //***************************************************************************** 327 extern uint32_t am_hal_pdm_deinitialize(void *pHandle); 328 329 //***************************************************************************** 330 // 331 //! @brief Power control function 332 //! 333 //! @param pHandle 334 //! @param ePowerState 335 //! @param bRetainState 336 //! @return uint32_t 337 // 338 //***************************************************************************** 339 extern uint32_t am_hal_pdm_power_control(void *pHandle, am_hal_sysctrl_power_state_e ePowerState, bool bRetainState); 340 341 //***************************************************************************** 342 // 343 //! @brief Configure the PDM 344 //! 345 //! @param pHandle 346 //! @param psConfig 347 //! @return uint32_t 348 // 349 //***************************************************************************** 350 extern uint32_t am_hal_pdm_configure(void *pHandle, const am_hal_pdm_config_t *psConfig); 351 352 // Enable/Disable 353 //***************************************************************************** 354 // 355 //! @brief Enable the PDM 356 //! 357 //! @param pHandle 358 //! @return uint32_t 359 // 360 //***************************************************************************** 361 extern uint32_t am_hal_pdm_enable(void *pHandle); 362 363 //***************************************************************************** 364 // 365 //! @brief Disable the PDM 366 //! 367 //! @param pHandle 368 //! @return uint32_t 369 // 370 //***************************************************************************** 371 extern uint32_t am_hal_pdm_disable(void *pHandle); 372 373 374 //***************************************************************************** 375 // 376 //! @brief setup dma parameters, 377 //! this will not start a DMA transfer 378 //! 379 //! @param pHandle 380 //! 381 //! @return 382 // 383 //***************************************************************************** 384 extern uint32_t am_hal_dma_param_setup(void *pHandle, am_hal_pdm_transfer_t *pDmaCfg); 385 386 //***************************************************************************** 387 // 388 //! @brief start dma with perviously setup parameters 389 //! 390 //! @param pHandle 391 //! 392 //! @return 393 // 394 //***************************************************************************** 395 extern uint32_t am_hal_dma_restart(void *pHandle); 396 //***************************************************************************** 397 // 398 //! @brief Setup and start a DMA transaction from the PDM directly to SRAM 399 //! 400 //! @param pHandle 401 //! @param pDmaCfg DMA config params 402 //! @return uint32_t 403 // 404 //***************************************************************************** 405 extern uint32_t am_hal_pdm_dma_start(void *pHandle, am_hal_pdm_transfer_t *pDmaCfg); 406 //***************************************************************************** 407 // 408 //! @brief Set FIFOTHR Value 409 //! 410 //! @param pHandle - handle for the interface. 411 //! @param value - value for the threshold. 412 //! 413 //! @return AM_HAL_STATUS_SUCCESS 414 // 415 //***************************************************************************** 416 uint32_t am_hal_pdm_fifo_threshold_setup(void *pHandle, uint32_t value); 417 418 //***************************************************************************** 419 // 420 //! @brief PDM DMA Get Buffer 421 //! 422 //! @param pHandle - handle for the interface. 423 //! 424 //! @return Pointer to the DMA Buffer 425 // 426 //***************************************************************************** 427 extern uint32_t am_hal_pdm_dma_get_buffer(void *pHandle); 428 429 //***************************************************************************** 430 431 //***************************************************************************** 432 // 433 //! @brief Flush the PDM FIFO 434 //! 435 //! @param pHandle 436 //! @return uint32_t 437 // 438 //***************************************************************************** 439 extern uint32_t am_hal_pdm_fifo_flush(void *pHandle); 440 441 //***************************************************************************** 442 // 443 //! @brief Enable PDM passthrough to the I2S slave. 444 //! 445 //! @param pHandle 446 //! @return uint32_t 447 // 448 //***************************************************************************** 449 extern uint32_t am_hal_pdm_i2s_enable(void *pHandle); 450 451 //***************************************************************************** 452 // 453 //! @brief Disable PDM passthrough to the I2S slave. 454 //! 455 //! @param pHandle 456 //! @return uint32_t 457 // 458 //***************************************************************************** 459 extern uint32_t am_hal_pdm_i2s_disable(void *pHandle); 460 461 //***************************************************************************** 462 // 463 //! @brief Interrupt enable 464 //! 465 //! @param pHandle 466 //! @param ui32IntMask 467 //! @return uint32_t 468 // 469 //***************************************************************************** 470 extern uint32_t am_hal_pdm_interrupt_enable(void *pHandle, uint32_t ui32IntMask); 471 472 //***************************************************************************** 473 // 474 //! @brief Interrupt disable 475 //! 476 //! @param pHandle 477 //! @param ui32IntMask 478 //! @return uint32_t 479 // 480 //***************************************************************************** 481 extern uint32_t am_hal_pdm_interrupt_disable(void *pHandle, uint32_t ui32IntMask); 482 483 //***************************************************************************** 484 // 485 //! @brief Interrupt clear 486 //! 487 //! @param pHandle 488 //! @param ui32IntMask 489 //! @return uint32_t 490 // 491 //***************************************************************************** 492 extern uint32_t am_hal_pdm_interrupt_clear(void *pHandle, uint32_t ui32IntMask); 493 494 //***************************************************************************** 495 // 496 //! @brief Returns the interrupt status 497 //! 498 //! @param pHandle 499 //! @param pui32Status 500 //! @param bEnabledOnly 501 //! @return uint32_t 502 // 503 //***************************************************************************** 504 extern uint32_t am_hal_pdm_interrupt_status_get(void *pHandle, uint32_t *pui32Status, bool bEnabledOnly); 505 506 //***************************************************************************** 507 // 508 //! @brief PDM Interrupt Service Routine 509 //! 510 //! @details This is called from an ISR, this will manage 511 //! double buffered PDM dma transfers 512 //! 513 //! @param pHandle - handle for the module instance. 514 //! @param ptIsrData - returns module status 515 //! @param pTransferCfg - Pointer to the PDM Config 516 //! 517 //! @return AM_HAL_STATUS_SUCCESS 518 // 519 //***************************************************************************** 520 extern uint32_t am_hal_pdm_interrupt_service(void *pHandle, 521 am_hal_interupt_service_msg_t *ptIsrData, 522 am_hal_pdm_transfer_t* pTransferCfg); 523 524 525 526 #ifdef __cplusplus 527 } 528 #endif 529 530 #endif // AM_HAL_PDM_H 531 532 //***************************************************************************** 533 // 534 // End Doxygen group. 535 //! @} 536 // 537 //***************************************************************************** 538