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 */