241 lines
8.6 KiB
C
241 lines
8.6 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
|
|
|
|
static 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, ®_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;
|
|
}
|
|
|
|
// static 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);
|
|
|
|
// 设置左DAC音量
|
|
bsp_aic3204_write_reg(hi2c, 0x41, (uint8_t)-64);
|
|
// 设置右DAC音量
|
|
bsp_aic3204_write_reg(hi2c, 0x42, (uint8_t)-64);
|
|
|
|
// 选择寄存器页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);
|
|
|
|
// 左声道DAC输出到LOL
|
|
bsp_aic3204_write_reg(hi2c, 0x0E, 0x08);
|
|
// 右声道DAC输出到LOR
|
|
bsp_aic3204_write_reg(hi2c, 0x0F, 0x08);
|
|
// 左声道DAC输出到LOL 增益-6dB
|
|
bsp_aic3204_write_reg(hi2c, 0x12, 0x00);
|
|
// 右声道DAC输出到LOR 增益-6dB
|
|
bsp_aic3204_write_reg(hi2c, 0x13, 0x00);
|
|
|
|
// 启动HPL HPR LOL LOR驱动器
|
|
bsp_aic3204_write_reg(hi2c, 0x09, 0x3C);
|
|
// 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);
|
|
|
|
elog_info(TAG, "bsp_aic3204_init: codec initialized");
|
|
return HAL_OK;
|
|
}
|