stm32h743_player/User/bsp/bsp_aic3204.c

225 lines
8.0 KiB
C

#include "bsp_aic3204.h"
#include "FreeRTOS.h"
#include "task.h"
#include "elog.h"
static const char *TAG = "bsp_aic3204";
#define BSP_AIC3204_I2C_ADDR 0x30
HAL_StatusTypeDef bsp_aic3204_write_reg(I2C_HandleTypeDef *hi2c, uint8_t reg_addr, uint8_t reg_value)
{
HAL_StatusTypeDef status = HAL_I2C_Mem_Write(hi2c, BSP_AIC3204_I2C_ADDR, reg_addr, 1, &reg_value, 1, 100);
if (status == HAL_OK) {
elog_debug(TAG, "write register 0x%02X@0x%02X success", reg_value, reg_addr);
} else {
elog_error(TAG, "write register 0x%02X@0x%02X failed", reg_value, reg_addr);
}
return status;
}
HAL_StatusTypeDef bsp_aic3204_read_reg(I2C_HandleTypeDef *hi2c, uint8_t reg_addr, uint8_t *reg_value_out)
{
HAL_StatusTypeDef status = HAL_I2C_Mem_Read(hi2c, BSP_AIC3204_I2C_ADDR, reg_addr, 1, reg_value_out, 1, 10);
if (status == HAL_OK) {
elog_debug(TAG, "read register 0x%02X@0x%02X success", *reg_value_out, reg_addr);
} else {
elog_error(TAG, "read register @0x%02X failed", reg_addr);
}
return status;
}
HAL_StatusTypeDef bsp_aic3204_set_fs(I2C_HandleTypeDef *hi2c, uint32_t fs_hz)
{
uint16_t n_dac;
uint16_t pll_j, pll_d;
uint16_t prb_no;
switch (fs_hz) {
case 11025:
case 22050:
case 44100:
case 88200:
case 176400:
pll_j = 7;
pll_d = 3500; //PLL输出的时钟频率CODEC_CLKIN=11.2896MHz*8
n_dac = (8 * 4) / (fs_hz / 11025);
break;
case 12000:
case 24000:
case 48000:
case 96000:
case 192000:
pll_j = 8;
pll_d = 0; //PLL输出的时钟频率CODEC_CLKIN=12.288MHz*8
n_dac = (8 * 4) / (fs_hz / 12000);
break;
case 8000:
case 16000:
case 32000:
pll_j = 8;
pll_d = 0; //PLL输出的时钟频率CODEC_CLKIN=12.288MHz*8
/* PLL输出的时钟频率CODEC_CLKIN=11.2896MHz*8 */
n_dac = (8 * 6) / (fs_hz / 8000);
break;
default:
elog_error(TAG, "bsp_aic3204_set_fs: unsupported sample rate: %dHz", fs_hz);
return HAL_ERROR;
}
if (fs_hz <= 48000) {
prb_no = 1;
} else if (fs_hz <= 96000) {
prb_no = 9;
} else {
prb_no = 19;
}
// 设置PLL_J
bsp_aic3204_write_reg(hi2c, 0x06, pll_j);
// 设置PLL_D
bsp_aic3204_write_reg(hi2c, 0x07, pll_d >> 8);
bsp_aic3204_write_reg(hi2c, 0x08, pll_d & 0xFF);
// 启动NDAC分频器并设置分频值
bsp_aic3204_write_reg(hi2c, 0x0b, 0x80 | n_dac);
// 设置DAC信号处理块(PRB)
bsp_aic3204_write_reg(hi2c, 0x3C, prb_no);
elog_info(TAG, "bsp_aic3204_set_fs: sample rate: %dHz, NDAC=%d, PLL J.D=%d.%d", fs_hz, n_dac, pll_j, pll_d);
return HAL_OK;
}
HAL_StatusTypeDef bsp_aic3204_init(I2C_HandleTypeDef *hi2c)
{
// 选择寄存器页0
// bsp_aic3204_write_reg(hi2c, 0x00, 0x00);
// 软件复位芯片
// bsp_aic3204_write_reg(hi2c, 0x01, 0x01);
// 硬件复位芯片
HAL_GPIO_WritePin(CODEC_RST_GPIO_Port, CODEC_RST_Pin, GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(10));
HAL_GPIO_WritePin(CODEC_RST_GPIO_Port, CODEC_RST_Pin, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(10));
/*
* 时钟结构
* PLL_CLKIN PLL_CLK /NDAC /MDAC /DOSR
* MFP5 -----------> PLL ---------> CODEC_CLKIN -------> DAC_CLK -------> DAC_MOD_CLK -------> DAC_FS
* |
* -------------> BCLK -----------------------> WCLK
* /BDIV_CLKIN /SAMPLE_BITS/CHANNELS
*
* 举例如下
* /1 /2 /128
* MFP5 ----> CODEC_CLKIN ----> DAC_CLK ----> DAC_MOD_CLK ------> DAC_FS
* 12.288MHz 12.288MHz 6.144MHz 48kHz
* |
* ----> BCLK -------> WCLK
* /8 1.536MHz /16/2 48kHz
*
* BDIV_CLKIN = MDAC * DOSR / SAMPLE_BITS / CHANNELS
*/
/*
uint16_t n_dac = 1;
uint16_t m_dac = 2;
uint16_t dac_osr = 128;
uint16_t bdiv_clkin = m_dac * dac_osr / 16 / 2;
// 选择寄存器页0
bsp_aic3204_write_reg(hi2c, 0x00, 0x00);
// MFP5用于时钟输入
bsp_aic3204_write_reg(hi2c, 0x34, 0x04);
// 选择GPIO输入为Codec主时钟源
bsp_aic3204_write_reg(hi2c, 0x04, 0x02);
// 启动NDAC分频器并设置分频值为1
bsp_aic3204_write_reg(hi2c, 0x0b, 0x80 | n_dac);
// 启动MDAC分频器并设置分频值为2
bsp_aic3204_write_reg(hi2c, 0x0c, 0x80 | m_dac);
// 设置DAC的超采样率(OSR)为128
bsp_aic3204_write_reg(hi2c, 0x0d, (dac_osr >> 8) & 0x03);
bsp_aic3204_write_reg(hi2c, 0x0e, dac_osr & 0xFF);
// 总线类型I2S 数据长度16位 BCLK方向为输出 WCLK方向为输出
bsp_aic3204_write_reg(hi2c, 0x1b, 0x0D);
// 设置DAC信号处理块(PRB)为PRB_1
bsp_aic3204_write_reg(hi2c, 0x3c, 0x01);
// 选择DAC_CLK做为BDIV_CLKIN
bsp_aic3204_write_reg(hi2c, 0x1D, 0x00);
// 启用对外WCLK与BCLK时钟输出 CODEC_CLKIN与BCLK的商为每个采样的大小 即声道数与DAC位数的乘积
bsp_aic3204_write_reg(hi2c, 0x1E, 0x80 | bdiv_clkin);
*/
// 选择寄存器页0
bsp_aic3204_write_reg(hi2c, 0x00, 0x00);
// MFP5用于时钟输入
bsp_aic3204_write_reg(hi2c, 0x34, 0x04);
// 选择GPIO输入为PLL时钟源 选择PLL输出为Codec主时钟源
bsp_aic3204_write_reg(hi2c, 0x04, 0x02 << 2 | 0x03 << 0);
// 启动PLL并设置PLL_P=1 PLL_R=1
bsp_aic3204_write_reg(hi2c, 0x05, 0x80 | 1 << 4 | 1 << 0);
// 设置PLL_J=7
bsp_aic3204_write_reg(hi2c, 0x06, 0x07);
// 设置PLL_D=3500
bsp_aic3204_write_reg(hi2c, 0x07, 3500 >> 8);
bsp_aic3204_write_reg(hi2c, 0x08, 3500 & 0xFF);
// 启动NDAC分频器并设置分频值为8
bsp_aic3204_write_reg(hi2c, 0x0B, 0x80 | 8);
// 启动MDAC分频器并设置分频值为2
bsp_aic3204_write_reg(hi2c, 0x0C, 0x80 | 2);
// 设置DAC的超采样率(OSR)为128
bsp_aic3204_write_reg(hi2c, 0x0D, 128 >> 8);
bsp_aic3204_write_reg(hi2c, 0x0E, 128 & 0xFF);
// 总线类型I2S 数据长度16位 BCLK方向为输出 WCLK方向为输出
bsp_aic3204_write_reg(hi2c, 0x1B, 0x0D);
// 选择DAC_CLK做为BDIV_CLKIN
bsp_aic3204_write_reg(hi2c, 0x1D, 0x00);
// 启用对外WCLK与BCLK时钟输出 CODEC_CLKIN与BCLK的商为每个采样的大小 即声道数与DAC位数的乘积
bsp_aic3204_write_reg(hi2c, 0x1E, 0x80 | 8);
// 设置DAC信号处理块(PRB)为PRB_1
bsp_aic3204_write_reg(hi2c, 0x3C, 1);
// 选择寄存器页1
bsp_aic3204_write_reg(hi2c, 0x00, 0x01);
// 关闭内部AVDD微供电
bsp_aic3204_write_reg(hi2c, 0x01, 0x08);
// 内部LDO上电 DVDD=1.72V AVDD=1.72V
bsp_aic3204_write_reg(hi2c, 0x02, 0x01);
// Set the REF charging time to 40ms
bsp_aic3204_write_reg(hi2c, 0x7b, 0x01);
// HP soft stepping settings for optimal pop performance at power up
// Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor.
// Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound.
bsp_aic3204_write_reg(hi2c, 0x14, 0x25);
// Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to Input Common Mode
bsp_aic3204_write_reg(hi2c, 0x0A, 0x00);
// Route Left DAC to HPL
bsp_aic3204_write_reg(hi2c, 0x0c, 0x08);
// Route Right DAC to HPR
bsp_aic3204_write_reg(hi2c, 0x0d, 0x08);
// Set the DAC PTM mode to PTM_P3/4
bsp_aic3204_write_reg(hi2c, 0x03, 0x00);
bsp_aic3204_write_reg(hi2c, 0x04, 0x00);
// Set the HPL gain to 0dB
bsp_aic3204_write_reg(hi2c, 0x10, 0x00);
// Set the HPR gain to 0dB
bsp_aic3204_write_reg(hi2c, 0x11, 0x00);
// Power up HPL and HPR drivers
bsp_aic3204_write_reg(hi2c, 0x09, 0x30);
// Wait for 2.5 sec for soft stepping to take effect
vTaskDelay(pdMS_TO_TICKS(1000));
// 选择寄存器页0
bsp_aic3204_write_reg(hi2c, 0x00, 0x00);
// Power up the Left and Right DAC Channels with route the Left Audio digital data to Left Channel DAC and Right Audio digital data to Right Channel DAC
bsp_aic3204_write_reg(hi2c, 0x3f, 0xd6);
// Unmute the DAC digital volume control
bsp_aic3204_write_reg(hi2c, 0x40, 0x00);
return HAL_OK;
}