Files
99_7018_lmx/cpu/br28/audio_demo/audio_adc_demo.c
2025-10-29 13:10:02 +08:00

448 lines
15 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.

/*
****************************************************************************
* 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*/