177 lines
4.6 KiB
C
177 lines
4.6 KiB
C
|
/*
|
||
|
******************************************************************************
|
||
|
* @file driver_pdm.c
|
||
|
* @author FreqChip Firmware Team
|
||
|
* @version V1.0.0
|
||
|
* @date 2023
|
||
|
* @brief pdm module driver.
|
||
|
* This file provides firmware functions to manage the
|
||
|
* pulse-duration modulation (PDM) peripheral
|
||
|
******************************************************************************
|
||
|
* @attention
|
||
|
*
|
||
|
* Copyright (c) 2023 FreqChip.
|
||
|
* All rights reserved.
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
#include "fr30xx.h"
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_IRQHandler
|
||
|
*
|
||
|
* @brief Handle PDM interrupt request.
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
*/
|
||
|
__WEAK void pdm_IRQHandler(PDM_HandleTypeDef *hpdm)
|
||
|
{
|
||
|
if (__PDM_IS_FIFO_ALMOST_FULL(hpdm->PDMx))
|
||
|
{
|
||
|
if (hpdm->p_RxData) {
|
||
|
pdm_read_data(hpdm, hpdm->p_RxData);
|
||
|
}
|
||
|
|
||
|
if (hpdm->RxCallback) {
|
||
|
hpdm->RxCallback(hpdm);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_init
|
||
|
*
|
||
|
* @brief Initialize the PDM according to the specified parameters in the struct_PDMInit_t
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
*/
|
||
|
void pdm_init(PDM_HandleTypeDef *hpdm)
|
||
|
{
|
||
|
/* Clock default use 24M */
|
||
|
hpdm->PDMx->Config.USB_MODE = 1;
|
||
|
/* Sample Rate */
|
||
|
hpdm->PDMx->Config.SAMPLE_RATE = hpdm->Init.SampleRate;
|
||
|
/* Over Samplek Mode */
|
||
|
hpdm->PDMx->Config.OSR_MODE = hpdm->Init.OverSampleMode;
|
||
|
/* channel config */
|
||
|
if (hpdm->Init.ChannelMode == PDM_STEREO) {
|
||
|
hpdm->PDMx->Config.MONO = 0;
|
||
|
hpdm->PDMx->Config.CH_SEL = 0;
|
||
|
}
|
||
|
else{
|
||
|
hpdm->PDMx->Config.MONO = 1;
|
||
|
hpdm->PDMx->Config.CH_SEL = hpdm->Init.ChannelMode;
|
||
|
}
|
||
|
|
||
|
/* fifo almost Full Threshold */
|
||
|
hpdm->PDMx->FF_AFLL_LVL = hpdm->Init.FIFO_FullThreshold;
|
||
|
|
||
|
pdm_vol_set(hpdm, hpdm->Init.Volume);
|
||
|
|
||
|
hpdm->PDMx->Config.RST = 1;
|
||
|
hpdm->PDMx->Config.RST = 0;
|
||
|
hpdm->PDMx->FF_RST.rst = 0x07;
|
||
|
hpdm->PDMx->FF_RST.rst = 0x00;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_start_IT
|
||
|
*
|
||
|
* @brief PDM read start in interrupt mode.
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
* @param fp_Data: buffer used to store received data, If fp_Data is NULL, application layer
|
||
|
* should take charge of reading data from fifo.
|
||
|
*/
|
||
|
void pdm_start_IT(PDM_HandleTypeDef *hpdm, void *fp_Data)
|
||
|
{
|
||
|
if (hpdm->b_RxBusy)
|
||
|
return;
|
||
|
|
||
|
__PDM_CLK_ENABLE(hpdm->PDMx);
|
||
|
__PDM_ENABLE(hpdm->PDMx);
|
||
|
|
||
|
__PDM_FIFO_ALMOST_FULL_INT_ENABLE(hpdm->PDMx);
|
||
|
|
||
|
hpdm->b_RxBusy = true;
|
||
|
hpdm->p_RxData = fp_Data;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_init
|
||
|
*
|
||
|
* @brief Initialize the PDM according to the specified parameters in the struct_PDMInit_t
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
* @param vol: target volume, unit is dB
|
||
|
*/
|
||
|
void pdm_vol_set(PDM_HandleTypeDef *hpdm, int8_t vol)
|
||
|
{
|
||
|
uint32_t vol_cfg;
|
||
|
|
||
|
if(vol <= 18) {
|
||
|
vol_cfg = PDM_VOL_dB(vol);
|
||
|
hpdm->Init.Volume = vol;
|
||
|
}
|
||
|
else {
|
||
|
return;
|
||
|
}
|
||
|
hpdm->PDMx->VOL_L = vol_cfg;
|
||
|
hpdm->PDMx->VOL_R = vol_cfg;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_read_data
|
||
|
*
|
||
|
* @brief read data from PDM fifo, read size is FIFO_FullThreshold
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
* @param pcm: buffer used to store received data.
|
||
|
*/
|
||
|
void pdm_read_data(PDM_HandleTypeDef *hpdm, void *fp_Data)
|
||
|
{
|
||
|
uint8_t thd = hpdm->Init.FIFO_FullThreshold;
|
||
|
|
||
|
if (hpdm->Init.ChannelMode == PDM_STEREO)
|
||
|
{
|
||
|
uint32_t *p_u32 = (void *)fp_Data;
|
||
|
while (thd--) {
|
||
|
*p_u32++ = hpdm->PDMx->DATA;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uint16_t *p_u16 = (void *)fp_Data;
|
||
|
while (thd--) {
|
||
|
*p_u16++ = hpdm->PDMx->DATA;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_start
|
||
|
*
|
||
|
* @brief PDM sampling start.
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
*/
|
||
|
void pdm_start(PDM_HandleTypeDef *hpdm)
|
||
|
{
|
||
|
__PDM_CLK_ENABLE(hpdm->PDMx);
|
||
|
__PDM_ENABLE(hpdm->PDMx);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn pdm_stop
|
||
|
*
|
||
|
* @brief PDM sampling stop.
|
||
|
*
|
||
|
* @param hpdm: PDM handle.
|
||
|
*/
|
||
|
void pdm_stop(PDM_HandleTypeDef *hpdm)
|
||
|
{
|
||
|
__PDM_DISABLE(hpdm->PDMx);
|
||
|
__PDM_CLK_DISABLE(hpdm->PDMx);
|
||
|
|
||
|
hpdm->b_RxBusy = false;
|
||
|
}
|