1.14. DAC
DAC接口包括该模块的初始化,关闭,模拟部分的开关,音量的控制等,相关接口可通过结构体dac_driver进行调用。该系列DAC支持16bit精度,单声道(单端)。
1.14.1. DAC接口
static const struct dac_driver dac_drv_ins = {
.open = __dac_open, //初始化DAC
.close = __dac_close, //关闭DAC
.analog_open = __dac_analog_open, //打开DAC的模拟部分
.analog_close = __dac_analog_close, //关闭DAC的模拟部分
.ioctrl = __dac_ioctl, //音量、采样率、中断配置接口
.vol_ctrl = __digital_vol_ctrl, //音量控制接口
};
const struct dac_driver *dac_drv = &dac_drv_ins;
1.14.2. DAC初始化
1.14.2.1. 传入参数
typedef struct _DAC_INF {
u32 def_sr; //DAC 普通模式采样率(8K,11.025K,12K,16K,22.05K,24K,32K,44.1K,48K,64K,88.2K,96K)
dac_func dac_input; //DAC中断回调
void *priv; //传入中断回调的私有参数
u8 dac_mode; //DAC模式(0:普通,1:2M, 2M模式下输入的音频不能超过-6dB)
u8 fs_2M_sr; //DAC 2M模式采样率参数(fs_2M_sr = 12M / dac_sr - 1,96k < dac_sr < 2 M)
u8 dcc_en; //直流滤波器使能
} DAC_INF;
1.14.2.2. 使用方法
#include "dac_api.h"
dac_input(void *priv, void *dac_buf, u32 len){
//*dac_buf:可写入的首地址
//len:可写入数据长度(字节数);
printf("dac_sr:%d\n", *priv);
}
int dac_sr = 48000;
DAC_INF info = {
.priv = (void *)&dac_sr,
.def_sr = dac_sr,
.dac_input = (dac_func)dac_input,
.dac_mode = (dac_sr > 96000L) ? 1 : 0,
.fs_2M_sr = 12000000L / dac_sr - 1,
.dcc_en = 1,
};
dac_drv->open(&info);
1.14.3. DAC关闭
关闭dac的数字部分和模拟部分
1.14.3.1. 使用方法
dac_drv->close(void);
1.14.4. dac打开模拟部分
该接口只会打开dac的模拟部分,不会对dac的数字部分进行操作。可配合dac_drv->analog_close()使用
1.14.4.1. 使用方法
dac_drv->analog_open(void);
1.14.5. dac关闭模拟部分
该接口只会关闭dac的模拟部分,不会对dac的数字部分进行操作。可配合dac_drv->analog_open()使用,减少不需要播放信号时的功耗。
1.14.5.1. 使用方法
dac_drv->analog_close(void);
1.14.6. dac音量、采样率、中断配置接口
该接口通过传入的命令和参数判断需要执行的功能(音量的初始化、采样率设置/获取、中断的开关)
1.14.6.1. 传入参数
enum { //传入参数 功能解释
DAC_REG_VOL_TAB,//u16 * 注册音量表
DAC_GET_MAX_VOL,//u8 * 获取最大音量
DAC_SET_MAX_VOL,//u8 * 设置最大音量
DAC_GET_CUR_VOL,//u8 * 获取当前音量
DAC_SET_CUR_VOL,//u8 * 设置当前音量
DAC_CLR_DMA_BUF,//NULL 清除DMABUF数据
DAC_SET_SR, //u16 * 设置采样率
DAC_GET_SR, //u16 * 获取采样率
DAC_IE_CTL, //u8 * 控制IE
};
1.14.6.2. 使用方法
#define MAX_SYS_VOL (31) //最大音量等级
#define DEFUAL_SYS_VOL (MAX_SYS_VOL) //系统默认音量
#define DAC_DEFAULT_SR (32000) //dac初始化的采样率
const u16 digital_vol_tab[MAX_SYS_VOL + 1] = {
0, 93, 111, 132, 158, 189, 226, 270, 323, 386, //9
462, 552, 660, 789, 943, 1127, 1347, 1610, 1925, 2301, //19
2751, 3288, 3930, 4698, 5616, 6713, 8025, 9592, 11466, 15200, //29
16000, 16384 //31
};
u8 vol = DEFUAL_SYS_VOL;
dac_drv->ioctrl((void *)&vol, DAC_SET_MAX_VOL); //设置最大音量
dac_drv->ioctrl((void *)&vol, DAC_SET_CUR_VOL); //设置当前音量
dac_drv->ioctrl((void *)digital_vol_tab, DAC_REG_VOL_TAB); //注册音量表
u16 def_sr = DAC_DEFAULT_SR;
u16 cur_sr = 0;
dac_drv->ioctrl((void *)&def_sr, DAC_SET_SR); //设置采样率(只适用于DAC普通模式)
dac_drv->ioctrl((void *)&cur_sr, DAC_GET_SR); //获取当前音量到cur_sr中(只适用于DAC普通模式)
dac_drv->ioctrl((void *)NULL, DAC_CLR_DMA_BUF); //清除DMABUF数据
u8 ie_en = 0;
dac_drv->ioctrl((void *)&ie_en, DAC_IE_CTL); //通过ie_en控制中断
1.14.7. dac音量控制接口
通过ioctrl完成音量表、最大音量和当前音量的设置后,将需要播放的数据传入该接口,便能实现音量控制。
1.14.7.1. 使用方法
dac_drv->vol_ctrl(dac_buf, buf_len);
1.14.8. dac使用案例
#define DAC_MAX_SYS_VOL (31) //最大音量等级
#define DAC_DEFUAL_SYS_VOL (DAC_MAX_SYS_VOL) //系统默认音量
const u16 dac_demo_digital_vol_tab[DAC_MAX_SYS_VOL + 1] = {
0, 93, 111, 132, 158, 189, 226, 270, 323, 386, //9
462, 552, 660, 789, 943, 1127, 1347, 1610, 1925, 2301, //19
2751, 3288, 3930, 4698, 5616, 6713, 8025, 9592, 11466, 15200, //29
16000, 16384 //31
};
u16 dac_cnt = 0;
extern int get_sine_data(u16 *s_cnt, s16 *data, u16 points, u8 ch);//数据替换
static void dac_input(void *priv, void *data, u32 len)
{
get_sine_data(&dac_cnt, data, len / 2, 1);//将数据替换为44.1K采样率的1k正弦波用于测试。
dac_drv->vol_ctrl(data, len);
}
void dac_test_demo()
{
u8 vol = DAC_DEFUAL_SYS_VOL;
dac_drv->ioctrl((void *)&vol, DAC_SET_MAX_VOL); //设置最大音量
dac_drv->ioctrl((void *)&vol, DAC_SET_CUR_VOL); //设置当前音量
dac_drv->ioctrl((void *)dac_demo_digital_vol_tab, DAC_REG_VOL_TAB); //注册音量表
int dac_sr = 44100;
DAC_INF dac_inf = {
.priv = (void *) &dac_sr,
.def_sr = dac_sr,
.dac_input = (dac_func)dac_input,
.dac_mode = (dac_sr > 96000L) ? 1 : 0,
.fs_2M_sr = 12000000L / dac_sr - 1,
.dcc_en = 1,
};
//电源配置
hadc_avddcp_config(1, AVDDCP_MODE_SEL_NORMAL, AVDDCP_VOL_SEL_3P60);
hadc_avddr_config(1, AVDDR_VOL_SEL_3P0);
hadc_avbg_config(1, 0, 1);
hadc_avcm_config(1, 1);
hadc_pa_config(1, 1, HADC_PA_MUXP_SEL_AVBG, HADC_PA_MUXN_DACO_BIAS, HADC_PA_GAIN_SEL_M0db);
dac_drv->open(&dac_inf);
u8 ie_en = 1;
dac_drv->ioctrl((void *)&ie_en, DAC_IE_CTL); //使能DAC中断
while (1) {
wdt_clear();
mdelay(5);
}
}