1 /*
2  * SPDX-FileCopyrightText: 2019-2025 SiFli Technologies(Nanjing) Co., Ltd
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "bf0_hal.h"
8 
9 
10 #if defined(HAL_PDM_MODULE_ENABLED) ||defined(_SIFLI_DOXYGEN_)
11 
12 static void PDM_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
13 static void PDM_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
14 static void PDM_DMAError(DMA_HandleTypeDef *hdma);
15 static HAL_StatusTypeDef PDM_Config(PDM_HandleTypeDef *hpdm, PDM_ConfigureTypeDef type);
16 static HAL_StatusTypeDef PDM_ConfigDMA(PDM_HandleTypeDef *hpdm);
17 
18 
19 
HAL_PDM_Init(PDM_HandleTypeDef * hpdm)20 HAL_StatusTypeDef HAL_PDM_Init(PDM_HandleTypeDef *hpdm)
21 {
22 
23     if (hpdm == NULL)
24     {
25         return HAL_ERROR;
26     }
27 
28     if (hpdm->State == PDM_STATE_RESET)
29     {
30         /* Allocate lock resource and initialize it */
31         hpdm->Lock = HAL_UNLOCKED;
32 
33         /* Init the low level hardware : GPIO, CLOCK, NVIC... */
34         HAL_PDM_MspInit(hpdm);
35     }
36 
37     hpdm->State = PDM_STATE_BUSY;
38 
39     if (hpdm->Instance == hwp_pdm1)
40         HAL_RCC_ResetModule(RCC_MOD_PDM1);
41 #ifdef hwp_pdm2
42     else if (hpdm->Instance == hwp_pdm2)
43         HAL_RCC_ResetModule(RCC_MOD_PDM2);
44 #endif
45 
46     __HAL_PDM_DISABLE(hpdm);
47 
48     PDM_Config(hpdm, PDM_CFG_CHANNEL | PDM_CFG_SAMPLERATE | PDM_CFG_DEPTH);
49 
50 
51 #if 0
52     hpdm->Instance->COMP_CFG0 |= PDM_COMP_CFG0_COMP_BYPASS;
53     hpdm->Instance->COMP_CFG0 &= ~PDM_COMP_CFG0_COMP_COEFF0;
54     hpdm->Instance->COMP_CFG0 |= (0x15c << PDM_COMP_CFG0_COMP_COEFF0_Pos);
55     hpdm->Instance->COMP_CFG1 &= ~PDM_COMP_CFG1_COMP_COEFF1;
56     hpdm->Instance->COMP_CFG1 |= (0xb31 << PDM_COMP_CFG1_COMP_COEFF1_Pos);
57     hpdm->Instance->COMP_CFG1 &= ~PDM_COMP_CFG1_COMP_COEFF2;
58     hpdm->Instance->COMP_CFG1 |= (0x57e << PDM_COMP_CFG1_COMP_COEFF2_Pos);
59 #endif
60 
61     hpdm->Instance->HPF_CFG &= ~PDM_HPF_CFG_HPF_BYPASS;
62     hpdm->Instance->HPF_CFG &= ~PDM_HPF_CFG_HPF_COEFF;
63     hpdm->Instance->HPF_CFG |= (0x7 << PDM_HPF_CFG_HPF_COEFF_Pos);
64 
65     hpdm->Instance->PGA_CFG &= ~PDM_PGA_CFG_PGA_GAIN_L;
66     hpdm->Instance->PGA_CFG |= (0x26 << PDM_PGA_CFG_PGA_GAIN_L_Pos);
67     hpdm->Instance->PGA_CFG &= ~PDM_PGA_CFG_PGA_GAIN_R;
68     hpdm->Instance->PGA_CFG |= (0x26 << PDM_PGA_CFG_PGA_GAIN_R_Pos);
69 
70 #if 0
71     hpdm->Instance->LPF_CFG0 &= ~PDM_LPF_CFG0_LPF_COEFF00;
72     hpdm->Instance->LPF_CFG0 |= (0xffa << PDM_LPF_CFG0_LPF_COEFF00_Pos);
73     hpdm->Instance->LPF_CFG0 &= ~PDM_LPF_CFG0_LPF_COEFF01;
74     hpdm->Instance->LPF_CFG0 |= (0x005 << PDM_LPF_CFG0_LPF_COEFF01_Pos);
75 
76     hpdm->Instance->LPF_CFG1 &= ~PDM_LPF_CFG1_LPF_COEFF02;
77     hpdm->Instance->LPF_CFG1 |= (0x028 << PDM_LPF_CFG1_LPF_COEFF02_Pos);
78     hpdm->Instance->LPF_CFG1 &= ~PDM_LPF_CFG1_LPF_COEFF03;
79     hpdm->Instance->LPF_CFG1 |= (0x01f << PDM_LPF_CFG1_LPF_COEFF03_Pos);
80 
81     hpdm->Instance->LPF_CFG2 &= ~PDM_LPF_CFG2_LPF_COEFF04;
82     hpdm->Instance->LPF_CFG2 |= (0xfc4 << PDM_LPF_CFG2_LPF_COEFF04_Pos);
83     hpdm->Instance->LPF_CFG2 &= ~PDM_LPF_CFG2_LPF_COEFF05;
84     hpdm->Instance->LPF_CFG2 |= (0xfaa << PDM_LPF_CFG2_LPF_COEFF05_Pos);
85 
86     hpdm->Instance->LPF_CFG3 &= ~PDM_LPF_CFG3_LPF_COEFF06;
87     hpdm->Instance->LPF_CFG3 |= (0x050 << PDM_LPF_CFG3_LPF_COEFF06_Pos);
88     hpdm->Instance->LPF_CFG3 &= ~PDM_LPF_CFG3_LPF_COEFF07;
89     hpdm->Instance->LPF_CFG3 |= (0x0b5 << PDM_LPF_CFG3_LPF_COEFF07_Pos);
90 
91     hpdm->Instance->LPF_CFG4 &= ~PDM_LPF_CFG4_LPF_COEFF08;
92     hpdm->Instance->LPF_CFG4 |= (0xfa0 << PDM_LPF_CFG4_LPF_COEFF08_Pos);
93     hpdm->Instance->LPF_CFG4 &= ~PDM_LPF_CFG4_LPF_COEFF09;
94     hpdm->Instance->LPF_CFG4 |= (0xe80 << PDM_LPF_CFG4_LPF_COEFF09_Pos);
95 
96     hpdm->Instance->LPF_CFG5 &= ~PDM_LPF_CFG5_LPF_COEFF10;
97     hpdm->Instance->LPF_CFG5 |= (0x06b << PDM_LPF_CFG5_LPF_COEFF10_Pos);
98     hpdm->Instance->LPF_CFG5 &= ~PDM_LPF_CFG5_LPF_COEFF11;
99     hpdm->Instance->LPF_CFG5 |= (0x506 << PDM_LPF_CFG5_LPF_COEFF11_Pos);
100 
101     hpdm->Instance->LPF_CFG6 &= ~PDM_LPF_CFG6_LPF_COEFF12;
102     hpdm->Instance->LPF_CFG6 |= (0x791 << PDM_LPF_CFG6_LPF_COEFF12_Pos);
103 #endif
104 
105     hpdm->Instance->LPF_CFG6 &= ~PDM_LPF_CFG6_LPF_BYPASS;
106 
107 
108 
109     hpdm->ErrorCode = PDM_ERROR_NONE;
110     hpdm->State     = PDM_STATE_READY;
111 
112 
113     return HAL_OK;
114 }
115 
HAL_PDM_DeInit(PDM_HandleTypeDef * hpdm)116 HAL_StatusTypeDef HAL_PDM_DeInit(PDM_HandleTypeDef *hpdm)
117 {
118     __HAL_PDM_DISABLE(hpdm);
119     hpdm->State = PDM_STATE_RESET;
120 
121     return HAL_OK;
122 }
123 
HAL_PDM_MspInit(PDM_HandleTypeDef * hpdm)124 __weak void HAL_PDM_MspInit(PDM_HandleTypeDef *hpdm)
125 {
126     /* Prevent unused argument(s) compilation warning */
127     UNUSED(hpdm);
128 
129     /* NOTE : This function should not be modified, when the callback is needed,
130               the HAL_PDM_MspInit should be implemented in the user file
131      */
132 }
133 
HAL_PDM_MspDeInit(PDM_HandleTypeDef * hpdm)134 __weak void HAL_PDM_MspDeInit(PDM_HandleTypeDef *hpdm)
135 {
136     /* Prevent unused argument(s) compilation warning */
137     UNUSED(hpdm);
138 
139     /* NOTE : This function should not be modified, when the callback is needed,
140               the HAL_PDM_MspDeInit should be implemented in the user file
141      */
142 }
143 
144 
HAL_PDM_Set_Gain(PDM_HandleTypeDef * hpdm,PDM_ChannelTypeDef channel,uint8_t value)145 HAL_StatusTypeDef HAL_PDM_Set_Gain(PDM_HandleTypeDef *hpdm, PDM_ChannelTypeDef channel, uint8_t value)
146 {
147     uint8_t hw_gain = value;
148     switch (channel)
149     {
150     case PDM_CHANNEL_LEFT_ONLY:
151         hpdm->Instance->PGA_CFG &= ~PDM_PGA_CFG_PGA_GAIN_L;
152         hpdm->Instance->PGA_CFG |= (hw_gain << PDM_PGA_CFG_PGA_GAIN_L_Pos);
153         break;
154 
155     case PDM_CHANNEL_RIGHT_ONLY:
156         hpdm->Instance->PGA_CFG &= ~PDM_PGA_CFG_PGA_GAIN_R;
157         hpdm->Instance->PGA_CFG |= (hw_gain << PDM_PGA_CFG_PGA_GAIN_R_Pos);
158         break;
159 
160     case PDM_CHANNEL_STEREO:
161     case PDM_CHANNEL_STEREO_SWAP:
162         hpdm->Instance->PGA_CFG &= ~(PDM_PGA_CFG_PGA_GAIN_L | PDM_PGA_CFG_PGA_GAIN_R);
163         hpdm->Instance->PGA_CFG |= (hw_gain << PDM_PGA_CFG_PGA_GAIN_L_Pos) | (hw_gain << PDM_PGA_CFG_PGA_GAIN_R_Pos);
164         break;
165 
166     default:
167         HAL_ASSERT(0);
168         break;
169     }
170 
171     return HAL_OK;
172 }
173 
HAL_PDM_Config(PDM_HandleTypeDef * hpdm,PDM_ConfigureTypeDef type)174 HAL_StatusTypeDef HAL_PDM_Config(PDM_HandleTypeDef *hpdm, PDM_ConfigureTypeDef type)
175 {
176 
177     if (hpdm == NULL)
178     {
179         return HAL_ERROR;
180     }
181     if (hpdm->State != PDM_STATE_READY)
182     {
183         return  HAL_BUSY;
184     }
185 
186 
187     return PDM_Config(hpdm, type);
188 }
189 
HAL_PDM_Receive_DMA(PDM_HandleTypeDef * hpdm,uint8_t * pData,uint32_t Size)190 HAL_StatusTypeDef HAL_PDM_Receive_DMA(PDM_HandleTypeDef *hpdm, uint8_t *pData, uint32_t Size)
191 {
192     HAL_StatusTypeDef errorcode = HAL_OK;
193 
194     uint32_t fifo_addr, transfw;
195 
196     /* check rx dma handle */
197     HAL_ASSERT(hpdm->hdmarx != NULL);
198     HAL_ASSERT(HAL_ALIGN((uint32_t)pData, 0x4));
199     HAL_ASSERT(HAL_ALIGN(Size, 0x4));
200 
201 
202     /* Process Locked */
203     __HAL_LOCK(hpdm);
204     __HAL_PDM_DISABLE_IT(hpdm, (PDM_INT_MSK_INT_MASK_R | PDM_INT_MSK_INT_MASK_L));
205 
206     if (hpdm->State != PDM_STATE_READY)
207     {
208         errorcode = HAL_BUSY;
209         goto error;
210     }
211 
212     if ((pData == NULL) || (Size == 0U))
213     {
214         errorcode = HAL_ERROR;
215         goto error;
216     }
217 
218     if (HAL_OK != PDM_ConfigDMA(hpdm))
219     {
220         errorcode = HAL_ERROR;
221         goto error;
222     }
223 
224     /* Set the transaction information */
225     hpdm->State       = PDM_STATE_BUSY_RX;
226     hpdm->ErrorCode   = PDM_ERROR_NONE;
227     hpdm->pRxBuffPtr  = (uint8_t *)pData;
228     hpdm->RxXferSize  = Size;
229 
230 
231 
232     /* Set the PDM RxDMA Half transfer complete callback */
233     hpdm->hdmarx->XferHalfCpltCallback = PDM_DMAHalfReceiveCplt;
234 
235     /* Set the PDM Rx DMA transfer complete callback */
236     hpdm->hdmarx->XferCpltCallback = PDM_DMAReceiveCplt;
237 
238     /* Set the DMA error callback */
239     hpdm->hdmarx->XferErrorCallback = PDM_DMAError;
240 
241     /* Set the DMA AbortCpltCallback */
242     hpdm->hdmarx->XferAbortCallback = NULL;
243 
244 
245     if (PDM_CHANNEL_RIGHT_ONLY == hpdm->Init.Channels)
246     {
247         fifo_addr = (uint32_t)&hpdm->Instance->DATA_R;
248     }
249     else
250     {
251         fifo_addr = (uint32_t)&hpdm->Instance->DATA_L;
252     }
253 
254 #ifdef  SF32LB55X
255     if (PDM_CHANNEL_DEPTH_8BIT == hpdm->Init.ChannelDepth)
256     {
257         /*32bit -> 8bit*/
258         fifo_addr += 0x2;
259         transfw = hpdm->RxXferSize;
260     }
261     else
262 #endif
263     {
264         transfw = hpdm->RxXferSize >> 2;
265     }
266 
267     /* Enable the PDM Error Interrupt Bit */
268     __HAL_PDM_ENABLE_IT(hpdm, (PDM_INT_MSK_INT_MASK_R | PDM_INT_MSK_INT_MASK_L));
269 
270     /* Enable the Rx DMA Stream/Channel  */
271     HAL_DMA_Start_IT(hpdm->hdmarx, (uint32_t)fifo_addr, (uint32_t)hpdm->pRxBuffPtr, transfw);
272 
273     /* Check if the PDM is already enabled */
274     if ((hpdm->Instance->CFG0 & PDM_CFG0_PDMCOREEN) != PDM_CFG0_PDMCOREEN)
275     {
276         /* Enable PDM peripheral */
277         __HAL_PDM_ENABLE(hpdm);
278     }
279 
280 
281 error:
282     /* Process Unlocked */
283     __HAL_UNLOCK(hpdm);
284     return errorcode;
285 }
286 
287 
288 
289 /**
290   * @brief Stop the DMA Transfer.
291   * @param  hpdm pointer to a PDM_HandleTypeDef structure that contains
292   *               the configuration information for the specified PDM module.
293   * @retval HAL status
294   */
HAL_PDM_DMAStop(PDM_HandleTypeDef * hpdm)295 HAL_StatusTypeDef HAL_PDM_DMAStop(PDM_HandleTypeDef *hpdm)
296 {
297     /* The Lock is not implemented on this API to allow the user application
298        to call the HAL PDM API under callbacks HAL_PDM_TxCpltCallback() or HAL_PDM_RxCpltCallback() or HAL_PDM_TxRxCpltCallback():
299        when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
300        and the correspond call back is executed HAL_PDM_TxCpltCallback() or HAL_PDM_RxCpltCallback() or HAL_PDM_TxRxCpltCallback()
301        */
302 
303     /* Abort the PDM DMA rx Stream/Channel  */
304     if (hpdm->hdmarx != NULL)
305     {
306         HAL_DMA_Abort(hpdm->hdmarx);
307     }
308 
309     /* Disable the PDM DMA Tx & Rx requests */
310     //CLEAR_BIT(hpdm->Instance->CR2, PDM_CR2_TXDMAEN | PDM_CR2_RXDMAEN);
311     hpdm->State = PDM_STATE_READY;
312     return HAL_OK;
313 }
314 
HAL_PDM_IRQHandler(PDM_HandleTypeDef * hpdm)315 void HAL_PDM_IRQHandler(PDM_HandleTypeDef *hpdm)
316 {
317     uint32_t err = hpdm->Instance->INT_ST;
318     uint32_t err_mask = hpdm->Instance->INT_MSK;
319 
320     if (err & PDM_INT_ST_OVERFLOW_R)
321     {
322         hpdm->Instance->INT_CLR = PDM_INT_CLR_INT_CLR_R;
323         if (0 == (err_mask & PDM_INT_MSK_INT_MASK_R))
324             hpdm->ErrorCode |= PDM_ERROR_OVERFLOW_R;
325         else
326         {
327             ;//Ignore
328         }
329     }
330 
331     if (err & PDM_INT_ST_OVERFLOW_L)
332     {
333         hpdm->Instance->INT_CLR = PDM_INT_CLR_INT_CLR_L;
334         if (0 == (err_mask & PDM_INT_MSK_INT_MASK_L))
335             hpdm->ErrorCode |= PDM_ERROR_OVERFLOW_L;
336         else
337         {
338             ;//Ignore
339         }
340     }
341 }
342 
343 
HAL_PDM_RxHalfCpltCallback(PDM_HandleTypeDef * hpdm)344 __weak void HAL_PDM_RxHalfCpltCallback(PDM_HandleTypeDef *hpdm)
345 {
346     /* Prevent unused argument(s) compilation warning */
347     UNUSED(hpdm);
348 
349     /* NOTE : This function should not be modified, when the callback is needed,
350               the HAL_PDM_RxHalfCpltCallback should be implemented in the user file
351      */
352 }
353 
HAL_PDM_RxCpltCallback(PDM_HandleTypeDef * hpdm)354 __weak void HAL_PDM_RxCpltCallback(PDM_HandleTypeDef *hpdm)
355 {
356     /* Prevent unused argument(s) compilation warning */
357     UNUSED(hpdm);
358 
359     /* NOTE : This function should not be modified, when the callback is needed,
360               the HAL_PDM_RxCpltCallback should be implemented in the user file
361      */
362 }
363 
HAL_PDM_ErrorCallback(PDM_HandleTypeDef * hpdm)364 __weak void HAL_PDM_ErrorCallback(PDM_HandleTypeDef *hpdm)
365 {
366     /* Prevent unused argument(s) compilation warning */
367     UNUSED(hpdm);
368 
369     /* NOTE : This function should not be modified, when the callback is needed,
370               the HAL_PDM_ErrorCallback should be implemented in the user file
371      */
372 }
373 
HAL_PDM_AbortCpltCallback(PDM_HandleTypeDef * hpdm)374 __weak void HAL_PDM_AbortCpltCallback(PDM_HandleTypeDef *hpdm)
375 {
376     /* Prevent unused argument(s) compilation warning */
377     UNUSED(hpdm);
378 
379     /* NOTE : This function should not be modified, when the callback is needed,
380               the HAL_PDM_AbortCpltCallback should be implemented in the user file
381      */
382 }
383 
384 
385 /**
386   * @brief DMA PDM receive process complete callback.
387   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
388   *               the configuration information for the specified DMA module.
389   * @retval None
390   */
PDM_DMAReceiveCplt(DMA_HandleTypeDef * hdma)391 static void PDM_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
392 {
393     PDM_HandleTypeDef *hpdm = (PDM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
394 
395     /* DMA Normal Mode */
396     if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
397     {
398         /* Disable ERR interrupt */
399         __HAL_PDM_DISABLE_IT(hpdm, (PDM_INT_MSK_INT_MASK_R | PDM_INT_MSK_INT_MASK_L));
400 
401 
402         hpdm->RxXferSize = 0U;
403         hpdm->State = PDM_STATE_READY;
404 
405 
406         if (hpdm->ErrorCode != PDM_ERROR_NONE)
407         {
408             HAL_PDM_ErrorCallback(hpdm);
409             return;
410         }
411     }
412     HAL_PDM_RxCpltCallback(hpdm);
413 
414     if (PDM_MODE_ONCE == hpdm->Init.Mode)
415         __HAL_PDM_DISABLE(hpdm);
416 
417 }
418 
419 /**
420   * @brief  DMA PDM half receive process complete callback
421   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
422   *               the configuration information for the specified DMA module.
423   * @retval None
424   */
PDM_DMAHalfReceiveCplt(DMA_HandleTypeDef * hdma)425 static void PDM_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
426 {
427     PDM_HandleTypeDef *hpdm = (PDM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
428 
429     HAL_PDM_RxHalfCpltCallback(hpdm);
430 }
431 
432 
433 /**
434   * @brief  DMA PDM communication error callback.
435   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
436   *               the configuration information for the specified DMA module.
437   * @retval None
438   */
PDM_DMAError(DMA_HandleTypeDef * hdma)439 static void PDM_DMAError(DMA_HandleTypeDef *hdma)
440 {
441     PDM_HandleTypeDef *hpdm = (PDM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
442 
443     SET_BIT(hpdm->ErrorCode, PDM_ERROR_DMA);
444     hpdm->State = PDM_STATE_READY;
445     HAL_PDM_ErrorCallback(hpdm);
446 }
447 
448 
PDM_Config(PDM_HandleTypeDef * hpdm,PDM_ConfigureTypeDef type)449 static HAL_StatusTypeDef PDM_Config(PDM_HandleTypeDef *hpdm, PDM_ConfigureTypeDef type)
450 {
451     uint32_t cfg0_value, cfg_fifo, lpf_cfg, sinc_cfg;
452 
453     if (hpdm == NULL)
454     {
455         return HAL_ERROR;
456     }
457     cfg0_value = hpdm->Instance->CFG0;
458     cfg_fifo   = hpdm->Instance->FIFO_CFG;
459 
460     cfg_fifo &= ~PDM_FIFO_CFG_PDM_SHIFT_Msk;
461 
462     if (type & PDM_CFG_CHANNEL)
463     {
464         cfg0_value &= ~(PDM_CFG0_LEFT_EN | PDM_CFG0_RIGHT_EN | PDM_CFG0_STEREO_EN | PDM_CFG0_SWAP_EN);
465         cfg_fifo &= ~(PDM_FIFO_CFG_BYTE_CON | PDM_FIFO_CFG_RX_DMA_MSK_L | PDM_FIFO_CFG_RX_DMA_MSK_R);
466         switch (hpdm->Init.Channels)
467         {
468         case PDM_CHANNEL_LEFT_ONLY:
469             cfg0_value |= PDM_CFG0_LEFT_EN;
470             cfg_fifo   |= PDM_FIFO_CFG_RX_DMA_MSK_R; //mask rigth channel
471             break;
472 
473         case PDM_CHANNEL_RIGHT_ONLY:
474             cfg0_value |= PDM_CFG0_RIGHT_EN;
475             cfg_fifo   |= PDM_FIFO_CFG_RX_DMA_MSK_L; //mask left channel
476             break;
477 
478         case PDM_CHANNEL_STEREO:
479             cfg_fifo   |= PDM_FIFO_CFG_BYTE_CON;
480             cfg0_value |= PDM_CFG0_LEFT_EN | PDM_CFG0_RIGHT_EN | PDM_CFG0_STEREO_EN;
481 #ifdef SF32LB55X
482             if (PDM_CHANNEL_DEPTH_16BIT != hpdm->Init.ChannelDepth) HAL_ASSERT(0);
483 #endif /* SF32LB55X */
484             break;
485 
486         case PDM_CHANNEL_STEREO_SWAP:
487             cfg_fifo   |= PDM_FIFO_CFG_BYTE_CON;
488             cfg0_value |= (PDM_CFG0_LEFT_EN | PDM_CFG0_RIGHT_EN | PDM_CFG0_STEREO_EN | PDM_CFG0_SWAP_EN);
489 #ifdef SF32LB55X
490             if (PDM_CHANNEL_DEPTH_16BIT != hpdm->Init.ChannelDepth) HAL_ASSERT(0);
491 #endif /* SF32LB55X */
492             break;
493 
494         default:
495             HAL_ASSERT(0);
496             break;
497         }
498     }
499 
500     if (type & PDM_CFG_SAMPLERATE)
501     {
502         /*
503             Sample rate = clk_source / clk_div / sinc_rate / down_sample
504         */
505         lpf_cfg = hpdm->Instance->LPF_CFG6;
506         sinc_cfg = hpdm->Instance->SINC_CFG;
507 
508         lpf_cfg &= ~PDM_LPF_CFG6_LPF_DS;       /*0: down_sample=2   1: down_sample=4*/
509         sinc_cfg &= ~PDM_SINC_CFG_SINC_ORDER_SEL; /*0: sinc_order=3   1: sinc_order=4*/
510         sinc_cfg &= ~PDM_SINC_CFG_SINC_RATE;
511         cfg_fifo &= ~(PDM_FIFO_CFG_PDM_SHIFT);
512         switch (hpdm->Init.SampleRate)
513         {
514         case PDM_SAMPLE_8KHZ:
515             if (hpdm->Init.clkSrc == 9600000)
516             {
517                 cfg0_value &= ~PDM_CFG0_CLK_SEL; //9.6MHz source
518                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
519                 cfg0_value |= (4 << PDM_CFG0_CLK_DIV_Pos);
520                 sinc_cfg |= (75 << PDM_SINC_CFG_SINC_RATE_Pos);
521                 lpf_cfg |= PDM_LPF_CFG6_LPF_DS;
522                 //cfg_fifo |= (0x2 << PDM_FIFO_CFG_PDM_SHIFT_Pos); //Align to 24bit
523             }
524             else  if (hpdm->Init.clkSrc == 3072000)
525             {
526                 cfg0_value |= PDM_CFG0_CLK_SEL; //3.072MHz source
527                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
528                 cfg0_value |= (3 << PDM_CFG0_CLK_DIV_Pos);
529                 sinc_cfg |= (64 << PDM_SINC_CFG_SINC_RATE_Pos);
530                 //cfg_fifo |= (0x2 << PDM_FIFO_CFG_PDM_SHIFT_Pos); //Align to 24bit
531             }
532             break;
533         case PDM_SAMPLE_16KHZ:
534             if (hpdm->Init.clkSrc == 9600000)
535             {
536                 cfg0_value &= ~PDM_CFG0_CLK_SEL; //9.6MHz source
537                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
538                 cfg0_value |= (6 << PDM_CFG0_CLK_DIV_Pos);
539                 sinc_cfg |= (50 << PDM_SINC_CFG_SINC_RATE_Pos);
540                 //cfg_fifo |= (0x4 << PDM_FIFO_CFG_PDM_SHIFT_Pos);  //Align to 24bit
541             }
542             else if (hpdm->Init.clkSrc == 3072000)
543             {
544                 cfg0_value |= PDM_CFG0_CLK_SEL; //3.072MHz source
545                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
546                 cfg0_value |= (1 << PDM_CFG0_CLK_DIV_Pos);
547                 sinc_cfg |= (96 << PDM_SINC_CFG_SINC_RATE_Pos);
548             }
549             break;
550         case PDM_SAMPLE_32KHZ:
551             if (hpdm->Init.clkSrc == 9600000)
552             {
553                 cfg0_value &= ~PDM_CFG0_CLK_SEL; //9.6MHz source
554                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
555                 cfg0_value |= (6 << PDM_CFG0_CLK_DIV_Pos);
556                 sinc_cfg |= (25 << PDM_SINC_CFG_SINC_RATE_Pos);
557                 //lpf_cfg |= PDM_LPF_CFG6_LPF_DS;
558             }
559             else if (hpdm->Init.clkSrc == 3072000)
560             {
561 
562                 cfg0_value |= PDM_CFG0_CLK_SEL; //3.072MHz source
563                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
564                 cfg0_value |= (1 << PDM_CFG0_CLK_DIV_Pos);
565                 sinc_cfg |= (48 << PDM_SINC_CFG_SINC_RATE_Pos);
566             }
567             break;
568         case PDM_SAMPLE_48KHZ:
569             if (hpdm->Init.clkSrc == 9600000)
570             {
571                 cfg0_value &= ~PDM_CFG0_CLK_SEL; //9.6MHz source
572                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
573                 cfg0_value |= (4 << PDM_CFG0_CLK_DIV_Pos);
574                 sinc_cfg |= (25 << PDM_SINC_CFG_SINC_RATE_Pos);
575                 sinc_cfg |= PDM_SINC_CFG_SINC_ORDER_SEL;
576                 //cfg_fifo |= (0x4 << PDM_FIFO_CFG_PDM_SHIFT_Pos);  //Align to 24bit
577             }
578             else if (hpdm->Init.clkSrc == 3072000)
579             {
580                 cfg0_value |= PDM_CFG0_CLK_SEL; //3.072MHz source
581                 cfg0_value &= ~PDM_CFG0_CLK_DIV;
582                 cfg0_value |= (1 << PDM_CFG0_CLK_DIV_Pos);
583                 sinc_cfg |= (32 << PDM_SINC_CFG_SINC_RATE_Pos);
584             }
585             break;
586         case PDM_SAMPLE_96KHZ:
587         {
588             /* Only support audpll */
589             /* pcm_clk:3.072M SINCRATE:8 LPF:4 SINC ORDER:4 */
590             cfg0_value |= PDM_CFG0_CLK_SEL; //3.072MHz source
591             cfg0_value &= ~PDM_CFG0_CLK_DIV;
592             cfg0_value |= (1 << PDM_CFG0_CLK_DIV_Pos);
593             sinc_cfg |= (8 << PDM_SINC_CFG_SINC_RATE_Pos);
594             sinc_cfg |= PDM_SINC_CFG_SINC_ORDER_SEL;
595             lpf_cfg |= PDM_LPF_CFG6_LPF_DS;
596             /* reg_pga_gain = 0x72,  pdm_shift = 0 */
597             // cfg_fifo |= (0x8 << PDM_FIFO_CFG_PDM_SHIFT_Pos);
598             hpdm->Instance->PGA_CFG &= ~PDM_PGA_CFG_PGA_GAIN_L;
599             hpdm->Instance->PGA_CFG |= (0x72 << PDM_PGA_CFG_PGA_GAIN_L_Pos);
600             hpdm->Instance->PGA_CFG &= ~PDM_PGA_CFG_PGA_GAIN_R;
601             hpdm->Instance->PGA_CFG |= (0x72 << PDM_PGA_CFG_PGA_GAIN_R_Pos);
602         }
603         break;
604         default:
605             HAL_ASSERT(0);
606             return HAL_ERROR;
607             break;
608         }
609         hpdm->Instance->SINC_CFG = sinc_cfg;
610         hpdm->Instance->LPF_CFG6 = lpf_cfg;
611     }
612 
613     if (type & PDM_CFG_DEPTH)
614     {
615         /*Channel depth*/
616 #ifndef SF32LB55X
617         cfg_fifo &= ~PDM_FIFO_CFG_BYTE_TRUNC;
618         switch (hpdm->Init.ChannelDepth)
619         {
620         case PDM_CHANNEL_DEPTH_8BIT:
621             cfg_fifo |= (2 << PDM_FIFO_CFG_BYTE_TRUNC_Pos);
622             break;
623         case PDM_CHANNEL_DEPTH_16BIT:
624             cfg_fifo |= (1 << PDM_FIFO_CFG_BYTE_TRUNC_Pos);
625             break;
626         case PDM_CHANNEL_DEPTH_24BIT:
627             cfg_fifo |= (0 << PDM_FIFO_CFG_BYTE_TRUNC_Pos);
628             break;
629         case PDM_CHANNEL_DEPTH_32BIT:
630             cfg_fifo |= (3 << PDM_FIFO_CFG_BYTE_TRUNC_Pos);
631             break;
632         default:
633             HAL_ASSERT(0);
634             return HAL_ERROR;
635             break;
636         }
637 #else
638         if (PDM_CHANNEL_DEPTH_16BIT != hpdm->Init.ChannelDepth)
639         {
640             cfg_fifo &= ~PDM_FIFO_CFG_BYTE_TRUNC;
641         }
642         else
643         {
644             cfg_fifo |= PDM_FIFO_CFG_BYTE_TRUNC;
645         }
646 #endif
647     }
648     hpdm->Instance->CFG0 = cfg0_value;
649     hpdm->Instance->FIFO_CFG = cfg_fifo;
650 
651     return HAL_OK;
652 }
653 
654 
PDM_ConfigDMA(PDM_HandleTypeDef * hpdm)655 static HAL_StatusTypeDef PDM_ConfigDMA(PDM_HandleTypeDef *hpdm)
656 {
657     /*Init DMA*/
658     if (hpdm->hdmarx != NULL)
659     {
660         hpdm->hdmarx->Init.Direction           = DMA_PERIPH_TO_MEMORY;
661         hpdm->hdmarx->Init.PeriphInc           = DMA_PINC_DISABLE;
662         hpdm->hdmarx->Init.MemInc              = DMA_MINC_ENABLE;
663 #ifdef  SF32LB55X
664         if (PDM_CHANNEL_DEPTH_8BIT == hpdm->Init.ChannelDepth)
665         {
666             hpdm->hdmarx->Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
667             hpdm->hdmarx->Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
668         }
669         else
670 #endif
671         {
672             hpdm->hdmarx->Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
673             hpdm->hdmarx->Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
674         }
675         hpdm->hdmarx->Init.Mode                = (PDM_MODE_LOOP == hpdm->Init.Mode) ? DMA_CIRCULAR : DMA_NORMAL;
676         hpdm->hdmarx->Init.Priority            = DMA_PRIORITY_LOW;
677         hpdm->hdmarx->Parent = (void *)hpdm;
678 
679         HAL_DMA_Init(hpdm->hdmarx);
680     }
681     if (hpdm->hdmarx_r != NULL)
682     {
683         hpdm->hdmarx_r->Init.Direction           = DMA_PERIPH_TO_MEMORY;
684         hpdm->hdmarx_r->Init.PeriphInc           = DMA_PINC_DISABLE;
685         hpdm->hdmarx_r->Init.MemInc              = DMA_MINC_ENABLE;
686 #ifdef  SF32LB55X
687         if (PDM_CHANNEL_DEPTH_8BIT == hpdm->Init.ChannelDepth)
688         {
689             hpdm->hdmarx_r->Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
690             hpdm->hdmarx_r->Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
691         }
692         else
693 #endif
694         {
695             hpdm->hdmarx_r->Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
696             hpdm->hdmarx_r->Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
697         }
698         hpdm->hdmarx_r->Init.Mode                = (PDM_MODE_LOOP == hpdm->Init.Mode) ? DMA_CIRCULAR : DMA_NORMAL;
699         hpdm->hdmarx_r->Init.Priority            = DMA_PRIORITY_LOW;
700         hpdm->hdmarx_r->Parent = (void *)hpdm;
701 
702         HAL_DMA_Init(hpdm->hdmarx_r);
703     }
704 
705     return HAL_OK;
706 }
707 
708 #endif /* HAL_PDM_MODULE_ENABLED */