1 //*****************************************************************************
2 //
3 //! @file am_hal_pdm.c
4 //!
5 //! @brief HAL implementation for the Pulse Density Modulation module.
6 //!
7 //! @addtogroup pdm_4p PDM - Pulse Density Modulation
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, 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 stable-7da8bae71f of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 
52 //*****************************************************************************
53 //
54 //! @name PDM magic number for handle verification
55 //! @{
56 //
57 //*****************************************************************************
58 #define AM_HAL_MAGIC_PDM                0xF956E2
59 
60 #define AM_HAL_PDM_HANDLE_VALID(h)                                            \
61     ((h) &&                                                                   \
62      ((am_hal_handle_prefix_t *)(h))->s.bInit &&                              \
63      (((am_hal_handle_prefix_t *)(h))->s.magic == AM_HAL_MAGIC_PDM))
64 //
65 //! @}
66 //
67 
68 //*****************************************************************************
69 //
70 //! Convenience macro for passing errors
71 //
72 //*****************************************************************************
73 #define RETURN_ON_ERROR(x)                                                    \
74     if ((x) != AM_HAL_STATUS_SUCCESS)                                         \
75     {                                                                         \
76         return (x);                                                           \
77     };
78 
79 //*****************************************************************************
80 //
81 //! Abbreviation for validating handles and returning errors
82 //
83 //*****************************************************************************
84 #ifndef AM_HAL_DISABLE_API_VALIDATION
85 
86 #define AM_HAL_PDM_HANDLE_CHECK(h)                                            \
87     if (!AM_HAL_PDM_HANDLE_VALID(h))                                          \
88     {                                                                         \
89         return AM_HAL_STATUS_INVALID_HANDLE;                                  \
90     }
91 
92 #else
93 
94 #define AM_HAL_PDM_HANDLE_CHECK(h)
95 
96 #endif // AM_HAL_DISABLE_API_VALIDATION
97 
98 //*****************************************************************************
99 //
100 //! @name Helper macros for delays.
101 //! @{
102 //
103 //*****************************************************************************
104 #define delay_ms(ms)                                                          \
105     if (1)                                                                    \
106     {                                                                         \
107         am_hal_clkgen_status_t sClkGenStatus;                                 \
108         am_hal_clkgen_status_get(&sClkGenStatus);                             \
109         am_hal_flash_delay((ms) * (sClkGenStatus.ui32SysclkFreq / 3000));     \
110     }
111 
112 #define delay_us(us)                                                          \
113     if (1)                                                                    \
114     {                                                                         \
115         am_hal_delay_us(us);                                                  \
116     }
117 //
118 //! @}
119 //
120 
121 //*****************************************************************************
122 //
123 //! Structure for handling PDM register state information for power up/down
124 //
125 //*****************************************************************************
126 am_hal_pdm_state_t g_PDMhandles[AM_REG_PDM_NUM_MODULES];
127 
128 //*****************************************************************************
129 //
130 // am_hal_pdm_initialize
131 //
132 //*****************************************************************************
133 uint32_t
am_hal_pdm_initialize(uint32_t ui32Module,void ** ppHandle)134 am_hal_pdm_initialize(uint32_t ui32Module, void **ppHandle)
135 {
136     //
137     // Check that the request module is in range.
138     //
139     if ( ui32Module >= AM_REG_PDM_NUM_MODULES )
140     {
141         return AM_HAL_STATUS_OUT_OF_RANGE;
142     }
143 
144     //
145     // Check for valid arguements.
146     //
147     if (!ppHandle)
148     {
149         return AM_HAL_STATUS_INVALID_ARG;
150     }
151 
152     //
153     // Check if the handle is unallocated.
154     //
155     if (g_PDMhandles[ui32Module].prefix.s.bInit)
156     {
157         return AM_HAL_STATUS_INVALID_OPERATION;
158     }
159 
160     //
161     // Initialize the handle.
162     //
163     g_PDMhandles[ui32Module].prefix.s.bInit = true;
164     g_PDMhandles[ui32Module].prefix.s.magic = AM_HAL_MAGIC_PDM;
165     g_PDMhandles[ui32Module].ui32Module = ui32Module;
166     g_PDMhandles[ui32Module].sRegState.bValid = false;
167 
168     //
169     // Return the handle.
170     //
171     *ppHandle = (void *)&g_PDMhandles[ui32Module];
172 
173     //
174     // Return the status.
175     //
176     return AM_HAL_STATUS_SUCCESS;
177 }
178 
179 //*****************************************************************************
180 //
181 // De-Initialization function.
182 //
183 //*****************************************************************************
184 uint32_t
am_hal_pdm_deinitialize(void * pHandle)185 am_hal_pdm_deinitialize(void *pHandle)
186 {
187     //
188     // Check the handle.
189     //
190     AM_HAL_PDM_HANDLE_CHECK(pHandle);
191 
192     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *)pHandle;
193 
194     //
195     // Reset the handle.
196     //
197     pState->prefix.s.bInit = false;
198     pState->prefix.s.magic = 0;
199     pState->ui32Module = 0;
200 
201     //
202     // Return the status.
203     //
204     return AM_HAL_STATUS_SUCCESS;
205 }
206 
207 //*****************************************************************************
208 //
209 // Power control function.
210 //
211 //*****************************************************************************
212 uint32_t
am_hal_pdm_power_control(void * pHandle,am_hal_sysctrl_power_state_e ePowerState,bool bRetainState)213 am_hal_pdm_power_control(void *pHandle,
214                          am_hal_sysctrl_power_state_e ePowerState,
215                          bool bRetainState)
216 {
217     //
218     // Check the handle.
219     //
220     AM_HAL_PDM_HANDLE_CHECK(pHandle);
221 
222     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
223     uint32_t ui32Module = pState->ui32Module;
224 
225     am_hal_pwrctrl_periph_e ePDMPowerModule = ((am_hal_pwrctrl_periph_e)
226                                                (AM_HAL_PWRCTRL_PERIPH_PDM0 +
227                                                 ui32Module));
228 
229     //
230     // Decode the requested power state and update PDM operation accordingly.
231     //
232     switch (ePowerState)
233     {
234         //
235         // Turn on the PDM.
236         //
237         case AM_HAL_SYSCTRL_WAKE:
238             //
239             // Make sure we don't try to restore an invalid state.
240             //
241             if (bRetainState && !pState->sRegState.bValid)
242             {
243                 return AM_HAL_STATUS_INVALID_OPERATION;
244             }
245 
246             //
247             // Enable power control.
248             //
249             am_hal_pwrctrl_periph_enable(ePDMPowerModule);
250 
251             if (bRetainState)
252             {
253                 //
254                 // Restore PDM registers
255                 //
256                 AM_CRITICAL_BEGIN;
257 
258                 pState->sRegState.bValid = false;
259 
260                 AM_CRITICAL_END;
261             }
262             break;
263 
264         //
265         // Turn off the PDM.
266         //
267         case AM_HAL_SYSCTRL_NORMALSLEEP:
268         case AM_HAL_SYSCTRL_DEEPSLEEP:
269             if (bRetainState)
270             {
271                 AM_CRITICAL_BEGIN;
272 
273                 pState->sRegState.bValid = true;
274 
275                 AM_CRITICAL_END;
276             }
277 
278             //
279             // Disable power control.
280             //
281             am_hal_pwrctrl_periph_disable(ePDMPowerModule);
282             break;
283 
284         default:
285             return AM_HAL_STATUS_INVALID_ARG;
286     }
287 
288     //
289     // Return the status.
290     //
291     return AM_HAL_STATUS_SUCCESS;
292 }
293 
294 //*****************************************************************************
295 //
296 // Configure the PDM.
297 //
298 //*****************************************************************************
299 uint32_t
am_hal_pdm_configure(void * pHandle,am_hal_pdm_config_t * psConfig)300 am_hal_pdm_configure(void *pHandle, am_hal_pdm_config_t *psConfig)
301 {
302     //
303     // Check the handle.
304     //
305     AM_HAL_PDM_HANDLE_CHECK(pHandle);
306 
307     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
308     uint32_t ui32Module = pState->ui32Module;
309 
310     //
311     // Apply the config structure settings to the CORECFG0 register.
312     //
313     PDMn(ui32Module)->CORECFG0_b.LRSWAP = psConfig->bLRSwap;
314     PDMn(ui32Module)->CORECFG0_b.SOFTMUTE = psConfig->bSoftMute;
315     // Set number of PDMA_CKO cycles during gain setting changes or soft mute
316     PDMn(ui32Module)->CORECFG0_b.SCYCLES = psConfig->ui32GainChangeDelay;
317 
318     PDMn(ui32Module)->CORECFG0_b.HPGAIN = psConfig->ui32HighPassCutoff;
319     PDMn(ui32Module)->CORECFG0_b.ADCHPD = psConfig->bHighPassEnable;
320     // PDMA_CKO frequency divisor. Fpdma_cko = Fmclk_l/(MCLKDIV+1)
321     PDMn(ui32Module)->CORECFG0_b.MCLKDIV = psConfig->ePDMAClkOutDivder;
322     PDMn(ui32Module)->CORECFG0_b.SINCRATE = psConfig->ui32DecimationRate;
323 
324     PDMn(ui32Module)->CORECFG0_b.PGAL = psConfig->eLeftGain;
325     PDMn(ui32Module)->CORECFG0_b.PGAR = psConfig->eRightGain;
326 
327     //
328     // Program the "CORECFG1_b" registers.
329     //
330     PDMn(ui32Module)->CORECFG1_b.PCMCHSET = psConfig->ePCMChannels;
331     // Divide down ratio for generating internal master MCLKQ.
332     PDMn(ui32Module)->CORECFG1_b.DIVMCLKQ = psConfig->eClkDivider;
333     // PDMA_CKO clock phase delay in terms of PDMCLK period to internal sampler
334     PDMn(ui32Module)->CORECFG1_b.CKODLY = psConfig->bPDMSampleDelay;
335     // Fine grain step size for smooth PGA or Softmute attenuation transition
336     PDMn(ui32Module)->CORECFG1_b.SELSTEP = psConfig->eStepSize;
337 
338     //
339     // Set the PDM Control register.
340     //
341     PDMn(ui32Module)->CTRL_b.CLKEN = 0;
342     PDMn(ui32Module)->CTRL_b.CLKSEL = psConfig->ePDMClkSpeed;
343 
344     PDMn(ui32Module)->CTRL_b.RSTB = 0;
345     PDMn(ui32Module)->CTRL_b.PCMPACK = 0;    // not supported in rev B
346 
347     delay_us(100);
348 
349     PDMn(ui32Module)->CTRL_b.RSTB = 1;
350 
351     return AM_HAL_STATUS_SUCCESS;
352 }
353 
354 //*****************************************************************************
355 //
356 // Configure the PDM Ctrl Register
357 //
358 //*****************************************************************************
359 uint32_t
am_hal_pdm_config_ctrlReg(void * pHandle,am_hal_pdm_config_t * psConfig)360 am_hal_pdm_config_ctrlReg(void *pHandle, am_hal_pdm_config_t *psConfig)
361 {
362     //
363     // Check the handle.
364     //
365     AM_HAL_PDM_HANDLE_CHECK(pHandle);
366 
367     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
368     uint32_t ui32Module = pState->ui32Module;
369 
370     PDMn(ui32Module)->CTRL_b.EN = 0;
371     PDMn(ui32Module)->CTRL_b.PCMPACK = 0;   // not supported in rev B
372     PDMn(ui32Module)->CTRL_b.RSTB = 0;
373     PDMn(ui32Module)->CTRL_b.CLKSEL = psConfig->ePDMClkSpeed;
374     PDMn(ui32Module)->CTRL_b.CLKEN = 0;
375 
376     return AM_HAL_STATUS_SUCCESS;
377 }
378 
379 //*****************************************************************************
380 //
381 // Enable the PDM.
382 //
383 //*****************************************************************************
384 uint32_t
am_hal_pdm_enable(void * pHandle)385 am_hal_pdm_enable(void *pHandle)
386 {
387     //
388     // Check the handle.
389     //
390     AM_HAL_PDM_HANDLE_CHECK(pHandle);
391 
392     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
393     uint32_t ui32Module = pState->ui32Module;
394 
395     PDMn(ui32Module)->CTRL_b.RSTB = 0;
396     delay_us(50);
397     PDMn(ui32Module)->CTRL_b.RSTB = 1;
398 
399     PDMn(ui32Module)->CTRL_b.CLKEN = 1;
400 
401     PDMn(ui32Module)->CTRL_b.EN    = 1;
402 
403     return AM_HAL_STATUS_SUCCESS;
404 }
405 
406 //*****************************************************************************
407 //
408 // Enable the PDM Control
409 //
410 //*****************************************************************************
411 uint32_t
am_hal_pdm_ctrl_enable(void * pHandle)412 am_hal_pdm_ctrl_enable(void *pHandle)
413 {
414     //
415     // Check the handle.
416     //
417     AM_HAL_PDM_HANDLE_CHECK(pHandle);
418 
419     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
420     uint32_t ui32Module = pState->ui32Module;
421 
422     PDMn(ui32Module)->CTRL_b.EN    = 1;
423 
424     return AM_HAL_STATUS_SUCCESS;
425 }
426 
427 //*****************************************************************************
428 //
429 // Enable the PDM CLK
430 //
431 //*****************************************************************************
432 uint32_t
am_hal_pdm_clk_enable(void * pHandle)433 am_hal_pdm_clk_enable(void *pHandle)
434 {
435     //
436     // Check the handle.
437     //
438     AM_HAL_PDM_HANDLE_CHECK(pHandle);
439 
440     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
441     uint32_t ui32Module = pState->ui32Module;
442 
443     PDMn(ui32Module)->CTRL_b.CLKEN = 1;
444 
445     return AM_HAL_STATUS_SUCCESS;
446 }
447 
448 //*****************************************************************************
449 //
450 // Reset the PDM.
451 //
452 //*****************************************************************************
453 uint32_t
am_hal_pdm_reset(void * pHandle)454 am_hal_pdm_reset(void *pHandle)
455 {
456     //
457     // Check the handle.
458     //
459     AM_HAL_PDM_HANDLE_CHECK(pHandle);
460 
461     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
462     uint32_t ui32Module = pState->ui32Module;
463 
464     PDMn(ui32Module)->CTRL_b.RSTB = 1;
465 
466     return AM_HAL_STATUS_SUCCESS;
467 }
468 
469 //*****************************************************************************
470 //
471 // Disable the PDM.
472 //
473 //*****************************************************************************
474 uint32_t
am_hal_pdm_disable(void * pHandle)475 am_hal_pdm_disable(void *pHandle)
476 {
477     //
478     // Check the handle.
479     //
480     AM_HAL_PDM_HANDLE_CHECK(pHandle);
481 
482     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
483     uint32_t ui32Module = pState->ui32Module;
484 
485     if (am_hal_pdm_dma_disable(pHandle) != AM_HAL_STATUS_SUCCESS)
486     {
487         PDMn(ui32Module)->DMACFG_b.DMAEN = 0;
488     }
489 
490     PDMn(ui32Module)->CTRL_b.EN    = 0;
491     PDMn(ui32Module)->CTRL_b.CLKEN = 0;
492 
493     return AM_HAL_STATUS_SUCCESS;
494 }
495 
496 //*****************************************************************************
497 //
498 // Given the total number of bytes in a DMA transaction, find a reasonable
499 // threshold setting.
500 //
501 //*****************************************************************************
502 static uint32_t
find_dma_threshold(uint32_t ui32TotalCount)503 find_dma_threshold(uint32_t ui32TotalCount)
504 {
505     //
506     // Start with a threshold value of 24, and search downward for values that
507     // fit our criteria.
508     //
509     uint32_t ui32Threshold;
510     uint32_t ui32Minimum = AM_HAL_PDM_DMA_THRESHOLD_MIN;
511 
512     for ( ui32Threshold = 24; ui32Threshold >= ui32Minimum; ui32Threshold -= 4 )
513     {
514         //
515         // With our loop parameters, we've already guaranteed that the
516         // threshold will be no higher than 24, and that it will be divisible
517         // by 4. The only remaining requirement is that ui32TotalCount must
518         // also be divisible by the threshold.
519         //
520         if ((ui32TotalCount % ui32Threshold) == 0)
521         {
522             break;
523         }
524     }
525 
526     //
527     // If we found an appropriate value, we'll return it here. Otherwise, we
528     // will return zero.
529     //
530     if (ui32Threshold < ui32Minimum)
531     {
532         ui32Threshold = 0;
533     }
534 
535     return ui32Threshold;
536 }
537 
538 //*****************************************************************************
539 //
540 // Starts a DMA transaction from the PDM directly to SRAM
541 //
542 //*****************************************************************************
543 uint32_t
am_hal_pdm_dma_start(void * pHandle,am_hal_pdm_transfer_t * pTransferCfg)544 am_hal_pdm_dma_start(void *pHandle, am_hal_pdm_transfer_t *pTransferCfg)
545 {
546     //
547     // Check the handle.
548     //
549     AM_HAL_PDM_HANDLE_CHECK(pHandle);
550 
551     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
552     uint32_t ui32Module = pState->ui32Module;
553 
554 #if 0 //ndef AM_HAL_DISABLE_API_VALIDATION
555     //
556     // Check for DMA to/from DTCM.
557     //
558     if ( (pTransferCfg->ui32TargetAddr >= AM_HAL_SYSTEM_MCU_DTCM_ADDR) &&
559       (pTransferCfg->ui32TargetAddr <= AM_HAL_SYSTEM_MCU_DTCM_ADDR + AM_HAL_SYSTEM_MCU_DTCM_SIZE) )
560     {
561       return AM_HAL_STATUS_OUT_OF_RANGE;
562     }
563 #endif
564 
565     // Configure Pingpong Buffer
566     pState->ui32BufferPtr  = \
567     pState->ui32BufferPing = pTransferCfg->ui32TargetAddr;
568     pState->ui32BufferPong = pTransferCfg->ui32TargetAddrReverse;
569 
570     //
571     // Find an appropriate threshold size for this transfer.
572     //
573     uint32_t ui32Threshold = find_dma_threshold(pTransferCfg->ui32TotalCount);
574 
575     //
576     // If we didn't find a threshold that will work, throw an error.
577     //
578     if (ui32Threshold == 0)
579     {
580         return AM_HAL_PDM_STATUS_BAD_TOTALCOUNT;
581     }
582 
583     PDMn(ui32Module)->FIFOTHR = ui32Threshold;
584 
585     //
586     // Configure DMA.
587     //
588     PDMn(ui32Module)->DMACFG = 0;
589     //PDMn(ui32Module)->DMACFG_b.DMAPRI = PDM0_DMACFG_DMAPRI_LOW;
590     //PDMn(ui32Module)->DMACFG_b.DMADIR = PDM0_DMACFG_DMADIR_P2M;
591     PDMn(ui32Module)->DMATOTCOUNT = pTransferCfg->ui32TotalCount;
592     PDMn(ui32Module)->DMATARGADDR = pTransferCfg->ui32TargetAddr;
593 
594     //
595     // Make sure the trigger is set for threshold.
596     //
597     PDMn(ui32Module)->DMATRIGEN_b.DTHR = 1;
598 
599     //
600     // Enable DMA
601     //
602     PDMn(ui32Module)->DMACFG_b.DMAEN = PDM0_DMACFG_DMAEN_EN;
603 
604     return AM_HAL_STATUS_SUCCESS;
605 }
606 
am_hal_pdm_dma_reset_count(uint32_t count)607 void am_hal_pdm_dma_reset_count(uint32_t count)
608 {
609   PDMn(0)->DMATOTCOUNT = count;
610 }
611 
612 //*****************************************************************************
613 //
614 // Flush the PDM FIFO
615 //
616 //*****************************************************************************
617 uint32_t
am_hal_pdm_fifo_flush(void * pHandle)618 am_hal_pdm_fifo_flush(void *pHandle)
619 {
620     //
621     // Check the handle.
622     //
623     AM_HAL_PDM_HANDLE_CHECK(pHandle);
624 
625     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
626     uint32_t ui32Module = pState->ui32Module;
627 
628     PDMn(ui32Module)->FIFOFLUSH = 1;
629 
630     return AM_HAL_STATUS_SUCCESS;
631 }
632 
633 //*****************************************************************************
634 //
635 // set the PDM FIFO Threshold value
636 //
637 //*****************************************************************************
638 uint32_t
am_hal_pdm_fifo_threshold_setup(void * pHandle,uint32_t value)639 am_hal_pdm_fifo_threshold_setup(void *pHandle, uint32_t value)
640 {
641     //
642     // Check the handle.
643     //
644     AM_HAL_PDM_HANDLE_CHECK(pHandle);
645 
646     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
647     uint32_t ui32Module = pState->ui32Module;
648 
649     PDMn(ui32Module)->FIFOTHR = value;
650 
651     return AM_HAL_STATUS_SUCCESS;
652 }
653 
654 //*****************************************************************************
655 //
656 // PDM interrupt service routine
657 //
658 //*****************************************************************************
am_hal_pdm_interrupt_service(void * pHandle,uint32_t ui32IntMask,am_hal_pdm_transfer_t * pTransferCfg)659 uint32_t am_hal_pdm_interrupt_service(void *pHandle, uint32_t ui32IntMask, am_hal_pdm_transfer_t *pTransferCfg)
660 {
661     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
662     uint32_t ui32Module = pState->ui32Module;
663 
664     if (ui32IntMask & AM_HAL_PDM_INT_DCMP)
665     {
666         PDMn(ui32Module)->DMATARGADDR = pState->ui32BufferPtr = (pState->ui32BufferPtr == pState->ui32BufferPong)? pState->ui32BufferPing: pState->ui32BufferPong;
667         PDMn(ui32Module)->DMATOTCOUNT = pTransferCfg->ui32TotalCount;
668     }
669 
670     if (ui32IntMask & AM_HAL_PDM_INT_OVF)
671     {
672 
673         am_hal_pdm_fifo_flush(pHandle);
674     }
675 
676     return AM_HAL_STATUS_SUCCESS;
677 }
678 
679 //*****************************************************************************
680 //
681 // Interrupt enable.
682 //
683 //*****************************************************************************
684 uint32_t
am_hal_pdm_interrupt_enable(void * pHandle,uint32_t ui32IntMask)685 am_hal_pdm_interrupt_enable(void *pHandle, uint32_t ui32IntMask)
686 {
687     //
688     // Check the handle.
689     //
690     AM_HAL_PDM_HANDLE_CHECK(pHandle);
691 
692     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
693     uint32_t ui32Module = pState->ui32Module;
694 
695     PDMn(ui32Module)->INTEN |= ui32IntMask;
696 
697     return AM_HAL_STATUS_SUCCESS;
698 }
699 
700 //*****************************************************************************
701 //
702 // Interrupt disable.
703 //
704 //*****************************************************************************
705 uint32_t
am_hal_pdm_interrupt_disable(void * pHandle,uint32_t ui32IntMask)706 am_hal_pdm_interrupt_disable(void *pHandle, uint32_t ui32IntMask)
707 {
708     //
709     // Check the handle.
710     //
711     AM_HAL_PDM_HANDLE_CHECK(pHandle);
712 
713     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
714     uint32_t ui32Module = pState->ui32Module;
715 
716     PDMn(ui32Module)->INTEN &= ~ui32IntMask;
717 
718     return AM_HAL_STATUS_SUCCESS;
719 }
720 
721 //*****************************************************************************
722 //
723 // Interrupt clear.
724 //
725 //*****************************************************************************
726 uint32_t
am_hal_pdm_interrupt_clear(void * pHandle,uint32_t ui32IntMask)727 am_hal_pdm_interrupt_clear(void *pHandle, uint32_t ui32IntMask)
728 {
729     //
730     // Check the handle.
731     //
732     AM_HAL_PDM_HANDLE_CHECK(pHandle);
733 
734     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
735     uint32_t ui32Module = pState->ui32Module;
736 
737     PDMn(ui32Module)->INTCLR = ui32IntMask;
738 
739     return AM_HAL_STATUS_SUCCESS;
740 }
741 
742 //*****************************************************************************
743 //
744 // Returns the interrupt status.
745 //
746 //*****************************************************************************
747 uint32_t
am_hal_pdm_interrupt_status_get(void * pHandle,uint32_t * pui32Status,bool bEnabledOnly)748 am_hal_pdm_interrupt_status_get(void *pHandle, uint32_t *pui32Status, bool bEnabledOnly)
749 {
750     //
751     // Check the handle.
752     //
753     AM_HAL_PDM_HANDLE_CHECK(pHandle);
754 
755     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
756     uint32_t ui32Module = pState->ui32Module;
757 
758     //
759     // If requested, only return the interrupts that are enabled.
760     //
761     if ( bEnabledOnly )
762     {
763         *pui32Status = PDMn(ui32Module)->INTSTAT;
764         *pui32Status &= PDMn(ui32Module)->INTEN;
765     }
766     else
767     {
768         *pui32Status = PDMn(ui32Module)->INTSTAT;
769     }
770 
771     return AM_HAL_STATUS_SUCCESS;
772 }
773 
774 //*****************************************************************************
775 //
776 // Get the DMA Bufffer.
777 //
778 //*****************************************************************************
779 uint32_t
am_hal_pdm_dma_get_buffer(void * pHandle)780 am_hal_pdm_dma_get_buffer(void *pHandle)
781 {
782     uint32_t ui32BufferPtr;
783     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
784 
785     // Invalidate DAXI to make sure CPU sees the new data when loaded
786     am_hal_daxi_control(AM_HAL_DAXI_CONTROL_INVALIDATE, 0);
787 
788     ui32BufferPtr = (pState->ui32BufferPtr == pState->ui32BufferPong)? pState->ui32BufferPing: pState->ui32BufferPong;
789 
790     return ui32BufferPtr;
791 }
792 
793 //*****************************************************************************
794 //
795 // Read the FIFO.
796 //
797 //*****************************************************************************
798 uint32_t
am_hal_pdm_fifo_data_read(void * pHandle)799 am_hal_pdm_fifo_data_read(void *pHandle)
800 {
801     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
802     uint32_t ui32Module = pState->ui32Module;
803 
804     return PDMn(ui32Module)->FIFOREAD;
805 }
806 
807 //*****************************************************************************
808 //
809 // Read the FIFOs.
810 //
811 //*****************************************************************************
am_hal_pdm_fifo_data_reads(void * pHandle,uint8_t * buffer,uint32_t size)812 uint32_t am_hal_pdm_fifo_data_reads(void *pHandle, uint8_t* buffer, uint32_t size)
813 {
814     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
815     uint32_t ui32Module = pState->ui32Module;
816 
817     uint32_t fiforead;
818 
819     uint8_t buf_size = 0;
820     for ( uint32_t i = 0; i < size; i++ )
821     {
822         //if ((i%2) != 0)
823         //{
824         //    fiforead = PDMn(ui32Module)->FIFOREAD;
825         //}
826         //else
827         {
828             fiforead = PDMn(ui32Module)->FIFOREAD; //left/right channel
829             buffer[buf_size++] = fiforead & 0xFF;
830             buffer[buf_size++] = (fiforead & 0xFF00)>>8;
831             buffer[buf_size++] = (fiforead & 0x00FF0000)>>16;
832         }
833     }
834 
835     return 0;
836 }
837 
838 //*****************************************************************************
839 //
840 // am_hal_pdm_fifo_count_get
841 //
842 //*****************************************************************************
am_hal_pdm_fifo_count_get(void * pHandle)843 uint32_t am_hal_pdm_fifo_count_get(void *pHandle)
844 {
845     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
846     uint32_t ui32Module = pState->ui32Module;
847 
848     return PDMn(ui32Module)->FIFOCNT;
849 }
850 
851 //*****************************************************************************
852 //
853 // am_hal_pdm_dma_state
854 //
855 //*****************************************************************************
am_hal_pdm_dma_state(void * pHandle)856 uint32_t am_hal_pdm_dma_state(void *pHandle)
857 {
858     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
859     uint32_t ui32Module = pState->ui32Module;
860 
861     return PDMn(ui32Module)->DMASTAT;
862 }
863 
864 //*****************************************************************************
865 //
866 // disable PDM DMA
867 //
868 //*****************************************************************************
869 uint32_t
am_hal_pdm_dma_disable(void * pHandle)870 am_hal_pdm_dma_disable(void *pHandle)
871 {
872     //
873     // Check the handle.
874     //
875     AM_HAL_PDM_HANDLE_CHECK(pHandle);
876     am_hal_pdm_state_t *pState = (am_hal_pdm_state_t *) pHandle;
877     uint32_t ui32Module = pState->ui32Module;
878 
879     //
880     // disable this pdm module while disabling DMA
881     //
882     uint32_t ui32CtrlSaved = PDMn(ui32Module)->CTRL;
883 
884     PDMn(ui32Module)->CTRL = ui32CtrlSaved & ~PDM0_CTRL_CLKEN_Msk;
885     PDMn(ui32Module)->DMACFG_b.DMAEN = 0;
886 
887     //
888     // disable dma interrupts
889     //
890     PDMn(ui32Module)->INTEN &= ~(AM_HAL_PDM_INT_DERR | AM_HAL_PDM_INT_DCMP);
891 
892     //
893     // clear interrupts
894     //
895     PDMn(ui32Module)->INTCLR = (AM_HAL_PDM_INT_DERR | AM_HAL_PDM_INT_DCMP);
896 
897 
898     PDMn(ui32Module)->DMATOTCOUNT = 0;
899 
900     //
901     // restore control register
902     //
903     PDMn(ui32Module)->CTRL = ui32CtrlSaved;
904 
905     return AM_HAL_STATUS_SUCCESS;
906 }
907 
908 //*****************************************************************************
909 //
910 // End Doxygen group.
911 //! @}
912 //
913 //*****************************************************************************
914