头文件
#ifndef F4_OS_AUDIO_WM8978_H
#define F4_OS_AUDIO_WM8978_H
#include "rtdevice.h"
#define WM8978_ADDR 0X1A
struct audio_wm8978 {
struct rt_i2c_bus_device *bus;
uint8_t addr;
rt_mutex_t lock;
};
typedef struct audio_wm8978 *audio_wm8978_t;
audio_wm8978_t wm8978_init(char *bus_name, uint8_t addr);
rt_err_t wm8978_cnf_init();
void wm8978_deInit(audio_wm8978_t wm8978);
rt_err_t wm8978_set_reg(audio_wm8978_t wm8978, uint8_t reg, uint16_t val);
uint16_t wm8978_read_reg(uint8_t reg);
void wm8978_ADDA_Cfg(uint8_t dacen, uint8_t adcen);
void wm8978_Input_Cfg(uint8_t micen, uint8_t lineinen, uint8_t auxen);
void wm8978_Output_Cfg(uint8_t dacen, uint8_t bpsen);
void wm8978_MIC_Gain(uint8_t gain);
void wm8978_LINEIN_Gain(uint8_t gain);
void wm8978_AUX_Gain(uint8_t gain);
void wm8978_I2S_Cfg(uint8_t fmt, uint8_t len);
void wm8978_HPvol_Set(uint8_t voll, uint8_t volr);
void wm8978_SPKvol_Set(uint8_t volx);
void wm8978_3D_Set(uint8_t depth);
void wm8978_EQ_3D_Dir(uint8_t dir);
void wm8978_EQ1_Set(uint8_t cfreq, uint8_t gain);
void wm8978_EQ2_Set(uint8_t cfreq, uint8_t gain);
void wm8978_EQ3_Set(uint8_t cfreq, uint8_t gain);
void wm8978_EQ4_Set(uint8_t cfreq, uint8_t gain);
void wm8978_EQ5_Set(uint8_t cfreq, uint8_t gain);
#endif
源文件
#include "audio_wm8978.h"
#include <rtthread.h>
#define DBG_ENABLE
#define DBG_TAG "wm8978"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
static audio_wm8978_t device = NULL;
static uint16_t wm8978_REGVAL_TBL[58] =
{
0X0000, 0X0000, 0X0000, 0X0000, 0X0050, 0X0000, 0X0140, 0X0000,
0X0000, 0X0000, 0X0000, 0X00FF, 0X00FF, 0X0000, 0X0100, 0X00FF,
0X00FF, 0X0000, 0X012C, 0X002C, 0X002C, 0X002C, 0X002C, 0X0000,
0X0032, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000,
0X0038, 0X000B, 0X0032, 0X0000, 0X0008, 0X000C, 0X0093, 0X00E9,
0X0000, 0X0000, 0X0000, 0X0000, 0X0003, 0X0010, 0X0010, 0X0100,
0X0100, 0X0002, 0X0001, 0X0001, 0X0039, 0X0039, 0X0039, 0X0039,
0X0001, 0X0001
};
static rt_err_t write_reg(uint8_t reg, uint16_t val) {
return wm8978_set_reg(device, reg, val);
}
rt_err_t wm8978_set_reg(audio_wm8978_t wm8978, uint8_t reg, uint16_t val) {
rt_uint8_t buf[2];
buf[0] = (reg << 1) | ((val >> 8) & 0X01);
buf[1] = val & 0XFF;
if (wm8978 == NULL) {
LOG_E("请先执行 wm8978_init");
return RT_ERROR;
}
if (rt_i2c_master_send(wm8978->bus, wm8978->addr, RT_I2C_WR, buf, 2) != 2) {
return RT_ERROR;
}
wm8978_REGVAL_TBL[reg] = val;
return RT_EOK;
}
audio_wm8978_t wm8978_init(char *bus_name, uint8_t addr) {
RT_ASSERT(bus_name);
device = rt_calloc(1, sizeof(struct audio_wm8978));
if (device == RT_NULL) {
LOG_E("Can't allocate memory for audio_wm8978 device on '%s' ", bus_name);
return RT_NULL;
}
device->bus = rt_i2c_bus_device_find(bus_name);
if (device->bus == RT_NULL) {
LOG_E("Can't find audio_wm8978 device on '%s' ", bus_name);
rt_free(device);
return RT_NULL;
}
device->lock = rt_mutex_create("mutex_wm8978", RT_IPC_FLAG_FIFO);
if (device->lock == RT_NULL) {
LOG_E("Can't create mutex for audio_wm8978 device on '%s' ", bus_name);
rt_free(device);
return RT_NULL;
}
{
device->bus->timeout = 3;
device->addr = addr;
}
return device;
}
void wm8978_deInit(audio_wm8978_t wm8978) {
if (wm8978 != NULL) {
if (wm8978 == device) {
rt_free(wm8978);
}
}
}
rt_err_t wm8978_cnf_init() {
if (write_reg(0, 0) != RT_EOK) return RT_ERROR;
write_reg(1, 0X1B);
write_reg(2, 0X1B0);
write_reg(3, 0X6C);
write_reg(6, 0);
write_reg(43, 1 << 4);
write_reg(47, 1 << 8);
write_reg(48, 1 << 8);
write_reg(49, 1 << 1);
write_reg(49, 1 << 2);
write_reg(10, 1 << 3);
write_reg(14, 1 << 3);
return RT_EOK;
}
uint16_t wm8978_read_reg(uint8_t reg) {
return wm8978_REGVAL_TBL[reg];
}
void wm8978_ADDA_Cfg(uint8_t dacen, uint8_t adcen) {
uint16_t regval;
regval = wm8978_read_reg(3);
if (dacen)regval |= 3 << 0;
else regval &= ~(3 << 0);
write_reg(3, regval);
regval = wm8978_read_reg(2);
if (adcen)regval |= 3 << 0;
else regval &= ~(3 << 0);
write_reg(2, regval);
}
void wm8978_Input_Cfg(uint8_t micen, uint8_t lineinen, uint8_t auxen) {
uint16_t regval;
regval = wm8978_read_reg(2);
if (micen)regval |= 3 << 2;
else regval &= ~(3 << 2);
write_reg(2, regval);
regval = wm8978_read_reg(44);
if (micen)regval |= 3 << 4 | 3 << 0;
else regval &= ~(3 << 4 | 3 << 0);
write_reg(44, regval);
if (lineinen)wm8978_LINEIN_Gain(5);
else wm8978_LINEIN_Gain(0);
if (auxen)wm8978_AUX_Gain(7);
else wm8978_AUX_Gain(0);
}
void wm8978_Output_Cfg(uint8_t dacen, uint8_t bpsen) {
uint16_t regval = 0;
if (dacen)regval |= 1 << 0;
if (bpsen) {
regval |= 1 << 1;
regval |= 5 << 2;
}
write_reg(50, regval);
write_reg(51, regval);
}
void wm8978_MIC_Gain(uint8_t gain) {
gain &= 0X3F;
write_reg(45, gain);
write_reg(46, gain | 1 << 8);
}
void wm8978_LINEIN_Gain(uint8_t gain) {
uint16_t regval;
gain &= 0X07;
regval = wm8978_read_reg(47);
regval &= ~(7 << 4);
write_reg(47, regval | gain << 4);
regval = wm8978_read_reg(48);
regval &= ~(7 << 4);
write_reg(48, regval | gain << 4);
}
void wm8978_AUX_Gain(uint8_t gain) {
uint16_t regval;
gain &= 0X07;
regval = wm8978_read_reg(47);
regval &= ~(7 << 0);
write_reg(47, regval | gain << 0);
regval = wm8978_read_reg(48);
regval &= ~(7 << 0);
write_reg(48, regval | gain << 0);
}
void wm8978_I2S_Cfg(uint8_t fmt, uint8_t len) {
fmt &= 0X03;
len &= 0X03;
write_reg(4, (fmt << 3) | (len << 5));
}
void wm8978_HPvol_Set(uint8_t voll, uint8_t volr) {
voll &= 0X3F;
volr &= 0X3F;
if (voll == 0)voll |= 1 << 6;
if (volr == 0)volr |= 1 << 6;
write_reg(52, voll);
write_reg(53, volr | (1 << 8));
}
void wm8978_SPKvol_Set(uint8_t volx) {
volx &= 0X3F;
if (volx == 0)volx |= 1 << 6;
write_reg(54, volx);
write_reg(55, volx | (1 << 8));
}
void wm8978_3D_Set(uint8_t depth) {
depth &= 0XF;
write_reg(41, depth);
}
void wm8978_EQ_3D_Dir(uint8_t dir) {
uint16_t regval;
regval = wm8978_read_reg(0X12);
if (dir)regval |= 1 << 8;
else regval &= ~(1 << 8);
write_reg(18, regval);
}
void wm8978_EQ1_Set(uint8_t cfreq, uint8_t gain) {
uint16_t regval;
cfreq &= 0X3;
if (gain > 24)gain = 24;
gain = 24 - gain;
regval = wm8978_read_reg(18);
regval &= 0X100;
regval |= cfreq << 5;
regval |= gain;
write_reg(18, regval);
}
void wm8978_EQ2_Set(uint8_t cfreq, uint8_t gain) {
uint16_t regval = 0;
cfreq &= 0X3;
if (gain > 24)gain = 24;
gain = 24 - gain;
regval |= cfreq << 5;
regval |= gain;
write_reg(19, regval);
}
void wm8978_EQ3_Set(uint8_t cfreq, uint8_t gain) {
uint16_t regval = 0;
cfreq &= 0X3;
if (gain > 24)gain = 24;
gain = 24 - gain;
regval |= cfreq << 5;
regval |= gain;
write_reg(20, regval);
}
void wm8978_EQ4_Set(uint8_t cfreq, uint8_t gain) {
uint16_t regval = 0;
cfreq &= 0X3;
if (gain > 24)gain = 24;
gain = 24 - gain;
regval |= cfreq << 5;
regval |= gain;
write_reg(21, regval);
}
void wm8978_EQ5_Set(uint8_t cfreq, uint8_t gain) {
uint16_t regval = 0;
cfreq &= 0X3;
if (gain > 24)gain = 24;
gain = 24 - gain;
regval |= cfreq << 5;
regval |= gain;
write_reg(22, regval);
}