KT24-1110_65E-HA-651B/cpu/br25/audio_common/app_audio.c
2024-11-10 18:44:17 +08:00

1824 lines
54 KiB
C
Raw Permalink 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 "system/includes.h"
#include "media/includes.h"
#include "app_config.h"
#include "app_action.h"
#include "app_main.h"
#include "audio_config.h"
#include "audio_dec.h"
#include "application/audio_output_dac.h"
#include "application/audio_dig_vol.h"
struct audio_dac_hdl dac_hdl;
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
#include "fm_emitter/fm_emitter_manage.h"
#endif
#include "update.h"
#if (defined(AUDIO_OUTPUT_WAY) && AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
extern void bt_emitter_set_vol(u8 vol);
#endif
#define LOG_TAG "[APP_AUDIO]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define DEFAULT_DIGTAL_VOLUME 16384
typedef short unaligned_u16 __attribute__((aligned(1)));
struct app_audio_config {
u8 state;
u8 prev_state;
volatile u8 fade_gain_l;
volatile u8 fade_gain_r;
volatile s16 fade_dgain_l;
volatile s16 fade_dgain_r;
volatile s16 fade_dgain_step_l;
volatile s16 fade_dgain_step_r;
volatile int save_vol_timer;
volatile u8 save_vol_cnt;
s16 digital_volume;
atomic_t ref;
s16 max_volume[APP_AUDIO_MAX_STATE];
u8 sys_cvol_max;
u8 call_cvol_max;
unaligned_u16 *sys_cvol;
unaligned_u16 *call_cvol;
};
static const char *audio_state[] = {
"idle",
"music",
"call",
"tone",
"linein",
"err",
};
struct dac_ch_delay_config {
u32 delay_time;
u32 protect_time;
u32 start_delay;
};
static struct app_audio_config app_audio_cfg = {0};
static struct dac_ch_delay_config dac_ch_delay_cfg = {0};
#define __this (&app_audio_cfg)
extern struct dac_platform_data dac_data;
extern struct audio_dac_hdl dac_hdl;
extern struct audio_adc_hdl adc_hdl;
OS_SEM dac_sem;
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
s16 dac_buff[1 * 1024] SEC(.dac_buff);
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS)
s16 dac_buff[1 * 1024] SEC(.dac_buff);
#elif AUDIO_OUTPUT_INCLUDE_DAC
s16 dac_buff[4 * 1024] SEC(.dac_buff);
/* s16 dac_buff[128] SEC(.dac_buff); */
#endif
/*
*********************************************************************
* Set Dac Channel Delay Time
* Description: 设置DAC 通道的启动延时
* Arguments : dac_delay_ms 启动延时(单位ms,传0代表使用默认配置)
* save_last_config_en 是否保存上一次DAC的延时配置(1:保存0不保存)
* Return : NULL
* Note(s) : 该接口用于设置DAC通道启动的延时
*********************************************************************
*/
void set_dac_start_delay_time(u16 dac_delay_ms, u8 save_last_config_en)
{
struct audio_dac_channel_attr attr;
audio_dac_channel_get_attr(&default_dac, &attr);
if (save_last_config_en) {
dac_ch_delay_cfg.delay_time = attr.delay_time;
dac_ch_delay_cfg.start_delay = attr.start_delay;
dac_ch_delay_cfg.protect_time = attr.protect_time;
}
if (dac_delay_ms) {
attr.start_delay = dac_delay_ms;
attr.protect_time = 0;
audio_dac_channel_set_attr(&default_dac, &attr);
} else {
attr.delay_time = dac_ch_delay_cfg.delay_time;
attr.protect_time = dac_ch_delay_cfg.protect_time;
attr.start_delay = dac_ch_delay_cfg.start_delay;
audio_dac_channel_set_attr(&default_dac, &attr);
}
}
/*从audio中申请一块空间给use使用*/
void *app_audio_alloc_use_buff(int use_len)
{
void *buf = NULL;
#if AUDIO_OUTPUT_INCLUDE_DAC
printf("uselen:%d, total:%d \n", use_len, sizeof(dac_buff));
if (use_len + (2 * 1024) > sizeof(dac_buff)) {
y_printf("dac buff < uselen\n");
return NULL;
}
int dac_len = ((sizeof(dac_buff) - use_len) * 4) / 4;
audio_dac_reset_buf(&dac_hdl, dac_buff, dac_len, 0);
return (u8 *)dac_buff + dac_len;
#endif
return buf;
}
/*释放从audio中申请的空间*/
void app_audio_release_use_buff(void *buf)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
printf("app_audio_release_use_buff \n");
if (buf) {
audio_dac_reset_buf(&dac_hdl, dac_buff, sizeof(dac_buff), 1);
}
#endif
}
/*关闭audio相关模块使能*/
void audio_disable_all(void)
{
//DAC:DACEN
JL_AUDIO->DAC_CON &= ~BIT(4);
//ADC:ADCEN
JL_AUDIO->ADC_CON &= ~BIT(4);
//EQ:
JL_EQ->CON0 &= ~BIT(0);
//FFT:
JL_FFT->CON = BIT(1);//置1强制关闭模块不管是否已经运算完成
}
REGISTER_UPDATE_TARGET(audio_update_target) = {
.name = "audio",
.driver_close = audio_disable_all,
};
/*
*************************************************************
*
* audio volume save
*
*************************************************************
*/
static void app_audio_volume_save_do(void *priv)
{
/* log_info("app_audio_volume_save_do %d\n", __this->save_vol_cnt); */
local_irq_disable();
if (++__this->save_vol_cnt >= 5) {
sys_timer_del(__this->save_vol_timer);
__this->save_vol_timer = 0;
__this->save_vol_cnt = 0;
local_irq_enable();
log_info("VOL_SAVE\n");
syscfg_write(CFG_MUSIC_VOL, &app_var.music_volume, 1);//中断里不能操作vm 关中断不能操作vm
return;
}
local_irq_enable();
}
static void app_audio_volume_change(void)
{
local_irq_disable();
__this->save_vol_cnt = 0;
if (__this->save_vol_timer == 0) {
__this->save_vol_timer = sys_timer_add(NULL, app_audio_volume_save_do, 1000);//中断里不能操作vm 关中断不能操作vm
}
local_irq_enable();
}
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
__attribute__((weak))
void bt_emitter_set_vol(u8 vol)
{
}
#endif
static int audio_vol_set(u8 gain_l, u8 gain_r, u8 fade)
{
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
return 0;
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS)
extern void *iis_digvol_last;
if (iis_digvol_last) {
audio_dig_vol_set(iis_digvol_last, AUDIO_DIG_VOL_ALL_CH, gain_l);
}
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
bt_emitter_set_vol(gain_l);
#endif
local_irq_disable();
__this->fade_gain_l = gain_l;
__this->fade_gain_r = gain_r;
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_L)
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), gain_l, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_l ? DEFAULT_DIGTAL_VOLUME : 0, fade);
#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R)
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), gain_r, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_r ? DEFAULT_DIGTAL_VOLUME : 0, fade);
#else
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), gain_l, fade);
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), gain_r, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_l ? DEFAULT_DIGTAL_VOLUME : 0, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(1), gain_r ? DEFAULT_DIGTAL_VOLUME : 0, fade);
#endif
local_irq_enable();
return 0;
}
#if (SYS_VOL_TYPE == VOL_TYPE_AD)
#define DGAIN_SET_MAX_STEP (300)
#define DGAIN_SET_MIN_STEP (30)
static unsigned short combined_vol_list[31][2] = {
{ 0, 0}, //0: None
{ 0, 16384}, // 1:-40.92 db
{ 2, 14124}, // 2:-39.51 db
{ 3, 14240}, // 3:-38.10 db
{ 4, 14326}, // 4:-36.69 db
{ 5, 14427}, // 5:-35.28 db
{ 6, 14562}, // 6:-33.87 db
{ 7, 14681}, // 7:-32.46 db
{ 8, 14802}, // 8:-31.05 db
{ 9, 14960}, // 9:-29.64 db
{10, 15117}, // 10:-28.22 db
{11, 15276}, // 11:-26.81 db
{12, 15366}, // 12:-25.40 db
{13, 15528}, // 13:-23.99 db
{14, 15675}, // 14:-22.58 db
{15, 15731}, // 15:-21.17 db
{16, 15535}, // 16:-19.76 db
{17, 15609}, // 17:-18.35 db
{18, 15684}, // 18:-16.93 db
{19, 15777}, // 19:-15.52 db
{20, 15851}, // 20:-14.11 db
{21, 15945}, // 21:-12.70 db
{22, 16002}, // 22:-11.29 db
{23, 16006}, // 23:-9.88 db
{24, 16050}, // 24:-8.47 db
{25, 16089}, // 25:-7.06 db
{26, 16154}, // 26:-5.64 db
{27, 16230}, // 27:-4.23 db
{28, 16279}, // 28:-2.82 db
{29, 16328}, // 29:-1.41 db
{30, 16384}, // 30:0.00 db
};
static unsigned short call_combined_vol_list[16][2] = {
{ 0, 0}, //0: None
{ 0, 16384}, // 1:-40.92 db
{ 2, 15345}, // 2:-38.79 db
{ 4, 14374}, // 3:-36.66 db
{ 5, 15726}, // 4:-34.53 db
{ 7, 14782}, // 5:-32.40 db
{ 8, 16191}, // 6:-30.27 db
{10, 15271}, // 7:-28.14 db
{12, 14336}, // 8:-26.00 db
{13, 15739}, // 9:-23.87 db
{15, 14725}, // 10:-21.74 db
{16, 15799}, // 11:-19.61 db
{18, 14731}, // 12:-17.48 db
{19, 16098}, // 13:-15.35 db
{21, 15027}, // 14:-13.22 db
{22, 16384}, // 15:-11.09 db
};
void audio_combined_vol_init(u8 cfg_en)
{
u16 sys_cvol_len = 0;
u16 call_cvol_len = 0;
u8 *sys_cvol = NULL;
u8 *call_cvol = NULL;
s16 *cvol;
log_info("audio_combined_vol_init\n");
__this->sys_cvol_max = ARRAY_SIZE(combined_vol_list) - 1;
__this->sys_cvol = combined_vol_list;
__this->call_cvol_max = ARRAY_SIZE(call_combined_vol_list) - 1;
__this->call_cvol = call_combined_vol_list;
if (cfg_en) {
sys_cvol = syscfg_ptr_read(CFG_COMBINE_SYS_VOL_ID, &sys_cvol_len);
if (sys_cvol && sys_cvol_len) {
__this->sys_cvol = (unaligned_u16 *)sys_cvol;
__this->sys_cvol_max = sys_cvol_len / 4 - 1;
printf("read sys_cvol ok\n");
} else {
printf("read sys_cvol false:%x,%x\n", sys_cvol, sys_cvol_len);
}
call_cvol = syscfg_ptr_read(CFG_COMBINE_CALL_VOL_ID, &call_cvol_len);
if (call_cvol && call_cvol_len) {
__this->call_cvol = (unaligned_u16 *)call_cvol;
__this->call_cvol_max = call_cvol_len / 4 - 1;
printf("read call_cvol ok\n");
} else {
printf("read call_combine_vol false:%x,%x\n", call_cvol, call_cvol_len);
}
}
log_info("sys_cvol_max:%d,call_cvol_max:%d\n", __this->sys_cvol_max, __this->call_cvol_max);
}
static int audio_combined_vol_set(u8 gain_l, u8 gain_r, u8 fade)
{
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
return 0;
#endif
u8 gain_max;
u8 target_again_l = 0;
u8 target_again_r = 0;
u16 target_dgain_l = 0;
u16 target_dgain_r = 0;
if (__this->state == APP_AUDIO_STATE_CALL) {
gain_max = __this->call_cvol_max;
gain_l = (gain_l > gain_max) ? gain_max : gain_l;
gain_r = (gain_r > gain_max) ? gain_max : gain_r;
target_again_l = *(&__this->call_cvol[gain_l * 2]);
target_again_r = *(&__this->call_cvol[gain_r * 2]);
target_dgain_l = *(&__this->call_cvol[gain_l * 2 + 1]);
target_dgain_r = *(&__this->call_cvol[gain_r * 2 + 1]);
} else {
gain_max = __this->sys_cvol_max;
gain_l = (gain_l > gain_max) ? gain_max : gain_l;
gain_r = (gain_r > gain_max) ? gain_max : gain_r;
target_again_l = *(&__this->sys_cvol[gain_l * 2]);
target_again_r = *(&__this->sys_cvol[gain_r * 2]);
target_dgain_l = *(&__this->sys_cvol[gain_l * 2 + 1]);
target_dgain_r = *(&__this->sys_cvol[gain_r * 2 + 1]);
}
y_printf("[l]v:%d,Av:%d,Dv:%d", gain_l, target_again_l, target_dgain_l);
local_irq_disable();
__this->fade_gain_l = target_again_l;
__this->fade_gain_r = target_again_r;
__this->fade_dgain_l = target_dgain_l;
__this->fade_dgain_r = target_dgain_r;
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_L)
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), __this->fade_gain_l, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), __this->fade_dgain_l, fade);
#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R)
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), __this->fade_gain_r, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), __this->fade_dgain_r, fade);
#else
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), __this->fade_gain_l, fade);
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), __this->fade_gain_r, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), __this->fade_dgain_l, fade);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(1), __this->fade_dgain_r, fade);
#endif
local_irq_enable();
return 0;
}
#endif // (SYS_VOL_TYPE == VOL_TYPE_AD)
void volume_up_down_direct(s8 value)
{
// reserve
}
void audio_fade_in_fade_out(u8 left_gain, u8 right_gain, u8 fade)
{
#if (SYS_VOL_TYPE == VOL_TYPE_AD)
audio_combined_vol_set(left_gain, right_gain, fade);
#else
audio_vol_set(left_gain, right_gain, fade);
#endif/*SYS_VOL_TYPE == VOL_TYPE_AD*/
}
extern char *music_dig_logo[];
extern void *sys_digvol_group;
void app_audio_set_volume(u8 state, s8 volume, u8 fade)
{
char *digvol_type = NULL ;
#if (SMART_BOX_EN)
extern bool smartbox_set_volume(s8 volume);
if (smartbox_set_volume(volume)) {
return;
}
#endif/*SMART_BOX_EN*/
switch (state) {
case APP_AUDIO_STATE_IDLE:
case APP_AUDIO_STATE_MUSIC:
case APP_AUDIO_STATE_LINEIN:
#if SYS_DIGVOL_GROUP_EN
digvol_type = "music_type";
#endif/*SYS_DIGVOL_GROUP_EN*/
app_var.music_volume = volume;
if (app_var.music_volume > get_max_sys_vol()) {
app_var.music_volume = get_max_sys_vol();
}
volume = app_var.music_volume;
break;
case APP_AUDIO_STATE_CALL:
#if SYS_DIGVOL_GROUP_EN
digvol_type = "call_esco";
#endif/*SYS_DIGVOL_GROUP_EN*/
app_var.call_volume = volume;
if (app_var.call_volume > 15) {
app_var.call_volume = 15;
}
#if (SYS_VOL_TYPE == VOL_TYPE_ANALOG)
/*
*SYS_VOL_TYPE == VOL_TYPE_ANALOG的时候
*将通话音量最大值按照手机通话的音量等级进行等分
*由于等级不匹配,会出现对应有些等级没有一一对应
*的情况,如果在意,建议使用以下其中一种:
*#define TCFG_CALL_USE_DIGITAL_VOLUME 1
*#define SYS_VOL_TYPE VOL_TYPE_AD
*#define SYS_VOL_TYPE VOL_TYPE_DIGITAL
*/
volume = app_var.aec_dac_gain * app_var.call_volume / 15;
#endif/*SYS_VOL_TYPE == VOL_TYPE_ANALOG*/
#if TCFG_CALL_USE_DIGITAL_VOLUME
audio_dac_vol_set(TYPE_DAC_DGAIN, \
BIT(0) | BIT(1), \
16384L * (s32)app_var.call_volume / (s32)__this->max_volume[APP_AUDIO_STATE_CALL], \
1);
return;
#endif/*TCFG_CALL_USE_DIGITAL_VOLUME*/
break;
case APP_AUDIO_STATE_WTONE:
#if SYS_DIGVOL_GROUP_EN
digvol_type = "tone_tone";
#endif/*SYS_DIGVOL_GROUP_EN*/
#if TONE_MODE_DEFAULE_VOLUME != 0
app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME;
volume = app_var.wtone_volume;
break;
#endif
#if APP_AUDIO_STATE_WTONE_BY_MUSIC == 1
app_var.wtone_volume = app_var.music_volume;
if (app_var.wtone_volume < 5) {
app_var.wtone_volume = 5;
}
#else
app_var.wtone_volume = volume;
#endif
if (app_var.wtone_volume > get_max_sys_vol()) {
app_var.wtone_volume = get_max_sys_vol();
}
volume = app_var.wtone_volume;
break;
default:
return;
}
if (state == __this->state) {
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
fm_emitter_manage_set_vol(volume);
#else
#if defined (VOL_TYPE_DIGGROUP) && defined (SYS_DIGVOL_GROUP_EN)
if (state == APP_AUDIO_STATE_LINEIN) {
//printf("linein analog vol:%d\n",volume);
audio_fade_in_fade_out(volume, volume, fade);
return;
}
if (SYS_VOL_TYPE == VOL_TYPE_DIGGROUP && SYS_DIGVOL_GROUP_EN) {
if (sys_digvol_group == NULL) {
/* printf("the sys_digvol_group is NULL\n-------------------------------------------------------------"); */
return;
}
if (strcmp(digvol_type, "music_type") == 0) {
for (int i = 0; strcmp(music_dig_logo[i], "NULL") != 0; i++) {
/* printf("%s\n", music_dig_logo[i]); */
if (audio_dig_vol_group_hdl_get(sys_digvol_group, music_dig_logo[i]) == NULL) {
continue;
}
audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, music_dig_logo[i]), AUDIO_DIG_VOL_ALL_CH, volume);
}
} else {
if (audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type) == NULL) {
return;
}
audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type), AUDIO_DIG_VOL_ALL_CH, volume);
}
}
else {
audio_fade_in_fade_out(volume, volume, fade);
}
#else
audio_fade_in_fade_out(volume, volume, fade);
#endif //vol_type_diggroup
#endif //audio_output_way
}
app_audio_volume_change();
}
void app_audio_set_volume_each_channel(u8 state, s8 volume_l, s8 volume_r, u8 fade)
{
char *digvol_type = NULL ;
switch (state) {
case APP_AUDIO_STATE_IDLE:
case APP_AUDIO_STATE_MUSIC:
case APP_AUDIO_STATE_LINEIN:
#if SYS_DIGVOL_GROUP_EN
digvol_type = "music_type";
#endif
app_var.music_volume = volume_l;
app_var.music_volume_r = volume_r;
if (app_var.music_volume > get_max_sys_vol()) {
app_var.music_volume = get_max_sys_vol();
}
if (app_var.music_volume_r > get_max_sys_vol()) {
app_var.music_volume_r = get_max_sys_vol();
}
volume_l = app_var.music_volume;
volume_r = app_var.music_volume_r;
break;
case APP_AUDIO_STATE_CALL:
#if SYS_DIGVOL_GROUP_EN
digvol_type = "call_esco";
#endif
app_var.call_volume = volume_l;
app_var.call_volume_r = volume_r;
if (app_var.call_volume > 15) {
app_var.call_volume = 15;
}
if (app_var.call_volume_r > 15) {
app_var.call_volume_r = 15;
}
volume_l = app_var.aec_dac_gain * app_var.call_volume / 15;
volume_r = app_var.aec_dac_gain * app_var.call_volume_r / 15;
#if TCFG_CALL_USE_DIGITAL_VOLUME
audio_digital_vol_set(volume_l);
return;
#endif
break;
case APP_AUDIO_STATE_WTONE:
#if SYS_DIGVOL_GROUP_EN
digvol_type = "tone_tone";
#endif
#if (TONE_MODE_DEFAULE_VOLUME != 0)
app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME;
volume_l = volume_r = app_var.wtone_volume;
break;
#endif
#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1)
app_var.wtone_volume = app_var.music_volume;
app_var.wtone_volume_r = app_var.music_volume_r;
if (app_var.wtone_volume < 5) {
app_var.wtone_volume = 5;
}
if (app_var.wtone_volume_r < 5) {
app_var.wtone_volume_r = 5;
}
#else
app_var.wtone_volume = volume_l;
app_var.wtone_volume_r = volume_r;
#endif
if (app_var.wtone_volume > get_max_sys_vol()) {
app_var.wtone_volume = get_max_sys_vol();
}
if (app_var.wtone_volume_r > get_max_sys_vol()) {
app_var.wtone_volume_r = get_max_sys_vol();
}
volume_l = app_var.wtone_volume;
volume_r = app_var.wtone_volume_r;
break;
default:
return;
}
if (state == __this->state) {
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
fm_emitter_manage_set_vol(volume);
#else
#if defined (VOL_TYPE_DIGGROUP) && defined (SYS_DIGVOL_GROUP_EN)
if (state == APP_AUDIO_STATE_LINEIN) {
//printf("linein analog vol:%d\n",volume);
audio_fade_in_fade_out(volume_l, volume_r, fade);
return;
}
if (SYS_VOL_TYPE == VOL_TYPE_DIGGROUP && SYS_DIGVOL_GROUP_EN) {
if (sys_digvol_group == NULL) {
/* printf("the sys_digvol_group is NULL\n-------------------------------------------------------------"); */
return;
}
if (strcmp(digvol_type, "music_type") == 0) {
for (int i = 0; music_dig_logo[i] != "NULL"; i++) {
/* printf("%s\n", music_dig_logo[i]); */
if (audio_dig_vol_group_hdl_get(sys_digvol_group, music_dig_logo[i]) == NULL) {
continue;
}
audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type), AUDIO_DIG_VOL_CH(0), volume_l);
audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type), AUDIO_DIG_VOL_CH(1), volume_r);
/* audio_dig_vol_group_vol_set(sys_digvol_group, music_dig_logo[i], AUDIO_DIG_VOL_ALL_CH, volume); */
}
} else {
if (audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type) == NULL) {
return;
}
audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type), AUDIO_DIG_VOL_CH(0), volume_l);
audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type), AUDIO_DIG_VOL_CH(1), volume_r);
/* audio_dig_vol_group_vol_set(sys_digvol_group, digvol_type, AUDIO_DIG_VOL_ALL_CH, volume); */
}
} else {
audio_fade_in_fade_out(volume_l, volume_r, fade);
}
#else
audio_fade_in_fade_out(volume_l, volume_r, fade);
#endif //vol_type_diggroup
#endif //audio_output_way
}
app_audio_volume_change();
}
void app_audio_volume_init(void)
{
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, app_var.music_volume, 1);
}
s8 app_audio_get_volume(u8 state)
{
s8 volume = 0;
switch (state) {
case APP_AUDIO_STATE_IDLE:
case APP_AUDIO_STATE_MUSIC:
case APP_AUDIO_STATE_LINEIN:
volume = app_var.music_volume;
break;
case APP_AUDIO_STATE_CALL:
volume = app_var.call_volume;
break;
case APP_AUDIO_STATE_WTONE:
#if TONE_MODE_DEFAULE_VOLUME != 0
app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME;
volume = app_var.wtone_volume;
break;
#endif
#if APP_AUDIO_STATE_WTONE_BY_MUSIC == 1
volume = app_var.music_volume;
break;
#else
volume = app_var.wtone_volume;
/* if (!volume) { */
/* volume = app_var.music_volume; */
/* } */
break;
#endif
case APP_AUDIO_CURRENT_STATE:
volume = app_audio_get_volume(__this->state);
break;
default:
break;
}
/* printf("app_audio_get_volume %d %d\n", state, volume); */
return volume;
}
static const char *audio_mute_string[] = {
"mute_default",
"unmute_default",
"mute_L",
"unmute_L",
"mute_R",
"unmute_R",
};
void app_audio_mute(u8 value)
{
u8 volume = 0;
printf("audio_mute:%s", audio_mute_string[value]);
switch (value) {
case AUDIO_MUTE_DEFAULT:
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
fm_emitter_manage_set_vol(0);
#else
audio_dac_vol_mute(1, 1);
#endif
break;
case AUDIO_UNMUTE_DEFAULT:
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
volume = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
fm_emitter_manage_set_vol(volume);
#else
audio_dac_vol_mute(0, 1);
#endif
break;
}
}
void app_audio_volume_up(u8 value)
{
#if (SMART_BOX_EN)
extern bool smartbox_key_volume_up(u8 value);
if (smartbox_key_volume_up(value)) {
return;
}
#endif
s16 volume = 0;
switch (__this->state) {
case APP_AUDIO_STATE_IDLE:
case APP_AUDIO_STATE_MUSIC:
case APP_AUDIO_STATE_LINEIN:
app_var.music_volume += value;
if (app_var.music_volume > get_max_sys_vol()) {
app_var.music_volume = get_max_sys_vol();
}
volume = app_var.music_volume;
break;
case APP_AUDIO_STATE_CALL:
app_var.call_volume += value;
if (app_var.call_volume > 15) {
app_var.call_volume = 15;
}
volume = app_var.call_volume;
break;
case APP_AUDIO_STATE_WTONE:
#if TONE_MODE_DEFAULE_VOLUME != 0
app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME;
volume = app_var.wtone_volume;
break;
#endif
#if APP_AUDIO_STATE_WTONE_BY_MUSIC == 1
app_var.wtone_volume = app_var.music_volume;
#endif
app_var.wtone_volume += value;
if (app_var.wtone_volume > get_max_sys_vol()) {
app_var.wtone_volume = get_max_sys_vol();
}
volume = app_var.wtone_volume;
#if APP_AUDIO_STATE_WTONE_BY_MUSIC == 1
app_var.music_volume = app_var.wtone_volume;
#endif
break;
default:
return;
}
app_audio_set_volume(__this->state, volume, 1);
}
void app_audio_volume_down(u8 value)
{
#if (SMART_BOX_EN)
extern bool samrtbox_key_volume_down(u8 value);
if (smartbox_key_volume_up(value)) {
return;
}
#endif
s16 volume = 0;
switch (__this->state) {
case APP_AUDIO_STATE_IDLE:
case APP_AUDIO_STATE_MUSIC:
case APP_AUDIO_STATE_LINEIN:
app_var.music_volume -= value;
if (app_var.music_volume < 0) {
app_var.music_volume = 0;
}
volume = app_var.music_volume;
break;
case APP_AUDIO_STATE_CALL:
app_var.call_volume -= value;
if (app_var.call_volume < 0) {
app_var.call_volume = 0;
}
volume = app_var.call_volume;
break;
case APP_AUDIO_STATE_WTONE:
#if TONE_MODE_DEFAULE_VOLUME != 0
app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME;
volume = app_var.wtone_volume;
break;
#endif
#if APP_AUDIO_STATE_WTONE_BY_MUSIC == 1
app_var.wtone_volume = app_var.music_volume;
#endif
app_var.wtone_volume -= value;
if (app_var.wtone_volume < 0) {
app_var.wtone_volume = 0;
}
volume = app_var.wtone_volume;
#if APP_AUDIO_STATE_WTONE_BY_MUSIC == 1
app_var.music_volume = app_var.wtone_volume;
#endif
break;
default:
return;
}
app_audio_set_volume(__this->state, volume, 1);
}
void app_audio_state_switch(u8 state, s16 max_volume)
{
r_printf("audio state old:%s,new:%s,vol:%d\n", audio_state[__this->state], audio_state[state], max_volume);
__this->prev_state = __this->state;
__this->state = state;
#if TCFG_CALL_USE_DIGITAL_VOLUME
if (__this->state == APP_AUDIO_STATE_CALL) {
/*调数字音量的时候,模拟音量定最大*/
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1), max_volume, 1);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 0, 1);
}
#endif
/*限制最大音量*/
__this->digital_volume = DEFAULT_DIGTAL_VOLUME;
__this->max_volume[state] = max_volume;
if (__this->state == APP_AUDIO_STATE_CALL) {
__this->max_volume[state] = 15;
}
#if (SYS_VOL_TYPE ==VOL_TYPE_DIGGROUP)
u8 dac_connect_mode = app_audio_output_mode_get();
switch (dac_connect_mode) {
case DAC_OUTPUT_MONO_L :
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), 30, 1);
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), 0, 1);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 16384, 1);
break;
case DAC_OUTPUT_MONO_R :
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), 30, 1);
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), 0, 1);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 16384, 1);
break;
default :
audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1), 30, 1);
audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 16384, 1);
}
#endif
app_audio_set_volume(__this->state, app_audio_get_volume(__this->state), 1);
}
void app_audio_state_exit(u8 state)
{
#if TCFG_CALL_USE_DIGITAL_VOLUME
if (__this->state == APP_AUDIO_STATE_CALL) {
}
#endif
r_printf("audio state now:%s,prev:%s\n", audio_state[__this->state], audio_state[__this->prev_state]);
if (state == __this->state) {
__this->state = __this->prev_state;
__this->prev_state = APP_AUDIO_STATE_IDLE;
} else if (state == __this->prev_state) {
__this->prev_state = APP_AUDIO_STATE_IDLE;
}
app_audio_set_volume(__this->state, app_audio_get_volume(__this->state), 1);
}
u8 app_audio_get_state(void)
{
return __this->state;
}
s16 app_audio_get_max_volume(void)
{
if (__this->state == APP_AUDIO_STATE_IDLE) {
return get_max_sys_vol();
}
return __this->max_volume[__this->state];
}
void dac_power_on(void)
{
log_info(">>>dac_power_on:%d", __this->ref.counter);
if (atomic_inc_return(&__this->ref) == 1) {
audio_dac_open(&dac_hdl);
}
}
void dac_sniff_power_off(void)
{
audio_dac_close(&dac_hdl);
}
void dac_power_off(void)
{
/* log_info(">>>dac_power_off:%d", __this->ref.counter); */
/* if (atomic_dec_return(&__this->ref)) { */
/* return; */
/* } */
#if 0
app_audio_mute(AUDIO_MUTE_DEFAULT);
if (dac_hdl.vol_l || dac_hdl.vol_r) {
u8 fade_time = dac_hdl.vol_l * 2 / 10 + 1;
os_time_dly(fade_time);
printf("fade_time:%d ms", fade_time);
}
#endif
audio_dac_close(&dac_hdl);
}
/*
*自定义dac上电延时时间具体延时多久应通过示波器测量
*/
#if 1
void dac_power_on_delay()
{
#if TCFG_MC_BIAS_AUTO_ADJUST
void mic_capless_auto_adjust_init();
mic_capless_auto_adjust_init();
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
os_time_dly(50);
}
#endif
#if TCFG_MIC_CAPLESS_ENABLE
//#define LADC_CAPLESS_INFO_DEBUG
#ifdef LADC_CAPLESS_INFO_DEBUG
/*
* adcdso:正负1000之内
* dacr32(正常范围:稳定在正负28000之内)
*/
void ladc_capless_info(s16 adcdso, s32 dacr32, s32 pout, s32 tmps8)
{
printf("[%d, %d, %d, %d]\n", adcdso, dacr32, pout, tmps8);
}
#endif
static void mic_capless_feedback_toggle(u8 toggle);
#define LADC_CAPLESS_ADJUST_SAVE
#ifdef LADC_CAPLESS_ADJUST_SAVE
#define DIFF_RANGE 50
#define CFG_DIFF_RANGE 200
#define CHECK_INTERVAL 7
#define DACR32_DEFAULT 32767
#define MIC_CAPLESS_ADJUST_BUD_DEFAULT 0
#define MIC_CAPLESS_ADJUST_BUD 100
/*不支持自动校准,使用快速收敛*/
#if TCFG_MC_BIAS_AUTO_ADJUST
u8 mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD_DEFAULT;
#else
u8 mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
#endif
s16 read_capless_DTB(void)
{
s16 dacr32 = 32767;
int ret = syscfg_read(CFG_DAC_DTB, &dacr32, 2);
printf("cfg DAC_DTB:%d,ret = %d\n", dacr32, ret);
/*没有记忆值,使用默认值*/
if (ret != 2) {
/*没有收敛值的时候,使用快速收敛*/
//printf("DAC_DTB NULL,use fast feedback");
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
/*
*未初始化状态,返回默认收敛值。可以通过修改默认收敛值,使其
*接近最终收敛值,来加快预收敛时间。比如最终收敛值是-2500
*可以把默认收敛值设置成-2000左右因为不同的样机稍微有点小差
*异,所以这个值不用那么精确,只要差不多就行了。
*/
return 32767;
}
return dacr32;
}
s16 read_vm_capless_DTB(void)
{
s16 vm_dacr32 = 32767;
int ret = syscfg_read(CFG_DAC_DTB, &vm_dacr32, 2);
printf("vm DAC_DTB:%d,ret = %d\n", vm_dacr32, ret);
if (ret != 2) {
return DACR32_DEFAULT;
}
return vm_dacr32;
}
s16 save_dacr32 = DACR32_DEFAULT;
static u8 adjust_complete = 0;
static u16 dtb_step_limit = 0; /*dtb收敛步进限制*/
void save_capless_DTB()
{
s16 diff;
//printf("save_capless_DTB\n");
if ((save_dacr32 != DACR32_DEFAULT) && adjust_complete) {
/*比较是否需要更新配置*/
s16 cfg_dacr32 = read_vm_capless_DTB();
adjust_complete = 0;
diff = save_dacr32 - cfg_dacr32;
if ((cfg_dacr32 == DACR32_DEFAULT) || ((diff < -CFG_DIFF_RANGE) || (diff > CFG_DIFF_RANGE))) {
log_info("dacr32 write:%d\n", save_dacr32);
syscfg_write(CFG_DAC_DTB, &save_dacr32, 2);
/* s16 tmp_dacr32;
syscfg_read(CFG_DAC_DTB,&tmp_dacr32,2);
printf("dacr32 read:%d\n",tmp_dacr32); */
} else {
log_info("dacr32 need't update:%d,diff:%d\n", save_dacr32, diff);
}
} else {
log_info("dacr32 adjust uncomplete:%d,complete:%d\n", save_dacr32, adjust_complete);
}
}
void ladc_capless_adjust_post(s32 dacr32, u8 begin)
{
static s32 last_dacr32 = 0;
static u8 check_cnt = 0;
s32 dacr32_diff;
/*adjust_begin,clear*/
if (begin) {
printf("dtb_step_limit = %d\n", dtb_step_limit);
last_dacr32 = 0;
adjust_complete = 0;
check_cnt = 0;
save_dacr32 = DACR32_DEFAULT;
return;
}
#if TCFG_MC_CONVERGE_TRACE
printf("<%d>", dacr32);
#endif/*MIC_CAPLESS_CONVERGE_TRACE*/
if (adjust_complete == 0) {
if (++check_cnt > CHECK_INTERVAL) {
check_cnt = 0;
dacr32_diff = dacr32 - last_dacr32;
//printf("[capless:%d-%d-%d]",dacr32,last_dacr32,dacr32_diff);
last_dacr32 = dacr32;
if (adjust_complete == 0) {
save_dacr32 = dacr32;
}
/*调整稳定*/
if ((dacr32_diff > -DIFF_RANGE) && (dacr32_diff < DIFF_RANGE)) {
log_info("adjust_OK:%d\n", dacr32);
adjust_complete = 1;
#if TCFG_MC_BIAS_AUTO_ADJUST
mic_capless_feedback_toggle(0);
#endif
}
}
}
}
#endif
/*
*dac快速校准
*/
//#define DAC_TRIM_FAST_EN
#ifdef DAC_TRIM_FAST_EN
u8 dac_trim_fast_en()
{
return 1;
}
#endif
/*
*capless模式一开始不要的数据包数量
*/
u16 get_ladc_capless_dump_num(void)
{
return 10;
}
/*
*mic省电容模式自动收敛
*/
u8 mic_capless_feedback_sw = 0;
static u8 audio_mc_idle_query(void)
{
return (mic_capless_feedback_sw ? 0 : 1);
}
REGISTER_LP_TARGET(audio_mc_device_lp_target) = {
.name = "audio_mc_device",
.is_idle = audio_mc_idle_query,
};
/*快调慢调边界*/
u16 get_ladc_capless_bud(void)
{
//printf("mc_bud:%d",mic_capless_adjust_bud);
return mic_capless_adjust_bud;
}
extern int audio_adc_mic_init(u16 sr);
extern void audio_adc_mic_exit(void);
int audio_mic_capless_feedback_control(u8 en, u16 sr)
{
int ret = 0;
if (en) {
ret = audio_adc_mic_init(sr);
} else {
audio_adc_mic_exit();
}
return ret;
}
OS_SEM mc_sem;
/*收敛的前提是偏置电压合法*/
static void mic_capless_feedback_toggle(u8 toggle)
{
int ret = 0;
log_info("mic_capless_feedback_toggle:%d-%d\n", mic_capless_feedback_sw, toggle);
if (toggle && (mic_capless_feedback_sw == 0)) {
mic_capless_feedback_sw = 1;
ret = audio_mic_capless_feedback_control(1, 32000);
if (ret == 0) {
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
}
os_sem_create(&mc_sem, 0);
} else if (mic_capless_feedback_sw) {
os_sem_post(&mc_sem);
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD_DEFAULT;
} else {
log_info("Nothing to do\n");
}
}
extern struct adc_platform_data adc_data;
#if TCFG_MC_BIAS_AUTO_ADJUST
static const u8 mic_bias_tab[] = {0, 20, 12, 28, 4, 18, 10, 26, 2, 22, 14, 30, 17, 21, 6, 25, 29, 27, 31, 5, 3, 7};
extern void delay_2ms(int cnt);
extern void wdt_clear(void);
extern void mic_analog_init(u8 mic_ldo_vsel, u8 mic_bias);
extern void mic_analog_close(struct adc_platform_data *pd);
void mic_capless_auto_adjust_init()
{
if (adc_data.mic_capless == 0) {
return;
}
log_info("mic_capless_bias_adjust_init:%d-%d\n", adc_data.mic_ldo_vsel, adc_data.mic_bias_res);
mic_analog_init(adc_data.mic_ldo_vsel, adc_data.mic_bias_res);
}
void mic_capless_auto_adjust_exit()
{
if (adc_data.mic_capless == 0) {
return;
}
log_info("mic_capless_bias_adjust_exit\n");
mic_analog_close(&adc_data);
}
/*AC696x系列只支持高压模式*/
#define MIC_BIAS_HIGH_UPPER_LIMIT 200 /*高压上限2.00v*/
#define MIC_BIAS_HIGH_LOWER_LIMIT 135 /*高压下限1.35v*/
#define ADC_MIC_IO IO_PORTA_01
#define ADC_MIC_CH AD_CH_PA1
#define MIC_BIAS_RSEL(x) SFR(JL_ANA->ADA_CON0, 6, 5, x)
#define MIC_LDO_SEL(x) SFR(JL_ANA->ADA_CON0, 2, 2, x)
/*
*return -1:非省电容模式
*return -2:校准失败
*return -3:麦掉线(坏了或者没焊接)
*return 0:默认值合法,不用校准
*return 1:默认值非法,启动校准
*/
#define MC_ERR_MODE -1
#define MC_ERR_TRIM_FAIL -2
#define MC_ERR_MIC_OFFLINE -3
#define MC_ERR_VALID 0
#define MC_ERR_INVALID 1
s8 mic_capless_auto_adjust(void)
{
u16 mic_bias_val = 0;
u8 mic_bias_idx = adc_data.mic_bias_res;
u8 mic_bias_compare = 0;
u16 bias_upper_limit = MIC_BIAS_HIGH_UPPER_LIMIT;
u16 bias_lower_limit = MIC_BIAS_HIGH_LOWER_LIMIT;
s8 ret = 0;
u8 err_cnt = 0;
u8 mic_ldo_idx = 0;
//printf("mic_capless_bias_adjust:%d\n",adc_data.mic_capless);
if (adc_data.mic_capless == 0) {
return -1;
}
log_info("mic_bias idx:%d,rsel:%d\n", mic_bias_idx, mic_bias_tab[mic_bias_idx]);
/*采样MIC_port(PA1)的偏置电压值*/
JL_PORTA->DIE &= ~BIT(1);
JL_PORTA->DIR |= BIT(1);
JL_PORTA->PU &= ~BIT(1);
JL_PORTA->PD &= ~BIT(1);
adc_add_sample_ch(ADC_MIC_CH);
#if 0
/*
*调试使用
*如果mic的偏置电压mic_bias_val稳定则表示延时足够否则加大延时知道电压值稳定
*/
while (1) {
wdt_clear();
MIC_BIAS_RSEL(mic_bias_tab[mic_bias_idx]);
delay_2ms(50);//延时等待偏置电压稳定
mic_bias_val = adc_get_voltage(ADC_MIC_CH) / 10;
log_info("mic_bias_val:%d,idx:%d,rsel:%d\n", mic_bias_val, mic_bias_idx, mic_bias_tab[mic_bias_idx]);
}
#endif
#if TCFG_MC_MIC_ONLINE_CHECK_EN
u8 tmp_rsel_idx = 1;
MIC_BIAS_RSEL(mic_bias_tab[tmp_rsel_idx]);
delay_2ms(25);//延时等待偏置电压稳定
u16 mic_bias_val_0 = adc_get_voltage(ADC_MIC_CH);
log_info("mic_bias_val:%d,idx:%d,rsel:%d\n", mic_bias_val_0, tmp_rsel_idx, mic_bias_tab[mic_bias_idx]);
tmp_rsel_idx = 16;
MIC_BIAS_RSEL(mic_bias_tab[tmp_rsel_idx]);
delay_2ms(25);//延时等待偏置电压稳定
u16 mic_bias_val_1 = adc_get_voltage(ADC_MIC_CH);
log_info("mic_bias_val:%d,idx:%d,rsel:%d\n", mic_bias_val_1, tmp_rsel_idx, mic_bias_tab[mic_bias_idx]);
u16 mic_bias_val_diff = __builtin_abs(mic_bias_val_0 - mic_bias_val_1);
log_info("mic_bias_val_diff:%d\n", mic_bias_val_diff);
if (mic_bias_val_diff < 500) {
printf("MIC_offline,Please check your layout!\n");
mic_capless_auto_adjust_exit();
return MC_ERR_MIC_OFFLINE;
}
#endif/*TCFG_MC_MIC_ONLEIN_CHECK_EN*/
while (1) {
wdt_clear();
MIC_BIAS_RSEL(mic_bias_tab[mic_bias_idx]);
delay_2ms(50);
mic_bias_val = adc_get_voltage(ADC_MIC_CH) / 10;
log_info("mic_bias_val:%d,idx:%d,rsel:%d\n", mic_bias_val, mic_bias_idx, mic_bias_tab[mic_bias_idx]);
if (mic_bias_val < bias_lower_limit) {
/*电压偏小,调小内部上拉偏置*/
mic_bias_compare |= BIT(0);
mic_bias_idx++;
if (mic_bias_idx >= sizeof(mic_bias_tab)) {
log_error("mic_bias_auto_adjust faild 0\n");
/*校准失败,使用快速收敛*/
//mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
ret = -2;
//break;
}
} else if (mic_bias_val > bias_upper_limit) {
/*电压偏大,调大内部上拉偏置*/
mic_bias_compare |= BIT(1);
if (mic_bias_idx) {
mic_bias_idx--;
} else {
log_error("mic_bias_auto_adjust faild 1\n");
/*校准失败,使用快速收敛*/
//mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
ret = -2;
//break;
}
} else {
if (mic_bias_compare) {
/*超出范围,调整过的值,保存*/
adc_data.mic_bias_res = mic_bias_idx;
log_info("mic_bias_adjust ok,idx:%d,rsel:%d\n", mic_bias_idx, mic_bias_tab[mic_bias_idx]);
/*记住校准过的值*/
ret = syscfg_write(CFG_MC_BIAS, &adc_data.mic_bias_res, 1);
log_info("mic_bias_adjust save ret = %d\n", ret);
ret = 1;
}
/*原本的MICLDO档位不合适保存新的MICLDO档位*/
if (err_cnt) {
adc_data.mic_ldo_vsel = mic_ldo_idx;
log_info("mic_ldo_vsel fix:%d\n", adc_data.mic_ldo_vsel);
//log_info("mic_bias:%d,idx:%d\n",adc_data.mic_bias_res,mic_bias_idx);
ret = syscfg_write(CFG_MIC_LDO_VSEL, &mic_ldo_idx, 1);
log_info("mic_ldo_vsel save ret = %d\n", ret);
ret = 1;
}
log_info("mic_bias valid:%d,idx:%d,res:%d\n", mic_bias_val, mic_bias_idx, mic_bias_tab[mic_bias_idx]);
break;
}
/*
*当前MICLDO分不出合适的偏置电压
* 选择1、修改MICLDO档位重新校准
* 选择2、直接退出跳出自动校准
*/
if ((mic_bias_compare == (BIT(0) | BIT(1))) || (ret == -2)) {
log_info("mic_bias_trim err,adjust micldo vsel\n");
ret = 0;
#if 1 /*选择1*/
/*从0开始遍历查询*/
if (err_cnt) {
mic_ldo_idx++;
}
err_cnt++;
/*跳过默认的ldo电压档*/
if (mic_ldo_idx == adc_data.mic_ldo_vsel) {
mic_ldo_idx++;
}
/*遍历结束没有合适的MICLDO电压档*/
if (mic_ldo_idx > 3) {
log_info("mic_bias_adjust tomeout\n");
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
ret = -3;
break;
}
log_info("mic_ldo_idx:%d", mic_ldo_idx);
MIC_LDO_SEL(mic_ldo_idx);
/*修改MICLDO电压档等待电压稳定*/
os_time_dly(20);
/*复位偏置电阻档位*/
mic_bias_idx = adc_data.mic_bias_res;
/*复位校准标志位*/
mic_bias_compare = 0;
#else /*选择2*/
log_info("mic_bias_trim err,break loop\n");
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
ret = -3;
break;
#endif
}
}
mic_capless_auto_adjust_exit();
return ret;
}
#endif
/*
*检查mic偏置是否需要校准,以下情况需要重新校准:
*1、power on reset
*2、vm被擦除
*3、每次开机都校准
*/
extern u8 power_reset_src;
u8 mc_bias_adjust_check()
{
#if(TCFG_MC_BIAS_AUTO_ADJUST == MC_BIAS_ADJUST_ALWAYS)
return 1;
#elif (TCFG_MC_BIAS_AUTO_ADJUST == MC_BIAS_ADJUST_ONE)
return 0;
#endif
u8 por_flag = 0;
int ret = syscfg_read(CFG_POR_FLAG, &por_flag, 1);
if (ret == 1) {
if (por_flag == 0xA5) {
log_info("power on reset 1");
por_flag = 0;
ret = syscfg_write(CFG_POR_FLAG, &por_flag, 1);
return 1;
}
}
if (power_reset_src & BIT(0)) {
log_info("power on reset 2");
return 1;
}
if (read_vm_capless_DTB() == DACR32_DEFAULT) {
log_info("vm format");
return 1;
}
return 0;
}
#if TCFG_MC_DTB_STEP_LIMIT
/*获取省电容mic收敛信息配置*/
int get_mc_dtb_step_limit(void)
{
return dtb_step_limit;
}
#endif /*TCFG_MC_DTB_STEP_LIMIT*/
/*
*pos = 1:dac trim begin
*pos = 2:dac trim end
*pos = 3:dac已经trim过(开机)
*pos = 4:dac已经读取过变量(过程)
*pos = 5:dac已经trim过(开机,dac模块初始化)
*/
extern void audio_dac2micbias_en(struct audio_dac_hdl *dac, u8 en);
void _audio_dac_trim_hook(u8 pos)
{
#if TCFG_MC_BIAS_AUTO_ADJUST
int ret = 0;
log_info("dac_trim_hook:%d\n", pos);
if ((adc_data.mic_capless == 0) || (pos == 0xFF)) {
return;
}
if (pos == 1) {
ret = mic_capless_auto_adjust();
if (ret >= 0) {
mic_capless_feedback_toggle(1);
} else {
/*校准出错的时候不做预收敛*/
log_info("auto_adjust err:%d\n", ret);
}
return;
} else if (pos == 2) {
if (mic_capless_feedback_sw) {
ret = os_sem_pend(&mc_sem, 250);
audio_mic_capless_feedback_control(0, 16000);
if (ret == OS_TIMEOUT) {
log_info("mc_trim1 timeout!\n");
} else {
dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT;
}
} else {
log_info("auto_feedback disable");
}
} else if (pos == 5) {
if (mc_bias_adjust_check()) {
//printf("MC_BIAS_ADJUST...");
void mic_capless_auto_adjust_init();
mic_capless_auto_adjust_init();
os_time_dly(25);
ret = mic_capless_auto_adjust();
if (ret == MC_ERR_MIC_OFFLINE) {
log_info("mic offline,return\n");
return;
}
/*
*预收敛条件:
*1、开机检查发现mic的偏置非法则校准回来同时重新收敛,比如中途更换mic头的情况
*2、收敛值丢失vm被擦除重新收敛一次(前提是校准成功)
*/
if ((ret == 1) || ((ret == 0) && (read_vm_capless_DTB() == DACR32_DEFAULT))) {
audio_dac2micbias_en(&dac_hdl, 1);
mic_capless_feedback_toggle(1);
ret = os_sem_pend(&mc_sem, 250);
audio_mic_capless_feedback_control(0, 16000);
audio_dac2micbias_en(&dac_hdl, 0);
if (ret == OS_TIMEOUT) {
log_info("mc_trim2 timeout!\n");
} else {
dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT;
}
} else {
log_info("auto_adjust err:%d\n", ret);
if (ret == 0) {
dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT;
}
}
} else {
log_info("MC_BIAS_OK...\n");
dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT;
}
}
mic_capless_feedback_sw = 0;
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
}
#endif/*TCFG_MIC_CAPLESS_ENABLE*/
////////////////////////////////// audio_output_api //////////////////////////////////////////////
#if 1
void _audio_dac_irq_hook(void)
{
/* putbyte('d'); */
extern struct audio_stream_dac_out *dac_last;
audio_stream_resume(&dac_last->entry);
}
void _audio_adc_irq_hook(void)
{
/* putbyte('a'); */
extern struct audio_adc_hdl adc_hdl;
audio_adc_irq_handler(&adc_hdl);
}
/*******************************************************
* Function name : app_audio_output_init
* Description : 音频输出设备初始化
* Return : None
********************* -HB ******************************/
void app_audio_output_init(void)
{
#if (AUDIO_OUTPUT_INCLUDE_DAC|| TCFG_AUDIO_ADC_ENABLE)
audio_dac_init(&dac_hdl, &dac_data);
#endif
#if AUDIO_OUTPUT_INCLUDE_DAC
#if TCFG_MIC_CAPLESS_ENABLE
/*初始化DAC_DTB*/
s16 dacr32 = read_capless_DTB();
audio_dac_set_capless_DTB(&dac_hdl, dacr32);
#endif/*TCFG_MIC_CAPLESS_ENABLE*/
audio_dac_set_buff(&dac_hdl, dac_buff, sizeof(dac_buff));
struct audio_dac_trim dac_trim;
int len = syscfg_read(CFG_DAC_TRIM_INFO, (void *)&dac_trim, sizeof(dac_trim));
if (len != sizeof(dac_trim) || dac_trim.left == 0 || dac_trim.right == 0) {
audio_dac_do_trim(&dac_hdl, &dac_trim, 0);
syscfg_write(CFG_DAC_TRIM_INFO, (void *)&dac_trim, sizeof(dac_trim));
} else {
#if TCFG_MIC_CAPLESS_ENABLE
_audio_dac_trim_hook(5);
#endif/*TCFG_MIC_CAPLESS_ENABLE*/
}
audio_dac_set_trim_value(&dac_hdl, &dac_trim);
audio_dac_set_delay_time(&dac_hdl, 30, 50);
#endif
}
/*******************************************************
* Function name : app_audio_output_sync_buff_init
* Description : 设置音频输出设备同步功能 buf
* Parameter :
* @sync_buff buf 起始地址
* @len buf 长度
* Return : None
********************* -HB ******************************/
void app_audio_output_sync_buff_init(void *sync_buff, int len)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
/*音频同步DA端buffer设置*/
/*audio_output_dac_sync_buff_init(sync_buff, len);*/
#endif
}
/*******************************************************
* Function name : app_audio_output_samplerate_select
* Description : 将输入采样率与输出采样率进行匹配对比
* Parameter :
* @sample_rate 输入采样率
* @high: 0 - 低一级采样率1 - 高一级采样率
* Return : 匹配后的采样率
********************* -HB ******************************/
int app_audio_output_samplerate_select(u32 sample_rate, u8 high)
{
return audio_dac_sample_rate_select(&dac_hdl, sample_rate, high);
}
/*******************************************************
* Function name : app_audio_output_samplerate_set
* Description : 设置音频输出设备的采样率
* Parameter :
* @sample_rate 采样率
* Return : 0 success, other fail
********************* -HB ******************************/
int app_audio_output_samplerate_set(int sample_rate)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_set_sample_rate(&dac_hdl, sample_rate);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_samplerate_get
* Description : 获取音频输出设备的采样率
* Return : 音频输出设备的采样率
********************* -HB ******************************/
int app_audio_output_samplerate_get(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_get_sample_rate(&dac_hdl);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_mode_get
* Description : 获取当前硬件输出模式
* Return : 输出模式
********************* -HB ******************************/
int app_audio_output_mode_get(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_get_pd_output(&dac_hdl);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_mode_set
* Description : 设置当前硬件输出模式
* Return : 0 success, other fail
********************* -HB ******************************/
int app_audio_output_mode_set(u8 output)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_set_pd_output(&dac_hdl, output);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_channel_get
* Description : 获取音频输出设备输出通道数
* Return : 通道数
********************* -HB ******************************/
int app_audio_output_channel_get(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_get_channel(&dac_hdl);
#endif
#if AUDIO_OUTPUT_INCLUDE_IIS
return 2;
#endif
}
/*******************************************************
* Function name : app_audio_output_channel_set
* Description : 设置音频输出设备输出通道数
* Parameter :
* @channel 通道数
* Return : 0 success, other fail
********************* -HB ******************************/
int app_audio_output_channel_set(u8 channel)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_set_channel(&dac_hdl, channel);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_write
* Description : 向音频输出设备写入需要输出的音频数据
* Parameter :
* @buf 写入音频数据的起始地址
* @len 写入音频数据的长度
* Return : 成功写入的长度
********************* -HB ******************************/
int app_audio_output_write(void *buf, int len)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_write(&default_dac, buf, len);
#elif AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM
return fm_emitter_cbuf_write(buf, len);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_start
* Description : 音频输出设备输出打开
* Return : 0 success, other fail
********************* -HB ******************************/
int app_audio_output_start(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
audio_dac_start(&dac_hdl);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_stop
* Description : 音频输出设备输出停止
* Return : 0 success, other fail
********************* -HB ******************************/
int app_audio_output_stop(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
audio_dac_channel_stop(&default_dac);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_reset
* Description : 音频输出设备重启
* Parameter :
* @msecs 重启时间 ms
* Return : 0 success, other fail
********************* -HB ******************************/
int app_audio_output_reset(u32 msecs)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_sound_reset(&dac_hdl, msecs);
#endif
return 0;
}
/*******************************************************
* Function name : app_audio_output_get_cur_buf_points
* Description : 获取当前音频输出buf还可以输出的点数
* Parameter :
* Return : 还可以输出的点数
********************* -HB ******************************/
int app_audio_output_get_cur_buf_points(void)
{
return 0;
}
int app_audio_output_ch_analog_gain_set(u8 ch, u8 again)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_ch_analog_gain_set(&dac_hdl, ch, again);
#endif
return 0;
}
int app_audio_output_ch_digital_gain_set(u8 ch, u32 dgain)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_ch_digital_gain_set(&dac_hdl, ch, dgain);
#endif
return 0;
}
int app_audio_output_state_get(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_get_status(&dac_hdl);
#endif
return 0;
}
void app_audio_output_ch_mute(u8 ch, u8 mute)
{
audio_dac_ch_mute(&dac_hdl, ch, mute);
}
int audio_output_buf_time(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_data_time(&dac_hdl);
#endif
return 0;
}
int audio_output_dev_is_working(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
return audio_dac_is_working(&dac_hdl);
#endif
return 1;
}
int audio_output_sync_start(void)
{
return 0;
}
int audio_output_sync_stop(void)
{
return 0;
}
#endif