#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, ®_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); // 设置左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); return HAL_OK; }