CODEC_I2S
简介
CODEC_I2S 模块,用于驱动外接音频芯片,配合 I2S 模块,完成音频的录制,播放等处理。
例如,外接顺芯 ES8374 芯片,再外接麦克风,扬声器,耳机,可以进行声音录制,也可以把音频数据从扬声器和耳机播放出去。
功能列表
Init——初始化 CODEC 驱动。
Deinit——去初始化 CODEC 驱动。
Set format——设置音频数据格式。
Start——启动音频处理。
Stop——停止音频处理。
Set mute——设置输出静音或者非静音。
Set volume——设置输出音量。
Set mic mute——设置输入静音或者非静音。
Set mic volume——设置输入音量。
Set reg——直接写 CODEC 芯片寄存器。
Get reg——直接读 CODEC 芯片寄存器。
功能概述
音频芯片 目前驱动只支持 ES8374 音频芯片,用户需要使用其他芯片可以参照文档对接。
主从设备 目前驱动中一般是 WM80X 芯片为 Master, ES8374 作为 Slave。
传输协议 I2S 和 CODEC 使用标准 I2S 协议传输。
工作模式 支持 IN,OUT, IN + OUT 三种方式:
IN :即麦克风从环境中采集声音数据,经 CODEC 芯片放大转换成数字信号,从 I2S 接口传给 WM80X 芯片处理;
OUT :WM80X 芯片把声音数据从 I2S 接口传递给 CODEC 音频芯片,转换成模拟信号输出到扬声器或者耳机上;
IN + OUT :同时使用录制和播放功能。
采样率 不同 CODEC 芯片能力不一样:
ES8374 : 支持 8K ~ 96K , 32 位立体声只支持 8K ~ 48K。
位深 使用 ES8374 芯片时,支持 16 位和 32 位,其他位数如 8 位,24 位,可以在上层进行重采样处理,example 中有重采样的参考。
声道 支持单声道和立体声。
静音 输入,输出都提供了静音设置接口。
音量 输入,输出都提供了音量设置接口。
寄存器读写 提供了直接读写 CODEC 芯片寄存器的接口。
配置
设备表配置
CODEC_I2S 需要在设备表中配置,根据实际使用的 Board 和芯片,按硬件连线和 CODEC 芯片型号进行配置。
编译配置
模块使用到 I2C, I2S和具体的 CODEC 芯片,所以需要把相关配置打开
CONFIG_COMPONENT_DRIVER_I2C_ENABLED=y
CONFIG_COMPONENT_DRIVER_I2S_ENABLED=y
CONFIG_COMPONENT_DRIVER_CODEC_ES8374_ENABLED=y
CODEC_I2C 地址
WM80X 控制 CODEC 芯片时,使用的是 I2C 协议,CODEC 芯片的 I2C 地址,需要参照手册和硬件连线。I2C 驱动接口使用 7 位地址,不包括读写位,在调用读写接口时,I2C 底层驱动会左移一位再加上读写位。
主要功能
初始化 CODEC_I2S
使用 CODEC_I2S 之前需调用
wm_drv_codec_i2s_init()
函数为CODEC_I2S分配资源,利用wm_device_t
,示例:wm_device_t *codec_i2s_dev = wm_dt_get_device_by_name("es8374"); wm_drv_codec_i2s_init("es8374");第一个参数指定设备名称,名称在设备表中定义,目前只有一个 CODEC_I2S 主设备,只能填 “es8374”
警告
CODEC_I2S 初始化后,如果没有调用
wm_drv_codec_i2s_deinit
, 再次调用wm_drv_codec_i2s_init
会返回NULL
。
去初始化 CODEC_I2S
使用完成 CODEC_I2S 后调用
wm_drv_codec_i2s_deinit()
释放CODEC_I2S分配的资源,示例:wm_drv_codec_i2s_dedeinit(codec_i2s_dev);
设置音频格式
初始化后,调用函数
wm_drv_codec_i2s_set_format
设置音频数据格式wm_drv_codec_i2s_set_format(codec_i2s_dev, 48000, 16, WM_I2S_CHAN_TYPE_STEREO);警告
根据 I2S 协议规范,同时使用 IN 和 OUT 功能,只能使用相同的格式。
开始
调用
wm_drv_codec_i2s_start
开始工作。wm_drv_codec_i2s_start(codec_i2s_dev);
停止
调用
wm_drv_codec_i2s_stop
开始工作。wm_drv_codec_i2s_stop(codec_i2s_dev);
设置输出静音
调用
wm_drv_codec_i2s_set_mute
设置输出静音。wm_drv_codec_i2s_set_mute(codec_i2s_dev);
设置输入静音
调用
wm_drv_codec_i2s_set_mic_mute
设置输入静音。wm_drv_codec_i2s_set_mic_mute(codec_i2s_dev);
设置输出音量
调用
wm_drv_codec_i2s_set_volume
设置输出音量,音量值从 0 ~ 100。wm_drv_codec_i2s_set_volume(codec_i2s_dev,90);
设置输入音量
调用
wm_drv_codec_i2s_set_mic_volume
设置输入音量,音量值从 0 ~ 100。wm_drv_codec_i2s_set_mic_volume(codec_i2s_dev,90);
写 CODEC 寄存器
调用
wm_drv_codec_i2s_set_reg
写 CODEC 寄存器。wm_drv_codec_i2s_set_reg(codec_i2s_dev,0x38,20);
读 CODEC 寄存器
调用
wm_drv_codec_i2s_get_reg
读 CODEC 寄存器。int value; wm_drv_codec_i2s_get_reg(codec_i2s_dev,0x38,&value);
注意事项
备注
音量从0到100,线性映射具体codec的最小db值和最大db值。
当上层音量改变时,具体codec的db阶数较稍,从而db可能没变化,音量也没有变化。
db线性变化时,对应的电压和功率放大不是线性的,人耳感官上的声音也不是线性的,要做到感官上的线性音量改变,需要上层使用者加一个映射表进行转换。
警告
VDDAC 和 VDDSPK电压尽可能保持一致,避免 Speaker 产生爆音。
应用实例
使用 CODEC_I2S 基本示例请参照 examples/peripheral/codec_i2s/wav_play_record
API 参考
查找 CODEC_I2S 相关 API 请参考:
CODEC_I2S 新驱动开发
SDK 中已经包含 ES8374 型号的驱动,针对其他型号的音频芯片,需要添加新的驱动代码。
CODEC 设备驱动框架
CODEC_I2S 驱动有统一的接口,定义在 components/driver/include/codec_i2s/wm_drv_codec_i2s.h 中, 文件中 wm_drv_codec_i2s_ops_t 定义的函数指针,就是实现 CODEC_I2S 驱动需要实现的接口。
CODEC_I2S 的驱动实现都放到 components/driver/src/codec_i2s/ 下,其中 wm_drv_codec_i2s.c 文件实现从统一接口到具体驱动实例的调用,具体驱动实例和设备的关联是在设备表中定义的。
图中 wm_drv_codec_i2s_xxx.c 就是需要实现的驱动。
第一步:在设备表中创建设备信息
下面是 ES8374的设备信息,可参照修改
const static wm_dt_hw_codec_i2s_t dt_hw_es8374 = { .init_cfg = { .init_level = 0, .init_priority = 49 }, .i2s_device_name = "i2s", .i2c_device_name = "i2c", .codec_cfg = { .i2c_address = 0x10, /**< codec i2c 7 bits address */ .in_port = 2, /**< mic port2 input */ .out_port = 3, /**< speaker and headphone use */ .jack_pin = WM_GPIO_NUM_MAX, .pa_pin = WM_GPIO_NUM_MAX, .max_gain = 0, /**< VPA = 5.0V , VDAC = 3.3V , max_gain = 20 * log(5.0/3.3) = 0 dB */ }, };备注
设备表的修改方法 可参考相关章节 Pinmux 以及 设备表
设备表中的 codec_cfg 必须和开发板匹配
第二步:创建新设备的 驱动主体文件
参照 wm_drv_codec_i2s_es8374.c 的实现,复制文件 wm_drv_codec_i2s_es8374.c 为 wm_drv_codec_i2s_XXX.c , 修改其中的 wm_drv_codec_i2s_es8374_ops 为 wm_drv_codec_i2s_XXX_ops , 然后根据新的 CODEC_I2S型号要求修改 实现其中的各个接口实现。
例如:
const wm_drv_codec_i2s_ops_t wm_drv_codec_i2s_xxx_ops = { .init = xxx_init, .deinit = xxx_deinit, .set_format = xxx_set_format, .start = xxx_start, .stop = xxx_stop, .set_mute = xxx_set_mute, .set_volume = xxx_set_volume, .set_mic_mute = xxx_set_mic_mute, .set_mic_volume = xxx_set_mic_volume, .set_reg = xxx_set_reg, .get_reg = xxx_get_reg, .dump = xxx_dump, };第三步: 配置文件完善
在 components/driver 下的 Kconfig 文件中,增加 CODEC 模块使能选项 COMPONENT_DRIVER_CODEC_XXXX_ENABLED
并在 CMakeLists.txt 文件中,把新增加的驱动文件加入编译
下面是 ES8374 的配置:
config COMPONENT_DRIVER_CODEC_ES8374_ENABLED bool "CODEC ES8374" default n select COMPONENT_DRIVER_I2S_ENABLED select COMPONENT_DRIVER_I2C_ENABLED help Enable codec es8374 driver module.备注
新的驱动需要在设备表中关联在某个设备上,这样该设备才能使用新的驱动。