Files

353 lines
11 KiB
C

/*
****************************************************************
* Hearing Aid Low Power
* 检测数据能量的函数
* File : audi_hearing_aid_lp.c
* By :
* Notes :
****************************************************************
*/
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "app_main.h"
#include "audio_config.h"
#include "app_action.h"
#include "audio_hearing_aid_lp.h"
extern struct audio_dac_hdl dac_hdl;
extern struct audio_adc_hdl adc_hdl;
#ifndef TCFG_AUDIO_DHA_MIC_SAMPLE_RATE
#define TCFG_AUDIO_DHA_MIC_SAMPLE_RATE 32000
#endif
//*********************************************************************************//
// mic能量检测处理配置 //
//*********************************************************************************//
//是否开启mic 能量检测
#define MIC_ENERGY_DETECT 1
//判断多少ms没有能量就进入低功耗
#define MIC_SNIFF_TIME 2 * 60 * 1000
//#define MIC_SNIFF_TIME 5 * 1000
//进入低功耗后每隔多少ms计算一次能量
#define MIC_CHECK_INTER 1 * 1000
//低功耗状态下能量检测计算多少ms的能量
#define MIC_ENERGY_TIME 20
//进入低功耗的能量值,小于此能量值进入低功耗
#define enter_sniff_energy 50
//退出低功耗的能量值,大于退出低功耗 //从低功耗出来时adc 能量值会比较高,需要比较高的阈值
#define exit_sniff_energy 170
//跳过刚上电的多少次中断数据
#define adc_isr_ignore_cnt 8
//是否打开mic 能量的调试打印
#define ENERGY_DEBUG_EN 0
static u8 enter_sleep = 0;
#if ENERGY_DEBUG_EN
static u32 debug_size = 4096 * 2;
/* static s16 debug_buf[4096 * 2]; */
static u32 debug_p = 0;
static u32 zero_cnt = 0;
static u32 no_zero_cnt = 0;
static u8 debug_flag = 0;
#endif
struct hearing_aid_energy_detect {
u32 exit_sniff_points; //一次检测的点数
u32 abs_total_0; //mic0 的能量
u32 abs_total_1; //mic1 的能量
u32 points_count; //点数
u32 energy_detect_flag;//是否开始计算能量的标志
u32 enter_sniff_points; //多少个点的能量低于阈值进低功耗
u32 exit_sniff_timer; //检测能量值定时器
u16 dac_start_timer; //检测能量值定时器
u16 dac_stop_timer; //检测能量值定时器
u8 dac_start_flag; //dac 开启或关闭的标志位
u8 isr_ignore_cnt; //跳过刚上电的多少次中断数据
u8 adc_ch_num; //打开多少个mic通道
struct adc_mic_ch mic_ch;
s16 *adc_dma_buf;
struct audio_adc_output_hdl adc_output;
u8 dac_open;
void (*hw_open)(void);
void (*hw_close)(void);
};
static struct hearing_aid_energy_detect *mic_aid = NULL;
void exit_sniff_start(void) //定时能量检测,能量检测的时候mic能不能正常工作
{
#if ENERGY_DEBUG_EN
printf("enter low_power_deal.c %d\n", __LINE__);
#endif
mic_aid->energy_detect_flag = 1; //开始能量计算
mic_aid->isr_ignore_cnt = adc_isr_ignore_cnt;
#if 1 //重新打开mic
extern void hearing_aid_energy_demo_open(u8 mic_idx, u8 gain, u16 sr, u8 mic_2_dac);
hearing_aid_energy_demo_open(TCFG_AD2DA_LOW_LATENCY_MIC_CHANNEL, 12, TCFG_AUDIO_DHA_MIC_SAMPLE_RATE, 0);
/* audio_adc_mic_aid_open(mic_aid->mic_idx, mic_aid->gain, mic_aid->sr, 0); */
#else
SFR(JL_ADDA->DAA_CON0, 16, 1, 1); // VBG_EN_11v
SFR(JL_ADDA->ADA_CON0, 17, 1, 0); // CTADCA_S2_RSTB
os_time_dly(50);
SFR(JL_ADDA->ADA_CON0, 17, 1, 1); // CTADCA_S2_RSTB
SFR(JL_ADDA->DAA_CON0, 12, 1, 1); //AUDIO_IBIAS_EN_11V
#endif
enter_sleep = 0; //退出低功耗
sys_timer_del(mic_aid->exit_sniff_timer);
}
void dac_start_timer(void) //启动dac
{
#if ENERGY_DEBUG_EN
printf("enter low_power_deal.c%d\n", __LINE__);
#endif
extern void hearing_aid_energy_demo_close(void);
hearing_aid_energy_demo_close();
printf("enter low_power_deal.c%d\n", __LINE__);
if (mic_aid->hw_open) {
mic_aid->hw_open();
}
/* sound_pcm_dev_start(NULL, 16000, 10); */
enter_sleep = 0; //退出低功耗
/* mic_aid->adc_2_dac = 1; */
mic_aid->dac_start_flag = 1 ;
sys_timer_del(mic_aid->dac_start_timer);
}
void dac_stop_timer(void) //关闭dac
{
#if ENERGY_DEBUG_EN
printf("enter low_power_deal.c%d\n", __LINE__);
#endif
extern void hearing_aid_energy_demo_close(void);
hearing_aid_energy_demo_close();
if (mic_aid->hw_close) {
printf("enter low_power_deal.c%d,%p\n", __LINE__, mic_aid->hw_close);
mic_aid->hw_close();
}
/* audio_adc_del_output_handler(&adc_hdl, &mic_aid->adc_output); */
/* audio_adc_mic_close(&mic_aid->mic_ch); */
mic_aid->adc_ch_num = 0; //mic_aid 被关了
//将变量清0,开始新一轮计算
mic_aid->abs_total_0 = 0;
mic_aid->abs_total_1 = 0;
mic_aid->points_count = 0;
mic_aid->energy_detect_flag = 0;
enter_sleep = 1; //进入低功耗
/* mic_aid->adc_2_dac = 0; */
mic_aid->dac_start_flag = 0 ;
sys_timer_del(mic_aid->dac_stop_timer);
printf("enter low_power_deal.c%d\n", __LINE__);
}
void audio_hearing_aid_lp_open(u8 ch_num, void (*hw_open)(void), void (*hw_close)(void)) //对多少个通道做数据处理
{
if (!mic_aid) {
printf("enter low_power_deal.c%d\n", __LINE__);
mic_aid = zalloc(sizeof(struct hearing_aid_energy_detect));
}
#if 0
else {
/* memset(mic_aid,0,sizeof(struct hearing_aid_energy_detect)); */
}
#endif
mic_aid->exit_sniff_points = MIC_ENERGY_TIME * (TCFG_AUDIO_DHA_MIC_SAMPLE_RATE / 1000); //进入低功耗后一次检测的点数
mic_aid->enter_sniff_points = MIC_SNIFF_TIME * (TCFG_AUDIO_DHA_MIC_SAMPLE_RATE / 1000); //多少个点的能量低于阈值进低功耗
mic_aid->adc_ch_num = ch_num;
mic_aid-> hw_open = hw_open; //正常工作打开硬件的函数(关mic,关dac)
mic_aid-> hw_close = hw_close; //进入低功耗关硬件的函数(开mic,开dac)
mic_aid->abs_total_0 = 0;
mic_aid->abs_total_1 = 0;
mic_aid->points_count = 0;
enter_sleep = 0;
}
void audio_hearing_aid_lp_close(void)
{
if (mic_aid) {
free(mic_aid);
mic_aid = NULL;
}
}
u8 audio_hearing_aid_lp_flag(void)
{
return enter_sleep;
}
void audio_hearing_aid_lp_detect(void *priv, s16 *data, int len)
{
#if MIC_ENERGY_DETECT
u32 points = len / 2;
s16 *pdata = data;
u32 i = 0;
s32 total_0 = 0;
s32 total_1 = 0;
s16 diff = 0;
u32 target_points = 0;
u32 target_energy = 0;
if (enter_sleep == 0) { //低功耗期间也会进中断,不能计算能量值
if (mic_aid->isr_ignore_cnt > 0) {
mic_aid->isr_ignore_cnt--;
return;
} //跳过刚开始的一次中断数据
for (i = 0; i < points; i++) {
total_0 += *pdata;
pdata++;
if (mic_aid->adc_ch_num == 2) {
total_1 += *pdata;
pdata++;
}
}
total_0 /= (len / 2 / mic_aid->adc_ch_num); //直流量
total_1 /= (len / 2 / mic_aid->adc_ch_num);
// printf(">> total_0 %d total_1 %d\n", total_0, total_1);
pdata = data;
if (mic_aid->energy_detect_flag) { //由定时器启动的能量计算
target_points = mic_aid->exit_sniff_points; //多少时间检测
target_energy = exit_sniff_energy;
} else {
target_points = mic_aid-> enter_sniff_points; //正常工作检测多久
target_energy = enter_sniff_energy;
}
for (i = 0; i < points; i++) {
#if ENERGY_DEBUG_EN
#if 0
if (debug_p < debug_size) {
debug_buf[debug_p++] = *pdata ;
if (*pdata == 0) {
zero_cnt++;
} else {
no_zero_cnt++;
}
}
#endif
#endif
diff = *pdata - total_0;
if (diff > 0) {
mic_aid->abs_total_0 += diff;
} else {
mic_aid->abs_total_0 -= diff;
}
pdata++;
if (mic_aid->adc_ch_num == 2) {
diff = *pdata - total_1;
if (diff > 0) {
mic_aid->abs_total_1 += diff;
} else {
mic_aid->abs_total_1 -= diff;
}
pdata++;
}
mic_aid -> points_count++;
#if ENERGY_DEBUG_EN
/* printf("enter audio_adc_aid.c@@@@@@@@@@@@@@@@@@@@@@@@@@%d,%d,%d,%d\n",__LINE__,target_points,enter_sleep,mic_aid->points_count); */
#endif
if (mic_aid->points_count == target_points) {
#if ENERGY_DEBUG_EN
printf("enter low_power_deal.c %d,%d,%d,%d,%d\n", __LINE__, mic_aid->abs_total_0, mic_aid->abs_total_1, mic_aid->points_count, target_points);
#endif
mic_aid->abs_total_0 /= target_points;
mic_aid->abs_total_1 /= target_points;
#if ENERGY_DEBUG_EN
printf("enter low_power_deal.c %d,%d,%d,%d\n", __LINE__, mic_aid->abs_total_0, mic_aid->abs_total_1, target_energy);
#endif
#if ENERGY_DEBUG_EN
extern void audio_adda_dump(void); //打印所有的dac,adc寄存器
extern void audio_gain_dump();
audio_adda_dump();
audio_gain_dump();
#endif
if ((mic_aid->abs_total_0 < target_energy) && (mic_aid->abs_total_1 < target_energy)) { //
mic_aid->dac_stop_timer = sys_timer_add(NULL, dac_stop_timer, 1);
mic_aid->exit_sniff_timer = sys_timer_add(NULL, exit_sniff_start, MIC_CHECK_INTER); //退出低功耗计算能量值
#if ENERGY_DEBUG_EN
debug_p = 0;
zero_cnt = no_zero_cnt = 0;
/* memset(debug_buf, 0, debug_size * 2); */
printf("enter low_power_deal.c %d,%d,%d\n", __LINE__, mic_aid->abs_total_0, mic_aid->abs_total_1);
#endif
break;
} else {
//将变量清0,开始新一轮计算
mic_aid->abs_total_0 = 0;
mic_aid->abs_total_1 = 0;
mic_aid->points_count = 0;
mic_aid->energy_detect_flag = 0;
enter_sleep = 0;
#if ENERGY_DEBUG_EN
debug_p = 0;
/* memset(debug_buf, 0, debug_size * 2); */
zero_cnt = no_zero_cnt = 0;
#endif
if (!audio_dac_is_working(&dac_hdl)) {
mic_aid->dac_start_timer = sys_timer_add(NULL, dac_start_timer, 1);
}
}
} //end of if 点数等于 enter_sniff_points
}//endf of for
} //end of 低功耗期间也会进中断,不能计算能量值
if (mic_aid->dac_open == 0) {
return;
}
#endif
}