Files
99_7018_lmx/cpu/br28/audio_demo/audio_adc_demo.c

448 lines
15 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
/*
****************************************************************************
* Audio ADC Demo
*
*Description : Audio ADC使用范例
*Notes : (1)demo为开发测试范例demo
*
* (2)mic工作模式说明
* A.(cap_mode)
* mic供电方式(mic_bias_inside = 1)
* B.(capless_mode)
* C.(cap_diff_mode)
****************************************************************************
*/
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "app_main.h"
#include "audio_config.h"
#include "audio_demo.h"
#include "asm/audio_adc.h"
#if 1
#define ADC_DEMO_LOG printf
#else
#define ADC_DEMO_LOG(...)
#endif
extern struct audio_dac_hdl dac_hdl;
extern struct audio_adc_hdl adc_hdl;
#define ADC_DEMO_CH_NUM 4 /*支持的最大采样通道(max = 2)*/
#define ADC_DEMO_BUF_NUM 2 /*采样buf数*/
#define ADC_DEMO_IRQ_POINTS 256 /*采样中断点数*/
#define ADC_DEMO_BUFS_SIZE (ADC_DEMO_CH_NUM * ADC_DEMO_BUF_NUM * ADC_DEMO_IRQ_POINTS)
struct adc_demo {
u8 adc_2_dac;
u8 mic_idx;
u8 linein_idx;
struct audio_adc_output_hdl adc_output;
struct adc_mic_ch mic_ch;
struct adc_linein_ch linein_ch;
s16 adc_buf[ADC_DEMO_BUFS_SIZE];
u8 linein_ch_num;
u8 linein_ch_sel;
};
static struct adc_demo *mic_demo = NULL;
static struct adc_demo *linein_demo = NULL;
/* 选择输出哪路 linein采样的数据,可通过按键调用此函数实现每按一下按键切一下输出的linein通路 */
void linein_output_channel_sel()
{
if (linein_demo) {
linein_demo->linein_ch_sel += 1;
if (linein_demo->linein_ch_sel > linein_demo->linein_ch_num - 1) {
linein_demo->linein_ch_sel = 0;
}
}
}
/*
*********************************************************************
* AUDIO MIC OUTPUT
* Description: mic采样数据回调
* Arguments : pric
* data mic数据
* len
* Return : 0
* Note(s) :
* L0 L1 L2 L3 L4 ...
* ()
* L0 R0 L1 R1 L2 R2...
*********************************************************************
*/
#define ADC_DEBUG_BUF (0)
#define ADC_DEBUF_SIZE (32000)
#if ADC_DEBUG_BUF
u32 d_skip_cnt = 100;
s16 d_buf[ADC_DEBUF_SIZE / 2] = {0};
u8 *d_ptr = d_buf;
u32 d_buf_cnt = 0;
#endif
static void adc_mic_demo_output(void *priv, s16 *data, int len)
{
//printf("> %d %d %d %d\n", data[0], data[1], data[2], data[3]);
int wlen = 0;
if (mic_demo && mic_demo->adc_2_dac) {
if (mic_demo->mic_idx == (AUDIO_ADC_MIC_0 | AUDIO_ADC_MIC_1)) {
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
/*输出两个mic的数据到DAC两个通道*/
putchar('a');
wlen = audio_dac_write(&dac_hdl, data, len * 2);
#else
/*输出其中一个mic的数据到DAC一个通道*/
putchar('b');
s16 *mono_data = data;
for (int i = 0; i < (len / 2); i++) {
mono_data[i] = data[i * 2]; /*MIC_L*/
//mono_data[i] = data[i * 2 + 1]; /*MIC_R*/
}
wlen = audio_dac_write(&dac_hdl, mono_data, len);
#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/
} else {
/*输出一个mic的数据到DAC一个通道*/
putchar('c');
wlen = audio_dac_write(&dac_hdl, data, len);
}
}
#if ADC_DEBUG_BUF
wdt_close();
if (d_skip_cnt) {
d_skip_cnt--;
return;
}
d_buf_cnt += len * ADC_DEMO_CH_NUM;
if (d_buf_cnt >= ADC_DEBUF_SIZE) {
wdt_close();
local_irq_disable();
printf(">>> hex\n\n");
put_buf(d_buf, ADC_DEBUF_SIZE);
printf(">>> hex end\n\n");
u32 i;
for (i = 0; i < ADC_DEBUF_SIZE / 2; i++) {
/* printf("%d\n", d_buf[i]); */
}
printf(">>> printf end\n\n");
while (1);
}
memcpy(d_ptr, data, len * ADC_DEMO_CH_NUM);
d_ptr += len * ADC_DEMO_CH_NUM;
#endif
}
/*
*********************************************************************
* AUDIO Linein OUTPUT
* Description: linein采样数据回调
* Arguments : pric
* data mic数据
* len
* Return : 0
* Note(s) :
* L0 L1 L2 L3 L4 ...
* ()
* L0 R0 L1 R1 L2 R2...
*********************************************************************
*/
#define LINEIN_DEBUG_BUF (0)
#define LINEIN_DEBUF_SIZE (32000)
#if LINEIN_DEBUG_BUF
u32 l_skip_cnt = 100;
s16 l_buf[LINEIN_DEBUF_SIZE / 2] = {0};
u8 *l_ptr = l_buf;
u32 l_buf_cnt = 0;
#endif
static void adc_linein_demo_output(void *priv, s16 *data, int len)
{
/* printf("> %d %d %d %d\n", data[0], data[1], data[2], data[3]); */
int wlen = 0;
if (linein_demo && linein_demo->adc_2_dac) {
if (linein_demo->linein_ch_num >= 2) {
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
/*输出两个linein的数据到DAC两个通道,默认输出第一个和第二个采样通道的数据*/
putchar('a');
s16 temp[len * 2];
for (int i = 0; i < len / 2; i++) {
temp[2 * i] = data[linein_demo->linein_ch_num * i];
temp[2 * i + 1] = data[linein_demo->linein_ch_num * i + 1];
}
wlen = audio_dac_write(&dac_hdl, temp, len * 2);
#else
/*输出其中一个linein的数据到DAC一个通道*/
putchar('b');
s16 *mono_data = data;
for (int i = 0; i < (len / 2); i++) {
switch (linein_demo->linein_ch_sel) {
case 0:
mono_data[i] = data[i * linein_demo->linein_ch_num]; /*第一路 linein采样的数据*/
break;
case 1:
mono_data[i] = data[i * linein_demo->linein_ch_num + 1]; /*第一路 linein采样的数据*/
break;
case 2:
mono_data[i] = data[i * linein_demo->linein_ch_num + 2]; /*第三路 linein采样的数据*/
break;
case 3:
mono_data[i] = data[i * linein_demo->linein_ch_num + 3]; /*第四路 linein采样的数据*/
break;
default:
break;
}
}
wlen = audio_dac_write(&dac_hdl, mono_data, len);
#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/
} else {
/*输出一个linein的数据到DAC一个通道*/
putchar('c');
wlen = audio_dac_write(&dac_hdl, data, len);
}
}
#if LINEIN_DEBUG_BUF
wdt_close();
if (l_skip_cnt) {
l_skip_cnt--;
return;
}
l_buf_cnt += len * ADC_DEMO_CH_NUM;
if (l_buf_cnt >= LINEIN_DEBUF_SIZE) {
wdt_close();
local_irq_disable();
printf(">>> hex\n\n");
put_buf(l_buf, LINEIN_DEBUF_SIZE);
printf(">>> hex end\n\n");
u32 i;
for (i = 0; i < LINEIN_DEBUF_SIZE / 2; i++) {
/* printf("%d\n", l_buf[i]); */
}
printf(">>> printf end\n\n");
while (1);
}
memcpy(l_ptr, data, len * ADC_DEMO_CH_NUM);
l_ptr += len * ADC_DEMO_CH_NUM;
#endif
}
/*
*********************************************************************
* AUDIO ADC MIC OPEN
* Description: mic通道
* Arguments : mic_idx mic通道
* gain mic增益
* sr mic采样率
* mic_2_dac mic数据DAC
* Return : None.
* Note(s) : (1)mic通道示例
* audio_adc_mic_demo_open(AUDIO_ADC_MIC_0,10,16000,1);
*
* audio_adc_mic_demo_open(AUDIO_ADC_MIC_1,10,16000,1);
* (2)mic通道示例
* audio_adc_mic_demo_open(AUDIO_ADC_MIC_1|AUDIO_ADC_MIC_0,10,16000,1);
*********************************************************************
*/
void audio_adc_mic_demo_open(u8 mic_idx, u8 gain, u16 sr, u8 mic_2_dac)
{
ADC_DEMO_LOG("audio_adc_mic_demo open:%d,gain:%d,sr:%d,mic_2_dac:%d\n", mic_idx, gain, sr, mic_2_dac);
mic_demo = zalloc(sizeof(struct adc_demo));
if (mic_demo) {
//step0:打开mic通道并设置增益
audio_adc_mic_open(&mic_demo->mic_ch, AUDIO_ADC_MIC_0, &adc_hdl);
audio_adc_mic_set_gain(&mic_demo->mic_ch, gain);
audio_adc_mic_0dB_en(1);
//step1:设置mic通道采样率
audio_adc_mic_set_sample_rate(&mic_demo->mic_ch, sr);
//step2:设置mic采样buf
audio_adc_mic_set_buffs(&mic_demo->mic_ch, mic_demo->adc_buf, ADC_DEMO_IRQ_POINTS * 2, ADC_DEMO_BUF_NUM);
//step3:设置mic采样输出回调函数
mic_demo->adc_output.handler = adc_mic_demo_output;
audio_adc_add_output_handler(&adc_hdl, &mic_demo->adc_output);
//step4:启动mic通道采样
audio_adc_mic_start(&mic_demo->mic_ch);
/*监听配置(可选)*/
mic_demo->adc_2_dac = mic_2_dac;
mic_demo->mic_idx = mic_idx;
if (mic_2_dac) {
ADC_DEMO_LOG("max_sys_vol:%d\n", get_max_sys_vol());
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
ADC_DEMO_LOG("cur_vol:%d\n", app_audio_get_volume(APP_AUDIO_STATE_MUSIC));
audio_dac_set_volume(&dac_hdl, app_audio_get_volume(APP_AUDIO_STATE_MUSIC));
audio_dac_set_sample_rate(&dac_hdl, sr);
audio_dac_start(&dac_hdl);
}
}
ADC_DEMO_LOG("audio_adc_mic_demo start succ\n");
int res = 0;
int msg[16];
// 循环一直往dac写数据
#ifdef BT_DUT_ADC_INTERFERE
while (0) {
#else
while (1) {
#endif/*BT_DUT_ADC_INTERFERE*/
// 这句是为了防止线程太久没有响应系统而产生异常,实际使用不需要
res = os_taskq_accept(ARRAY_SIZE(msg), msg);
os_time_dly(500);
}
}
/*
*********************************************************************
* AUDIO ADC MIC CLOSE
* Description: mic采样模块
* Arguments : None.
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_adc_mic_demo_close(void)
{
ADC_DEMO_LOG("audio_adc_mic_demo_close\n");
if (mic_demo) {
audio_adc_del_output_handler(&adc_hdl, &mic_demo->adc_output);
audio_adc_mic_close(&mic_demo->mic_ch);
free(mic_demo);
mic_demo = NULL;
}
}
/*
*********************************************************************
* AUDIO ADC linein OPEN
* Description: linein通道
* Arguments : linein_idx linein通道
* gain linein增益
* sr linein采样率
* linein_2_dac linein数据DAC
* Return : None.
* Note(s) : (1)linein通道示例
* audio_adc_linein_demo_open(AUDIO_ADC_LINE0,10,16000,1);
*
* audio_adc_linein_demo_open(AUDIO_ADC_LINE1,10,16000,1);
* (2)linein通道示例
* audio_adc_linein_demo_open(AUDIO_ADC_LINE1|AUDIO_ADC_LINE0,10,16000,1);
* (3)linein通道示例
* audio_adc_linein_demo_open(AUDIO_ADC_LINE3|AUDIO_ADC_LINE2|AUDIO_ADC_LINE1|AUDIO_ADC_LINE0,10,16000,1);
*********************************************************************
*/
void audio_adc_linein_demo_open(u8 linein_idx, u8 gain, u16 sr, u8 linein_2_dac)
{
ADC_DEMO_LOG("audio_adc_linein_demo open:%d,gain:%d,sr:%d,linein_2_dac:%d\n", linein_idx, gain, sr, linein_2_dac);
linein_demo = zalloc(sizeof(struct adc_demo));
if (linein_demo) {
//step0:打开linein通道并设置增益
if (linein_idx & AUDIO_ADC_LINE0) {
audio_adc_linein_open(&linein_demo->linein_ch, AUDIO_ADC_LINE0, &adc_hdl);
audio_adc_linein_set_gain(&linein_demo->linein_ch, gain);
audio_adc_linein_0dB_en(1);
linein_demo->linein_ch_num += 1;
}
if (linein_idx & AUDIO_ADC_LINE1) {
audio_adc_linein1_open(&linein_demo->linein_ch, AUDIO_ADC_LINE1, &adc_hdl);
audio_adc_linein1_set_gain(&linein_demo->linein_ch, gain);
audio_adc_linein1_0dB_en(1);
linein_demo->linein_ch_num += 1;
}
if (linein_idx & AUDIO_ADC_LINE2) {
audio_adc_linein2_open(&linein_demo->linein_ch, AUDIO_ADC_LINE2, &adc_hdl);
audio_adc_linein2_set_gain(&linein_demo->linein_ch, gain);
audio_adc_linein2_0dB_en(1);
linein_demo->linein_ch_num += 1;
}
if (linein_idx & AUDIO_ADC_LINE3) {
audio_adc_linein3_open(&linein_demo->linein_ch, AUDIO_ADC_LINE3, &adc_hdl);
audio_adc_linein3_set_gain(&linein_demo->linein_ch, gain);
audio_adc_linein3_0dB_en(1);
linein_demo->linein_ch_num += 1;
}
//step1:设置linein通道采样率
audio_adc_linein_set_sample_rate(&linein_demo->linein_ch, sr);
//step2:设置linein采样buf
audio_adc_linein_set_buffs(&linein_demo->linein_ch, linein_demo->adc_buf, ADC_DEMO_IRQ_POINTS * 2, ADC_DEMO_BUF_NUM);
//step3:设置linein采样输出回调函数
linein_demo->adc_output.handler = adc_linein_demo_output;
audio_adc_add_output_handler(&adc_hdl, &linein_demo->adc_output);
//step4:启动linein通道采样
audio_adc_linein_start(&linein_demo->linein_ch);
/*监听配置(可选)*/
linein_demo->adc_2_dac = linein_2_dac;
linein_demo->linein_idx = linein_idx;
if (linein_2_dac) {
ADC_DEMO_LOG("max_sys_vol:%d\n", get_max_sys_vol());
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
ADC_DEMO_LOG("cur_vol:%d\n", app_audio_get_volume(APP_AUDIO_STATE_MUSIC));
audio_dac_set_volume(&dac_hdl, app_audio_get_volume(APP_AUDIO_STATE_MUSIC));
audio_dac_set_sample_rate(&dac_hdl, sr);
audio_dac_start(&dac_hdl);
}
}
ADC_DEMO_LOG("audio_adc_linein_demo start succ\n");
int res = 0;
int msg[16];
// 循环一直往dac写数据
while (1) {
// 这句是为了防止线程太久没有响应系统而产生异常,实际使用不需要
res = os_taskq_accept(ARRAY_SIZE(msg), msg);
os_time_dly(500);
}
}
/*
*********************************************************************
* AUDIO ADC linein CLOSE
* Description: linein采样模块
* Arguments : None.
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_adc_linein_demo_close(void)
{
ADC_DEMO_LOG("audio_adc_linein_demo_close\n");
if (linein_demo) {
audio_adc_del_output_handler(&adc_hdl, &linein_demo->adc_output);
audio_adc_linein_close(&linein_demo->linein_ch);
free(linein_demo);
linein_demo = NULL;
}
}
//开启audio_adc接口 用于测试BT干扰
void audio_adc_mic_dut_open(void)
{
audio_adc_mic_demo_open(AUDIO_ADC_MIC_0, 10, 16000, 0);
}
#if AUDIO_DEMO_LP_REG_ENABLE
static u8 adc_demo_idle_query()
{
return mic_demo ? 0 : 1;
}
REGISTER_LP_TARGET(adc_demo_lp_target) = {
.name = "adc_demo",
.is_idle = adc_demo_idle_query,
};
#endif/*AUDIO_DEMO_LP_REG_ENABLE*/