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