Files
banban/ql-application/threadx/interface/custom_app/audio.c
T

554 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdio.h>
#include "ql_rtos.h"
#include "ql_application.h"
#include "ql_audio.h"
#include "ql_iic.h"
#include "ql_gpio.h"
#include "app_inc.h"
#include "ql_fs.h"
#define DEFAULT_VOLUME 6
//#define TEST_MIC
u8 g_cur_volume = 0;
u8 g_pre_volume = 0;
extern const char *mp3_file[];
extern int g_file_valid;
// 关键寄存器定义
#define ES8311_REG_SYSTEM 0x01
#define ES8311_REG_CLK_CTL 0x00
#define ES8311_REG_PDN_CTL 0x0D
#define ES8311_REG_STATUS 0x00
#define ES8311_REG_CHIPID 0xFD
#if 0
static uint16 es8311_init_reg[] = {
0x0045,//45 is the addr, 0x00 is the value
0x3001,
0x1002,
0x0002,
0x1003,
0x2416,
0x2004,
0x0005,
0x2006,
0x0007,
0xff08,
0x0f09,
0x0f0a,
0x000b,
0x000c,
0x1310,
0x7f11,
0x3f01,
0x8000,
0x010d,
0x1014,
0x2812,
0x1013,
0x020e,
0x440f,
0x0015,
0x0a1b,
0x6a1c,
0x0837,
0x0044,
0xbf17,
0xbf32,
};
#endif
#if 1
static uint16 es8311_init_reg[] = {
0x0045,
0x3001,
0x1002,
0x0002,
0x1003,
0x2416,
0x2004,
0x0005,
0x2006,
0x0007,
0xff08,
0x0f09,
0x0f0a,
0x000b,
0x000c,
0x1310, // 0x10 保持不变
0x7f11, // 0x11 保持不变
0x3f01,
0x8000,
0x010d,
0x1014, // ← 修改:LINSEL=1, PGAGAIN=0(+0dB) 或 0x0214(+6dB)
0x2812,
0x1013,
0x020e,
0x440f,
0x0015,
0x0a1b,
0x6a1c,
0x0837,
0x0044,
0xa717, // ← 修改:ADC_VOLUME=0x9F (-32dB),缩短拾音距离
0xbf32, // DAC音量保持不变
0x0018, // ← 新增:关闭ALC (如果之前没配的话)
// 0x0016, // ← 新增/修改:ADC_SCALE=0 (0dB)
};
#endif
static uint16 es8311_sleep_reg[] = {
0x0032,//32 is the addr, 0x00 is the value 音量控制
0x0017,//MIC采样功率
0xFF0E,//设置外设低功耗
0x0212,//powerdown dac
0x0014,
0xF90D,//FA0D
0x0015,
0x0837,
0x1002,
0x0000,
0x1F00,
0x3001,
0x0001,
0x0045,
};
#if 0
static uint16 es8311_resume_reg[] = {
0x010D,//45 is the addr, 0x00 is the value
0x0045,
0x3F01,
0x8000,
0x0002,
0x0837,
0x4015,
0x1014,
0x0012,
0x000E,
0xBF32,
0xBF17,
};
#endif
#if 1
static uint16 es8311_resume_reg[] = {
0x010D,
0x0045,
0x3F01,
0x8000,
0x0002,
0x0837,
0x4015,
0x1014,
0x0012,
0x000E,
0xBF32,
0xa717, // ← 同步修改:ADC_VOLUME=-32dB
};
#endif
#define ES8311_INIT_REG_LEN sizeof(es8311_init_reg)/sizeof(es8311_init_reg[0])
#define ES8311_SLEEP_REG_LEN sizeof(es8311_sleep_reg)/sizeof(es8311_sleep_reg[0])
#define ES8311_RESUME_REG_LEN sizeof(es8311_resume_reg)/sizeof(es8311_resume_reg[0])
#define ES8311_REG_I2C_DEVICEID 0xFD
#define ES8311_I2C_SLAVE_ADDR 0x18
unsigned char ql_es8311_write_reg(unsigned char reg, unsigned char data)
{
sw_i2c_start();
sw_i2c_write_byte(ES8311_I2C_SLAVE_ADDR << 1);
sw_i2c_write_byte(reg);
sw_i2c_write_byte(data);
sw_i2c_stop();
return 0;
}
/*************************************************************
* I2C1_read_eeprom
* Description: I2C1 read FT24C02 eeprom
* Parameters: op_addr: operate address
* pData: data point
* len: data len
* return: unsigned long
* error: none
*/
unsigned char ql_es8311_read_reg(unsigned char reg, unsigned char *pData)
{
sw_i2c_start();
sw_i2c_write_byte(ES8311_I2C_SLAVE_ADDR << 1);
sw_i2c_write_byte(reg);
sw_i2c_start();
sw_i2c_write_byte((ES8311_I2C_SLAVE_ADDR << 1)+1);
*pData=sw_i2c_read_byte(0);
sw_i2c_stop();
return 0;
}
void ql_es8311_init(void)
{
char i = 0;
for (i = 0; i < ES8311_INIT_REG_LEN; i++)
{
ql_es8311_write_reg(es8311_init_reg[i]&0xFF, es8311_init_reg[i]>>8);
}
}
void ql_es8311_open(void) //��ʼ��es8311�ͺ�codec
{
unsigned short status = 0;
unsigned char val = 0;
status = ql_es8311_read_reg(ES8311_REG_I2C_DEVICEID, &val);
if ((status == 0) && (0x83 == val))
{
ql_es8311_init();
printf("quec_es8311_init!!!\n");
}
app_set_default_volume();
}
void ql_es8311_sleep(void)
{
#if 1
char i = 0;
for (i = 0; i < ES8311_SLEEP_REG_LEN; i++)
{
ql_es8311_write_reg(es8311_sleep_reg[i]&0xFF, es8311_sleep_reg[i]>>8);
}
#endif
}
void ql_es8311_wake(void)
{
#if 1
char i = 0;
for (i = 0; i < ES8311_RESUME_REG_LEN; i++)
{
ql_es8311_write_reg(es8311_resume_reg[i]&0xFF, es8311_resume_reg[i]>>8);
ql_rtos_task_sleep_ms(5);
}
app_set_default_volume();
#endif
}
void ql_es8311_vocie_set(u8 value)
{
ql_es8311_write_reg(0x32, value);
}
u8 ql_es8311_vocie_get(void)
{
u8 value = 0;
//ql_es8311_write_reg(0x32, value);
ql_es8311_read_reg(0x32, &value);
}
static ql_cb_on_speakerpa play_audio_pa_cb(unsigned int on){
if(on){
// printf("PA on\r\n");
}else{
//printf("PA off\r\n");
app_codec_pa_close();
}
}
signed short DSP_codec_gain[12]={-36,-31,-27,-24,-21,-18,-15,-12,-9,-6,-3,0};
static void ql_audio_record_callback(acm_audio_track_handle handle, acm_audio_record_event_t event)
{
printf("audio_record_callback event:%d\r\n", event);
}
void app_codec_pa_close(void)
{
ql_gpio_init(GPIO_PIN_NO_68, PIN_DIRECTION_OUT, PIN_PULL_PU, PIN_LEVEL_LOW); //for new board
//ql_gpio_init(GPIO_PIN_NO_57, PIN_DIRECTION_OUT, PIN_PULL_PU, PIN_LEVEL_LOW); //for old board
}
void app_codec_pa_open(void)
{
ql_gpio_init(GPIO_PIN_NO_68, PIN_DIRECTION_OUT, PIN_PULL_PU, PIN_LEVEL_HIGH); //for new board
//ql_gpio_init(GPIO_PIN_NO_57, PIN_DIRECTION_OUT, PIN_PULL_PU, PIN_LEVEL_HIGH); //for old board
}
#if 0
#define VOLUME_FILE "U:/volume_file.txt"
int read_volume_file(uint8_t *buff, int len)
{
QFILE * fp = NULL;
int ret = -1;
// 安全修复:检查参数
if(buff == NULL || len <= 0){
printf("[FS]ERROR!!! *** invalid parameters\r\n");
return -1;
}
if(ql_access(VOLUME_FILE, 0)!=0){
printf("read %s not is exist\n", VOLUME_FILE);
return -1;
}
fp = ql_fopen(VOLUME_FILE, "r");
if(NULL == fp)
{
printf("[FS]ERROR!!! *** file open fail: %s \r\n", VOLUME_FILE);
return -1;
}
ret = ql_fread(buff, len, 1, fp);
if(ret < 0)
{
printf("[FS]ERROR!!! *** file read fail: %s \r\n", VOLUME_FILE);
}
ql_fclose(fp);
// 安全修复:fp已关闭,无需设为NULL
return ret;
}
int save_volume_file(uint8_t *buff, int len)
{
QFILE * fp = NULL;
int ret = -1;
// 安全修复:检查参数
if(buff == NULL || len <= 0){
printf("[FS]ERROR!!! *** invalid parameters\r\n");
return -1;
}
fp = ql_fopen(VOLUME_FILE, "w+");
if(NULL == fp)
{
printf("[FS]ERROR!!! *** file open fail: %s \r\n", VOLUME_FILE);
return -1;
}
ret = ql_fwrite(buff, len, 1, fp);
if(ret < 0)
{
printf("[FS]ERROR!!! *** file write fail: %s \r\n", VOLUME_FILE);
}
ql_fclose(fp);
// 安全修复:fp已关闭,无需设为NULL
return ret;
}
#endif
void app_set_volume(uint8_t value)
{
//save_volume_file(&value, 1);
if(g_cur_volume==0){
hal_kv_set("volume", &value, 1);
}
printf("set volume:%d\r\n", value);
ql_es8311_vocie_set(value);
if(value==VOLUME_80){
g_cur_volume = 80;
}else if(value==VOLUME_60){
g_cur_volume = 60;
}else if(value==VOLUME_40){
g_cur_volume = 40;
}else if(value==VOLUME_100){
g_cur_volume = 100;
}else if(value==VOLUME_10){
g_cur_volume = 10;
}else if(value==VOLUME_20){
g_cur_volume = 20;
}else if(value==VOLUME_30){
g_cur_volume = 30;
}else if(value==VOLUME_70){
g_cur_volume = 70;
}else if(value==VOLUME_50){
g_cur_volume = 50;
}else if(value==VOLUME_90){
g_cur_volume = 90;
}else{
g_cur_volume = 70;
}
}
uint8_t app_get_volume(void)
{
uint8_t value = 0;
int ret = 0;
ret = hal_kv_get("volume", &value, 1);
printf("get volume:%d, ret:%d\r\n", value, ret);
//ret = read_volume_file(&value, 1);
if(ret<0){
g_cur_volume = 70;
hal_kv_set("volume", &g_cur_volume, 1);
return VOLUME_70;
}
g_cur_volume = value;
if(value==10){
ret = VOLUME_10;
}else if(value==20){
ret = VOLUME_20;
}else if(value==30){
ret = VOLUME_30;
}else if(value==40){
ret = VOLUME_40;
}else if(value==50){
ret = VOLUME_50;
}else if(value==60){
ret = VOLUME_60;
}else if(value==70){
ret = VOLUME_70;
}else if(value==80){
ret = VOLUME_80;
}else if(value==90){
ret = VOLUME_90;
}else if(value==100){
ret = VOLUME_100;
}
return ret;
}
int app_set_default_volume(void)
{
int volume = app_get_volume();
//g_pre_volume = volume;
printf("volume:%d\r\n", volume);
ql_es8311_vocie_set(volume);
return volume;
}
#ifdef TEST_MIC
static void ql_audio_track_callback(acm_audio_track_handle handle, acm_audio_track_event_t event)
{
printf("audio_track_callback event:%d\r\n", event);
}
#endif
void play_start_mp3_file(void)
{
char *filename_buff[64]={0x00};
sprintf(filename_buff, "U:/%s", mp3_file[1]);
if(ql_access(filename_buff, 0)==0){
g_file_valid = 1;
aofei_mp3_player(filename_buff);
}
}
void app_audio_init(void)
{
// static audio_record_handle record_hd;
while(!ql_get_audio_state()){
ql_rtos_task_sleep_ms(50);
}
printf("ql_audio_init ...\r\n");
unsigned int rate = 16000;
ql_codecpcm_config pcm_config[] = {PCM_FS_256,PCM_CODEC_SAMPLE_16000,0};
app_codec_pa_close();
ql_codec_choose(AUD_EXTERNAL_CODEC, &pcm_config); //ģ���ڲ����ú�������codec���pcm����
ql_es8311_open();
ql_set_audio_path_receiver();
ql_set_rxcodec_gain_table(1, 0, 36, 1, 1,0, 2);
ql_set_rxcodec_gain_table(1, 1, 36, 1, 1,0, 2);
ql_set_rxcodec_gain_table(1, 2, 36, 1, 2,0, 2);
ql_set_rxcodec_gain_table(1, 3, 36, 1, 2,0, 2);
ql_set_rxcodec_gain_table(1, 4, 36, 1, 3,0, 2);
ql_set_rxcodec_gain_table(1, 5, 36, 1, 3,1, 2);
ql_set_rxcodec_gain_table(1, 6, 36, 1, 4,1, 2);
ql_set_rxcodec_gain_table(1, 7, 36, 1, 4,1, 2);
ql_set_rxcodec_gain_table(1, 8, 36, 1, 4,1, 2);
ql_set_rxcodec_gain_table(1, 9, 36, 1, 4,1, 2);
ql_set_rxcodec_gain_table(1, 10, 36, 1, 4,1, 2);
ql_set_rxcodec_gain_table(1, 11, 36, 1, 4,1, 2);
ql_set_dsp_gain_table(1, DSP_codec_gain);
ql_bind_speakerpa_cb(play_audio_pa_cb);
//ql_set_volume(DEFAULT_VOLUME);
g_pre_volume = app_set_default_volume();
play_start_mp3_file();
#ifdef TEST_MIC
unsigned int channels = 1;
unsigned int record_len;
int read_ret = -1, write_ret = -1;
char *tmp_buf = NULL;
audio_track_handle track_hd;
audio_record_handle record_hd;
record_len = (channels*rate*2*20)/1000;
tmp_buf = malloc(record_len);
track_hd = ql_audio_track_open(rate, channels, 0x100, ql_audio_track_callback);
record_hd = ql_audio_record_open(rate, channels, 0, ql_audio_record_callback);
app_codec_pa_open();
while (1)
{
read_ret = ql_audio_record_read(record_hd, tmp_buf, &record_len);
printf("ql_pcm_read, pcm read:%d %d\n", read_ret,record_len);
if ((read_ret == 0) && record_len > 0) {
write_ret = ql_audio_track_write(track_hd, tmp_buf, record_len);
printf("ql_pcm_write, pcm write:%d\n", write_ret);
}
ql_rtos_task_sleep_ms(15);
}
#endif
}