first
This commit is contained in:
414
apps/common/audio/wm8978/iic.c
Normal file
414
apps/common/audio/wm8978/iic.c
Normal file
@ -0,0 +1,414 @@
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/**@file iic_io.c
|
||||
@brief IO模拟的IIC的驱动
|
||||
@details
|
||||
@author zhiying
|
||||
@date 2013-3-26
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include "iic.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: IIC 模块初始化函数
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void iic_init_io(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_init_io(void)
|
||||
{
|
||||
iic_data_h();
|
||||
iic_data_out(); //SDA设置成输出
|
||||
iic_clk_h();
|
||||
iic_clk_out(); //SCL设置成输出
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief
|
||||
@param 无
|
||||
@return
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_start(void)
|
||||
{
|
||||
iic_init_io();
|
||||
iic_delay();
|
||||
iic_data_l();
|
||||
iic_delay();
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
//iic_data_h();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief STOP IIC
|
||||
@param 无
|
||||
@return 无
|
||||
@note void iic_stop(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_stop(void)
|
||||
{
|
||||
iic_data_out();
|
||||
iic_data_l();
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
iic_data_h();
|
||||
iic_delay();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 读取ACK
|
||||
@param 无
|
||||
@return 都会的ACK/NACK的电平
|
||||
@note tbool r_ack(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tbool r_ack(void)
|
||||
{
|
||||
tbool tnack;
|
||||
iic_data_in();
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
tnack = iic_data_r();
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
return tnack;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 发送一个ACK信号的数据,
|
||||
@param flag :发送的ACK/nack的类型
|
||||
@return 无
|
||||
@note void s_ack(u8 flag)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void s_ack(u8 flag)
|
||||
{
|
||||
iic_data_out();
|
||||
iic_clk_l();
|
||||
if (flag) {
|
||||
iic_data_h();
|
||||
} else {
|
||||
iic_data_l();
|
||||
}
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
iic_clk_l();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 从IIC总线接收一个BYTE的数据,
|
||||
@param 无
|
||||
@return 读取回的数据
|
||||
@note u8 iic_revbyte_io( void )
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 iic_revbyte_io(void)
|
||||
{
|
||||
u8 tbyteI2C = 0X00;
|
||||
u8 i;
|
||||
iic_data_in();
|
||||
iic_delay();
|
||||
for (i = 0; i < 8; i++) {
|
||||
iic_clk_h();
|
||||
tbyteI2C <<= 1;
|
||||
iic_delay();
|
||||
if (iic_data_r()) {
|
||||
tbyteI2C++;
|
||||
}
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
}
|
||||
return tbyteI2C;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 从IIC总线接收一个BYTE的数据,并发送一个指定的ACK
|
||||
@param para :发送ACK 还是 NACK
|
||||
@return 读取回的数据
|
||||
@note u8 iic_revbyte( u8 para )
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 iic_revbyte(u8 para)
|
||||
{
|
||||
u8 tbyte;
|
||||
tbyte = iic_revbyte_io();
|
||||
s_ack(para);
|
||||
delay(30000);
|
||||
return tbyte;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 向IIC总线发送一个BYTE的数据
|
||||
@param byte :要写的EEROM的地址
|
||||
@return 无
|
||||
@note void iic_sendbyte_io(u8 byte)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_sendbyte_io(u8 byte)
|
||||
{
|
||||
u8 i;
|
||||
iic_data_out();
|
||||
iic_delay();
|
||||
//otp_printf("byte: %02x\n", byte);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (byte & BIT(7)) {
|
||||
iic_data_h(); //最高位是否为1,为1则SDA= 1,否则 SDA=0
|
||||
} else {
|
||||
iic_data_l();
|
||||
}
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
byte <<= 1; //数据左移一位,进入下一轮送数
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 向IIC总线发送一个BYTE的数据,并读取ACK
|
||||
@param byte :要写的EEROM的地址
|
||||
@return 无
|
||||
@note void iic_sendbyte(u8 byte)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_sendbyte(u8 byte)
|
||||
{
|
||||
iic_sendbyte_io(byte);
|
||||
r_ack();
|
||||
delay(30000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///------------------------------------------------------------------------------
|
||||
///------------------------------------IIC_API-----------------------------------
|
||||
///------------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool g_iic_busy = 0; ///<iic繁忙标记
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: IIC 模块初始化函数
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void iic_init(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_init(void)
|
||||
{
|
||||
// iic_data_out();
|
||||
iic_data_h();
|
||||
iic_data_out();
|
||||
//iic_clk_out();
|
||||
iic_clk_h(); ///<配置接口函数IO
|
||||
iic_clk_out();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: eeprom 核实
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void eeprom_verify(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void eeprom_verify(void)
|
||||
{
|
||||
puts("eeprom_verify 1\n");
|
||||
|
||||
if ((read_eerom(0) != 0x55)
|
||||
|| (read_eerom(1) != 0xAA)) {
|
||||
write_eerom(0, 0x55);
|
||||
write_eerom(1, 0xAA);
|
||||
}
|
||||
|
||||
puts("eeprom_verify 2\n");
|
||||
if ((read_eerom(0) != 0x55)
|
||||
|| (read_eerom(1) != 0xAA)) {
|
||||
puts("iic-no\n");//外接eeprom无效
|
||||
} else {
|
||||
puts("iic-yes\n"); //有外接eeprom
|
||||
}
|
||||
}
|
||||
|
||||
void iic_write_one_byte(u8 iic_dat)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(iic_dat); //写数据
|
||||
iic_stop(); //I2C停止时序
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief IIC写函数
|
||||
@param chip_id :目标IC的ID号
|
||||
@param iic_addr: 目标IC的目标寄存器的地址
|
||||
@param *iic_dat: 写望目标IC的数据的指针
|
||||
@param n:需要写的数据的数目
|
||||
@return 无
|
||||
@note void iic_write(u8 chip_id,u8 iic_addr,u8 *iic_dat,u8 n)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_write(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(chip_id); //写命令
|
||||
|
||||
if (0xff != iic_addr) {
|
||||
iic_sendbyte(iic_addr); //写地址
|
||||
}
|
||||
for (; n > 0; n--) {
|
||||
iic_sendbyte(*iic_dat++); //写数据
|
||||
}
|
||||
iic_stop(); //I2C停止时序
|
||||
g_iic_busy = 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief IIC总线向一个目标ID读取几个数据
|
||||
@param address : 目标ID
|
||||
@param *p : 存档读取到的数据的buffer指针
|
||||
@param number : 需要读取的数据的个数
|
||||
@return 无
|
||||
@note void i2c_read_nbyte(u8 address,u8 *p,u8 number)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_readn(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(chip_id); //写命令
|
||||
if (0xff != iic_addr) {
|
||||
iic_sendbyte(iic_addr); //写地址
|
||||
}
|
||||
for (; n > 1; n--) {
|
||||
*iic_dat++ = iic_revbyte(0); //读数据
|
||||
}
|
||||
*iic_dat++ = iic_revbyte(1);
|
||||
iic_stop(); //I2C停止时序
|
||||
g_iic_busy = 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief EEROM/RTC RAM读函数
|
||||
@param addr :要写的EEROM/RTC RAM的地址
|
||||
@return 读到的数据
|
||||
@note u8 read_info(u8 addr)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 read_info(u8 addr)
|
||||
{
|
||||
return read_eerom(addr);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief EEROM/RTC RAM写函数
|
||||
@param addr :要读的EEROM/RTC RAM的地址
|
||||
@param dat :需要读的数据
|
||||
@return 无
|
||||
@note void write_info(u8 addr,u8 dat)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void write_info(u8 addr, u8 dat)
|
||||
{
|
||||
write_eerom(addr, dat);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief eeprom START
|
||||
@param 无
|
||||
@return 无
|
||||
@note void eeprom_page_write_start(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void eeprom_page_write_start(void)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(0xa0); //写命令
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief IIC STOP
|
||||
@param 无
|
||||
@return 无
|
||||
@note void eeprom_page_write_stop(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void eeprom_page_write_stop(void)
|
||||
{
|
||||
iic_stop(); //I2C停止iic_data_out
|
||||
g_iic_busy = 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief EEROM读函数
|
||||
@param addr :要写的EEROM的地址
|
||||
@param 无
|
||||
@return 无
|
||||
@note u8 iic_read(u8 iic_addr)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 read_eerom(u8 iic_addr)
|
||||
{
|
||||
u8 tbyte;
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(0xa0); //写命令
|
||||
iic_sendbyte(iic_addr); //写地址
|
||||
iic_start(); //写转为读命令,需要再次启动I2C
|
||||
iic_sendbyte(0xa1); //读命令
|
||||
tbyte = iic_revbyte(1);
|
||||
iic_stop(); //I2C停止
|
||||
g_iic_busy = 0;
|
||||
return tbyte;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 带有毫秒延时的EEROM写函数
|
||||
@param addr :要写的EEROM的地址
|
||||
@param dat :需要写的数据
|
||||
@return 无
|
||||
@note void write_info(u8 addr,u8 dat)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void write_eerom(u8 addr, u8 dat)
|
||||
{
|
||||
iic_write(0xa0, addr, &dat, 1);
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: 记忆信息到存储器(EEPROM)
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void set_memory(u8 addr, u8 dat)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void set_memory(u8 addr, u8 dat)
|
||||
{
|
||||
write_eerom(addr, dat);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: 获取记忆信息(EEPROM)
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: u8 get_memory(u8 addr)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
u8 get_memory(u8 addr)
|
||||
{
|
||||
return read_eerom(addr);
|
||||
}
|
||||
63
apps/common/audio/wm8978/iic.h
Normal file
63
apps/common/audio/wm8978/iic.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef _IIC_H_
|
||||
#define _IIC_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
typedef unsigned int tu8, tbool ;
|
||||
|
||||
void iic_write(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n);
|
||||
void iic_readn(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n);
|
||||
void iic_init(void);
|
||||
void iic_init_io(void);
|
||||
void write_info(u8 addr, u8 dat);
|
||||
tu8 read_info(u8 addr);
|
||||
|
||||
void write_eerom(u8 addr, u8 dat);
|
||||
tu8 read_eerom(u8 iic_addr);
|
||||
void eeprom_page_write_stop(void);
|
||||
void eeprom_page_write_start(void);
|
||||
void eeprom_verify(void);
|
||||
|
||||
void iic_start(void);
|
||||
void iic_stop(void);
|
||||
void iic_sendbyte_io(u8 byte);
|
||||
void iic_sendbyte(u8 byte);
|
||||
tu8 iic_revbyte(u8 para);
|
||||
|
||||
extern bool g_iic_busy;
|
||||
|
||||
//#define iic_delay() delay(3000)
|
||||
#define iic_delay() delay(100)
|
||||
|
||||
|
||||
#define IIC_PORT JL_PORTB
|
||||
#define IIC_DATA_PORT 5
|
||||
#define IIC_CLK_PORT 6
|
||||
|
||||
#define iic_clk_out() do{IIC_PORT->DIR &= ~BIT(IIC_CLK_PORT);IIC_PORT->PU &= ~BIT(IIC_CLK_PORT);}while(0)
|
||||
#define iic_clk_h() do{IIC_PORT->OUT |= BIT(IIC_CLK_PORT);IIC_PORT->DIR &=~BIT(IIC_CLK_PORT);}while(0)
|
||||
#define iic_clk_l() do{IIC_PORT->OUT &=~BIT(IIC_CLK_PORT);IIC_PORT->DIR &=~BIT(IIC_CLK_PORT);}while(0)
|
||||
|
||||
#define iic_data_out() do{IIC_PORT->DIR &= ~BIT(IIC_DATA_PORT);IIC_PORT->PU &= ~BIT(IIC_DATA_PORT);}while(0)
|
||||
#define iic_data_in() do{IIC_PORT->DIR |= BIT(IIC_DATA_PORT);IIC_PORT->PU |= BIT(IIC_DATA_PORT);}while(0)
|
||||
#define iic_data_r() (IIC_PORT->IN&BIT(IIC_DATA_PORT))
|
||||
#define iic_data_h() do{IIC_PORT->OUT |= BIT(IIC_DATA_PORT);IIC_PORT->DIR &= ~BIT(IIC_DATA_PORT);}while(0)
|
||||
#define iic_data_l() do{IIC_PORT->OUT &=~BIT(IIC_DATA_PORT);IIC_PORT->DIR &= ~BIT(IIC_DATA_PORT);}while(0)
|
||||
|
||||
/*
|
||||
#define app_IIC_write(a, b, c, d) \
|
||||
iic_write(a, b, c, d)
|
||||
#define app_IIC_readn(a, b, c, d) \
|
||||
iic_readn(a, b, c, d)
|
||||
#define app_E2PROM_write(a, b) \
|
||||
write_eerom(a, b)
|
||||
#define app_E2PROM_read(a) \
|
||||
read_eerom(a)
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
359
apps/common/audio/wm8978/wm8978.c
Normal file
359
apps/common/audio/wm8978/wm8978.c
Normal file
@ -0,0 +1,359 @@
|
||||
#include "iic.h"
|
||||
#include "wm8978.h"
|
||||
|
||||
extern tbool r_ack(void);
|
||||
//--------------------------------------------------------------------------------
|
||||
#define IIC_Init iic_init_io
|
||||
#define IIC_Start iic_start
|
||||
#define IIC_Stop iic_stop
|
||||
#define IIC_Send_Byte iic_sendbyte_io
|
||||
#define IIC_Wait_Ack r_ack
|
||||
|
||||
|
||||
|
||||
|
||||
//WM8978寄存器值缓存区(总共58个寄存器,0~57),占用116字节内存
|
||||
//因为WM8978的IIC操作不支持读操作,所以在本地保存所有寄存器值
|
||||
//写WM8978寄存器时,同步更新到本地寄存器值,读寄存器时,直接返回本地保存的寄存器值.
|
||||
//注意:WM8978的寄存器值是9位的,所以要用u16来存储.
|
||||
static u16 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
|
||||
};
|
||||
|
||||
//WM8978写寄存器
|
||||
//reg:寄存器地址
|
||||
//val:要写入寄存器的值
|
||||
//返回值:0,成功;
|
||||
// 其他,错误代码
|
||||
u8 WM8978_Write_Reg(u8 reg, u16 val)
|
||||
{
|
||||
IIC_Start();
|
||||
IIC_Send_Byte((WM8978_ADDR << 1) | 0); //发送器件地址+写命令
|
||||
if (IIC_Wait_Ack()) {
|
||||
return 1; //等待应答(成功?/失败?)
|
||||
}
|
||||
IIC_Send_Byte((reg << 1) | ((val >> 8) & 0X01)); //写寄存器地址+数据的最高位
|
||||
if (IIC_Wait_Ack()) {
|
||||
return 2; //等待应答(成功?/失败?)
|
||||
}
|
||||
IIC_Send_Byte(val & 0XFF); //发送数据
|
||||
if (IIC_Wait_Ack()) {
|
||||
return 3; //等待应答(成功?/失败?)
|
||||
}
|
||||
IIC_Stop();
|
||||
WM8978_REGVAL_TBL[reg] = val; //保存寄存器值到本地
|
||||
return 0;
|
||||
}
|
||||
|
||||
//WM8978初始化
|
||||
//返回值:0,初始化正常
|
||||
//其他,错误代码
|
||||
u8 WM8978_Init(u8 dacen, u8 adcen)
|
||||
{
|
||||
u8 res;
|
||||
IIC_Init();//初始化IIC接口
|
||||
|
||||
int i = 10;
|
||||
while (--i) {
|
||||
res = WM8978_Write_Reg(0, 0); //软复位WM8978
|
||||
if (!res) {
|
||||
printf("wm8978 reset ok,i=%d\n", i);
|
||||
break;
|
||||
} else {
|
||||
printf("wm8978 cmu err!!!\n");
|
||||
}
|
||||
delay(50000);
|
||||
}
|
||||
if (0 == i) {
|
||||
printf("Rest WM8978 10 times FAIL\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//以下为通用设置
|
||||
WM8978_Write_Reg(1, 0X1B); //R1,MICEN设置为1(MIC使能),BIASEN设置为1(模拟器工作),VMIDSEL[1:0]设置为:11(5K)
|
||||
WM8978_Write_Reg(2, 0X1B0); //R2,ROUT1,LOUT1输出使能(耳机可以工作),BOOSTENR,BOOSTENL使能
|
||||
WM8978_Write_Reg(3, 0X6C); //R3,LOUT2,ROUT2输出使能(喇叭工作),RMIX,LMIX使能
|
||||
WM8978_Write_Reg(6, 0); //R6,MCLK由外部提供
|
||||
WM8978_Write_Reg(43, 1 << 4); //R43,INVROUT2反向,驱动喇叭
|
||||
WM8978_Write_Reg(47, 0 << 8); //R47设置,PGABOOSTL,左通道MIC获得20倍增益
|
||||
WM8978_Write_Reg(48, 0 << 8); //R48设置,PGABOOSTR,右通道MIC获得20倍增益
|
||||
WM8978_Write_Reg(49, 1 << 1); //R49,TSDEN,开启过热保护
|
||||
WM8978_Write_Reg(10, 1 << 3); //R10,SOFTMUTE关闭,128x采样,最佳SNR
|
||||
WM8978_Write_Reg(14, 1 << 3); //R14,ADC 128x采样率
|
||||
|
||||
|
||||
//
|
||||
delay(10000);
|
||||
WM8978_HPvol_Set(30, 30); //耳机音量设置
|
||||
WM8978_SPKvol_Set(60); //喇叭音量设置
|
||||
delay(10000);
|
||||
WM8978_ADDA_Cfg(dacen, adcen); //开启DAC
|
||||
WM8978_Input_Cfg(adcen, 0, 0); //关闭输入通道
|
||||
WM8978_Output_Cfg(dacen, adcen); //开启DAC输出
|
||||
delay(10000);
|
||||
WM8978_I2S_Cfg(2, 0); //飞利浦标准,16位数据长度
|
||||
WM8978_MIC_Gain(63);
|
||||
|
||||
printf("WM8978_Init Finish\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//WM8978读寄存器
|
||||
//就是读取本地寄存器值缓冲区内的对应值
|
||||
//reg:寄存器地址
|
||||
//返回值:寄存器值
|
||||
u16 WM8978_Read_Reg(u8 reg)
|
||||
{
|
||||
return WM8978_REGVAL_TBL[reg];
|
||||
}
|
||||
//WM8978 DAC/ADC配置
|
||||
//adcen:adc使能(1)/关闭(0)
|
||||
//dacen:dac使能(1)/关闭(0)
|
||||
void WM8978_ADDA_Cfg(u8 dacen, u8 adcen)
|
||||
{
|
||||
u16 regval;
|
||||
regval = WM8978_Read_Reg(3); //读取R3
|
||||
if (dacen) {
|
||||
regval |= 3 << 0; //R3最低2个位设置为1,开启DACR&DACL
|
||||
} else {
|
||||
regval &= ~(3 << 0); //R3最低2个位清零,关闭DACR&DACL.
|
||||
}
|
||||
WM8978_Write_Reg(3, regval); //设置R3
|
||||
regval = WM8978_Read_Reg(2); //读取R2
|
||||
if (adcen) {
|
||||
regval |= 3 << 0; //R2最低2个位设置为1,开启ADCR&ADCL
|
||||
} else {
|
||||
regval &= ~(3 << 0); //R2最低2个位清零,关闭ADCR&ADCL.
|
||||
}
|
||||
WM8978_Write_Reg(2, regval); //设置R2
|
||||
}
|
||||
//WM8978 输入通道配置
|
||||
//micen:MIC开启(1)/关闭(0)
|
||||
//lineinen:Line In开启(1)/关闭(0)
|
||||
//auxen:aux开启(1)/关闭(0)
|
||||
void WM8978_Input_Cfg(u8 micen, u8 lineinen, u8 auxen)
|
||||
{
|
||||
u16 regval;
|
||||
regval = WM8978_Read_Reg(2); //读取R2
|
||||
if (micen) {
|
||||
regval |= 3 << 2; //开启INPPGAENR,INPPGAENL(MIC的PGA放大)
|
||||
} else {
|
||||
regval &= ~(3 << 2); //关闭INPPGAENR,INPPGAENL.
|
||||
}
|
||||
WM8978_Write_Reg(2, regval); //设置R2
|
||||
|
||||
regval = WM8978_Read_Reg(44); //读取R44
|
||||
if (micen) {
|
||||
regval |= 3 << 4 | 3 << 0; //开启LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
|
||||
} else {
|
||||
regval &= ~(3 << 4 | 3 << 0); //关闭LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
|
||||
}
|
||||
WM8978_Write_Reg(44, regval); //设置R44
|
||||
|
||||
if (lineinen) {
|
||||
WM8978_LINEIN_Gain(5); //LINE IN 0dB增益
|
||||
} else {
|
||||
WM8978_LINEIN_Gain(0); //关闭LINE IN
|
||||
}
|
||||
if (auxen) {
|
||||
WM8978_AUX_Gain(7); //AUX 6dB增益
|
||||
} else {
|
||||
WM8978_AUX_Gain(0); //关闭AUX输入
|
||||
}
|
||||
}
|
||||
//WM8978 输出配置
|
||||
//dacen:DAC输出(放音)开启(1)/关闭(0)
|
||||
//bpsen:Bypass输出(录音,包括MIC,LINE IN,AUX等)开启(1)/关闭(0)
|
||||
void WM8978_Output_Cfg(u8 dacen, u8 bpsen)
|
||||
{
|
||||
u16 regval = 0;
|
||||
if (dacen) {
|
||||
regval |= 1 << 0; //DAC输出使能
|
||||
}
|
||||
if (bpsen) {
|
||||
regval |= 1 << 1; //BYPASS使能
|
||||
regval |= 5 << 2; //0dB增益
|
||||
}
|
||||
WM8978_Write_Reg(50, regval); //R50设置
|
||||
WM8978_Write_Reg(51, regval); //R51设置
|
||||
}
|
||||
//WM8978 MIC增益设置(不包括BOOST的20dB,MIC-->ADC输入部分的增益)
|
||||
//gain:0~63,对应-12dB~35.25dB,0.75dB/Step
|
||||
void WM8978_MIC_Gain(u8 gain)
|
||||
{
|
||||
gain &= 0X3F;
|
||||
WM8978_Write_Reg(45, gain); //R45,左通道PGA设置
|
||||
WM8978_Write_Reg(46, gain | 1 << 8); //R46,右通道PGA设置
|
||||
}
|
||||
//WM8978 L2/R2(也就是Line In)增益设置(L2/R2-->ADC输入部分的增益)
|
||||
//gain:0~7,0表示通道禁止,1~7,对应-12dB~6dB,3dB/Step
|
||||
void WM8978_LINEIN_Gain(u8 gain)
|
||||
{
|
||||
u16 regval;
|
||||
gain &= 0X07;
|
||||
regval = WM8978_Read_Reg(47); //读取R47
|
||||
regval &= ~(7 << 4); //清除原来的设置
|
||||
WM8978_Write_Reg(47, regval | gain << 4); //设置R47
|
||||
regval = WM8978_Read_Reg(48); //读取R48
|
||||
regval &= ~(7 << 4); //清除原来的设置
|
||||
WM8978_Write_Reg(48, regval | gain << 4); //设置R48
|
||||
}
|
||||
//WM8978 AUXR,AUXL(PWM音频部分)增益设置(AUXR/L-->ADC输入部分的增益)
|
||||
//gain:0~7,0表示通道禁止,1~7,对应-12dB~6dB,3dB/Step
|
||||
void WM8978_AUX_Gain(u8 gain)
|
||||
{
|
||||
u16 regval;
|
||||
gain &= 0X07;
|
||||
regval = WM8978_Read_Reg(47); //读取R47
|
||||
regval &= ~(7 << 0); //清除原来的设置
|
||||
WM8978_Write_Reg(47, regval | gain << 0); //设置R47
|
||||
regval = WM8978_Read_Reg(48); //读取R48
|
||||
regval &= ~(7 << 0); //清除原来的设置
|
||||
WM8978_Write_Reg(48, regval | gain << 0); //设置R48
|
||||
}
|
||||
//设置I2S工作模式
|
||||
//fmt:0,LSB(右对齐);1,MSB(左对齐);2,飞利浦标准I2S;3,PCM/DSP;
|
||||
//len:0,16位;1,20位;2,24位;3,32位;
|
||||
void WM8978_I2S_Cfg(u8 fmt, u8 len)
|
||||
{
|
||||
fmt &= 0X03;
|
||||
len &= 0X03; //限定范围
|
||||
WM8978_Write_Reg(4, (fmt << 3) | (len << 5)); //R4,WM8978工作模式设置
|
||||
}
|
||||
|
||||
//设置耳机左右声道音量
|
||||
//voll:左声道音量(0~63)
|
||||
//volr:右声道音量(0~63)
|
||||
void WM8978_HPvol_Set(u8 voll, u8 volr)
|
||||
{
|
||||
voll &= 0X3F;
|
||||
volr &= 0X3F; //限定范围
|
||||
if (voll == 0) {
|
||||
voll |= 1 << 6; //音量为0时,直接mute
|
||||
}
|
||||
if (volr == 0) {
|
||||
volr |= 1 << 6; //音量为0时,直接mute
|
||||
}
|
||||
WM8978_Write_Reg(52, voll); //R52,耳机左声道音量设置
|
||||
WM8978_Write_Reg(53, volr | (1 << 8)); //R53,耳机右声道音量设置,同步更新(HPVU=1)
|
||||
}
|
||||
//设置喇叭音量
|
||||
//voll:左声道音量(0~63)
|
||||
void WM8978_SPKvol_Set(u8 volx)
|
||||
{
|
||||
volx &= 0X3F; //限定范围
|
||||
if (volx == 0) {
|
||||
volx |= 1 << 6; //音量为0时,直接mute
|
||||
}
|
||||
WM8978_Write_Reg(54, volx); //R54,喇叭左声道音量设置
|
||||
WM8978_Write_Reg(55, volx | (1 << 8)); //R55,喇叭右声道音量设置,同步更新(SPKVU=1)
|
||||
}
|
||||
//设置3D环绕声
|
||||
//depth:0~15(3D强度,0最弱,15最强)
|
||||
void WM8978_3D_Set(u8 depth)
|
||||
{
|
||||
depth &= 0XF; //限定范围
|
||||
WM8978_Write_Reg(41, depth); //R41,3D环绕设置
|
||||
}
|
||||
//设置EQ/3D作用方向
|
||||
//dir:0,在ADC起作用
|
||||
// 1,在DAC起作用(默认)
|
||||
void WM8978_EQ_3D_Dir(u8 dir)
|
||||
{
|
||||
u16 regval;
|
||||
regval = WM8978_Read_Reg(0X12);
|
||||
if (dir) {
|
||||
regval |= 1 << 8;
|
||||
} else {
|
||||
regval &= ~(1 << 8);
|
||||
}
|
||||
WM8978_Write_Reg(18, regval); //R18,EQ1的第9位控制EQ/3D方向
|
||||
}
|
||||
|
||||
//设置EQ1
|
||||
//cfreq:截止频率,0~3,分别对应:80/105/135/175Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ1_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval = WM8978_Read_Reg(18);
|
||||
regval &= 0X100;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(18, regval); //R18,EQ1设置
|
||||
}
|
||||
//设置EQ2
|
||||
//cfreq:中心频率,0~3,分别对应:230/300/385/500Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ2_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(19, regval); //R19,EQ2设置
|
||||
}
|
||||
//设置EQ3
|
||||
//cfreq:中心频率,0~3,分别对应:650/850/1100/1400Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ3_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(20, regval); //R20,EQ3设置
|
||||
}
|
||||
//设置EQ4
|
||||
//cfreq:中心频率,0~3,分别对应:1800/2400/3200/4100Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ4_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(21, regval); //R21,EQ4设置
|
||||
}
|
||||
//设置EQ5
|
||||
//cfreq:中心频率,0~3,分别对应:5300/6900/9000/11700Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ5_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(22, regval); //R22,EQ5设置
|
||||
}
|
||||
|
||||
|
||||
55
apps/common/audio/wm8978/wm8978.h
Normal file
55
apps/common/audio/wm8978/wm8978.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef __WM8978_H
|
||||
#define __WM8978_H
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#define WM8978_ADDR 0X1A //WM8978的器件地址,固定为0X1A
|
||||
|
||||
#define EQ1_80Hz 0X00
|
||||
#define EQ1_105Hz 0X01
|
||||
#define EQ1_135Hz 0X02
|
||||
#define EQ1_175Hz 0X03
|
||||
|
||||
#define EQ2_230Hz 0X00
|
||||
#define EQ2_300Hz 0X01
|
||||
#define EQ2_385Hz 0X02
|
||||
#define EQ2_500Hz 0X03
|
||||
|
||||
#define EQ3_650Hz 0X00
|
||||
#define EQ3_850Hz 0X01
|
||||
#define EQ3_1100Hz 0X02
|
||||
#define EQ3_14000Hz 0X03
|
||||
|
||||
#define EQ4_1800Hz 0X00
|
||||
#define EQ4_2400Hz 0X01
|
||||
#define EQ4_3200Hz 0X02
|
||||
#define EQ4_4100Hz 0X03
|
||||
|
||||
#define EQ5_5300Hz 0X00
|
||||
#define EQ5_6900Hz 0X01
|
||||
#define EQ5_9000Hz 0X02
|
||||
#define EQ5_11700Hz 0X03
|
||||
|
||||
|
||||
u8 WM8978_Init(u8 dacen, u8 adcen);
|
||||
void WM8978_ADDA_Cfg(u8 dacen, u8 adcen);
|
||||
void WM8978_Input_Cfg(u8 micen, u8 lineinen, u8 auxen);
|
||||
void WM8978_Output_Cfg(u8 dacen, u8 bpsen);
|
||||
void WM8978_MIC_Gain(u8 gain);
|
||||
void WM8978_LINEIN_Gain(u8 gain);
|
||||
void WM8978_AUX_Gain(u8 gain);
|
||||
u8 WM8978_Write_Reg(u8 reg, u16 val);
|
||||
u16 WM8978_Read_Reg(u8 reg);
|
||||
void WM8978_HPvol_Set(u8 voll, u8 volr);
|
||||
void WM8978_SPKvol_Set(u8 volx);
|
||||
void WM8978_I2S_Cfg(u8 fmt, u8 len);
|
||||
void WM8978_3D_Set(u8 depth);
|
||||
void WM8978_EQ_3D_Dir(u8 dir);
|
||||
void WM8978_EQ1_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ2_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ3_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ4_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ5_Set(u8 cfreq, u8 gain);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user