/* ****************************************************************************** * @file bsp_led.c * @author fire * @version V1.0 * @date 2015-xx-xx * @brief wm8978驱动 ****************************************************************************** * @attention * * 实验平台:野火 STM32 H750 开发板 * 论坛 :http://www.chuxue123.com * 淘宝 :http://firestm32.taobao.com * ****************************************************************************** */ #include "./wm8978/bsp_wm8978.h" #include "./usart/bsp_debug_usart.h" #include "main.h" #include "./i2c/i2c.h" //#include "./Recorder/Recorder.h" #include "./delay/core_delay.h" extern I2C_HandleTypeDef I2C_Handle; uint32_t AudioTotalSize ; /* 音频文件的总大小 */ uint32_t AudioRemSize; /* 将剩余的数据保存在音频文件中 */ uint16_t *CurrentPos; /* 音频数据指针的当前位置 */ DMA_HandleTypeDef hdma_spi2_tx; DMA_HandleTypeDef hdma_spi2_rx; /** ******************************************************************************************************* * I2C控制WM8978配置部分 ******************************************************************************************************* */ static uint8_t WM8978_I2C_WriteRegister(uint8_t RegisterAddr, uint16_t RegisterValue); static uint16_t wm8978_ReadReg(uint8_t _ucRegAddr); static uint8_t wm8978_WriteReg(uint8_t _ucRegAddr, uint16_t _usValue); /* wm8978寄存器缓存 由于WM8978的I2C两线接口不支持读取操作,因此寄存器值缓存在内存中,当写寄存器时同步更新缓存,读寄存器时 直接返回缓存中的值。 寄存器MAP 在WM8978(V4.5_2011).pdf 的第89页,寄存器地址是7bit, 寄存器数据是9bit */ static uint16_t wm8978_RegCash[] = { 0x000, 0x000, 0x000, 0x000, 0x050, 0x000, 0x140, 0x000, 0x000, 0x000, 0x000, 0x0FF, 0x0FF, 0x000, 0x100, 0x0FF, 0x0FF, 0x000, 0x12C, 0x02C, 0x02C, 0x02C, 0x02C, 0x000, 0x032, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x038, 0x00B, 0x032, 0x000, 0x008, 0x00C, 0x093, 0x0E9, 0x000, 0x000, 0x000, 0x000, 0x003, 0x010, 0x010, 0x100, 0x100, 0x002, 0x001, 0x001, 0x039, 0x039, 0x039, 0x039, 0x001, 0x001 }; /** * @brief 通过I2C将给定寄存器的字节写入音频编解码器 * @param RegisterAddr: 待写入寄存器的地址 * @param RegisterValue: 要写入目标寄存器的字节值 * @retval 通信成功返回1,失败返回0 */ static uint8_t WM8978_I2C_WriteRegister(uint8_t RegisterAddr, uint16_t RegisterValue) { uint16_t tmp; tmp = (RegisterValue&0xff) << 8; tmp |= ((RegisterAddr << 1) & 0xFE) | ((RegisterValue >> 8) & 0x1); if(HAL_I2C_Master_Transmit(&I2C_Handle,WM8978_SLAVE_ADDRESS,(uint8_t *)&tmp,2,WM8978_I2C_FLAG_TIMEOUT)==HAL_OK) { return 1; } else return 0; } /** * @brief 从cash中读回读回wm8978寄存器 * @param _ucRegAddr : 寄存器地址 * @retval 寄存器值 */ static uint16_t wm8978_ReadReg(uint8_t _ucRegAddr) { return wm8978_RegCash[_ucRegAddr]; } /** * @brief 写wm8978寄存器 * @param _ucRegAddr: 寄存器地址 * @param _usValue: 寄存器值 * @retval 0:写入失败 * 1:写入成功 */ static uint8_t wm8978_WriteReg(uint8_t _ucRegAddr, uint16_t _usValue) { uint8_t res; res=WM8978_I2C_WriteRegister(_ucRegAddr,_usValue); wm8978_RegCash[_ucRegAddr] = _usValue; return res; } /** * @brief 配置I2C GPIO,并检查I2C总线上的WM8978是否正常 * @param 无 * @retval 1,初始化成功; * 0,初始化失败。 */ uint8_t wm8978_Init(void) { uint8_t res; I2cMaster_Init(); /* 初始化I2C接口 */ res=wm8978_Reset(); /* 硬件复位WM8978所有寄存器到缺省状态 */ wm8978_CtrlGPIO1(1); /* 控制WM8978的一个GPIO接口控制其为放音状态 */ return res; } /** * @brief 修改输出通道1音量 * @param _ucVolume :音量值, 0-63 * @retval 无 */ void wm8978_SetOUT1Volume(uint8_t _ucVolume) { uint16_t regL; uint16_t regR; if (_ucVolume > 0x3F) { _ucVolume = 0x3F; } regL = _ucVolume; regR = _ucVolume; /* R52 LOUT1 Volume control R53 ROUT1 Volume control */ /* 先更新左声道缓存值 */ wm8978_WriteReg(52, regL | 0x00); /* 再同步更新左右声道的音量 */ wm8978_WriteReg(53, regR | 0x100); /* 0x180表示 在音量为0时再更新,避免调节音量出现的“嘎哒”声 */ } /** * @brief 修改输出通道2音量 * @param _ucVolume :音量值, 0-63 * @retval 无 */ void wm8978_SetOUT2Volume(uint8_t _ucVolume) { uint16_t regL; uint16_t regR; if (_ucVolume > 0x3F) { _ucVolume = 0x3F; } regL = _ucVolume; regR = _ucVolume; /* R54 LOUT2 (SPK) Volume control R55 ROUT2 (SPK) Volume control */ /* 先更新左声道缓存值 */ wm8978_WriteReg(54, regL | 0x00); /* 再同步更新左右声道的音量 */ wm8978_WriteReg(55, regR | 0x100); /* 在音量为0时再更新,避免调节音量出现的“嘎哒”声 */ } /** * @brief 读取输出通道1音量 * @param 无 * @retval 当前音量值 */ uint8_t wm8978_ReadOUT1Volume(void) { return (uint8_t)(wm8978_ReadReg(52) & 0x3F ); } /** * @brief 读取输出通道2音量 * @param 无 * @retval 当前音量值 */ uint8_t wm8978_ReadOUT2Volume(void) { return (uint8_t)(wm8978_ReadReg(54) & 0x3F ); } /** * @brief 输出静音. * @param _ucMute:模式选择 * @arg 1:静音 * @arg 0:取消静音 * @retval 无 */ void wm8978_OutMute(uint8_t _ucMute) { uint16_t usRegValue; if (_ucMute == 1) /* 静音 */ { usRegValue = wm8978_ReadReg(52); /* Left Mixer Control */ usRegValue |= (1u << 6); wm8978_WriteReg(52, usRegValue); usRegValue = wm8978_ReadReg(53); /* Left Mixer Control */ usRegValue |= (1u << 6); wm8978_WriteReg(53, usRegValue); usRegValue = wm8978_ReadReg(54); /* Right Mixer Control */ usRegValue |= (1u << 6); wm8978_WriteReg(54, usRegValue); usRegValue = wm8978_ReadReg(55); /* Right Mixer Control */ usRegValue |= (1u << 6); wm8978_WriteReg(55, usRegValue); } else /* 取消静音 */ { usRegValue = wm8978_ReadReg(52); usRegValue &= ~(1u << 6); wm8978_WriteReg(52, usRegValue); usRegValue = wm8978_ReadReg(53); /* Left Mixer Control */ usRegValue &= ~(1u << 6); wm8978_WriteReg(53, usRegValue); usRegValue = wm8978_ReadReg(54); usRegValue &= ~(1u << 6); wm8978_WriteReg(54, usRegValue); usRegValue = wm8978_ReadReg(55); /* Left Mixer Control */ usRegValue &= ~(1u << 6); wm8978_WriteReg(55, usRegValue); } } /** * @brief 设置增益 * @param _ucGain :增益值, 0-63 * @retval 无 */ void wm8978_SetMicGain(uint8_t _ucGain) { if (_ucGain > GAIN_MAX) { _ucGain = GAIN_MAX; } /* PGA 音量控制 R45, R46 WM8978(V4.5_2011).pdf 25页 Bit8 INPPGAUPDATE Bit7 INPPGAZCL 过零再更改 Bit6 INPPGAMUTEL PGA静音 Bit5:0 增益值,010000是0dB */ wm8978_WriteReg(45, _ucGain); wm8978_WriteReg(46, _ucGain | (1 << 8)); } /** * @brief 设置Line输入通道的增益 * @param _ucGain :音量值, 0-7. 7最大,0最小。 可衰减可放大。 * @retval 无 */ void wm8978_SetLineGain(uint8_t _ucGain) { uint16_t usRegValue; if (_ucGain > 7) { _ucGain = 7; } /* Mic 输入信道的增益由 PGABOOSTL 和 PGABOOSTR 控制 Aux 输入信道的输入增益由 AUXL2BOOSTVO[2:0] 和 AUXR2BOOSTVO[2:0] 控制 Line 输入信道的增益由 LIP2BOOSTVOL[2:0] 和 RIP2BOOSTVOL[2:0] 控制 */ /* WM8978(V4.5_2011).pdf 29页,R47(左声道),R48(右声道), MIC 增益控制寄存器 R47 (R48定义与此相同) B8 PGABOOSTL = 1, 0表示MIC信号直通无增益,1表示MIC信号+20dB增益(通过自举电路) B7 = 0, 保留 B6:4 L2_2BOOSTVOL = x, 0表示禁止,1-7表示增益-12dB ~ +6dB (可以衰减也可以放大) B3 = 0, 保留 B2:0` AUXL2BOOSTVOL = x,0表示禁止,1-7表示增益-12dB ~ +6dB (可以衰减也可以放大) */ usRegValue = wm8978_ReadReg(47); usRegValue &= 0x8F;/* 将Bit6:4清0 1000 1111*/ usRegValue |= (_ucGain << 4); wm8978_WriteReg(47, usRegValue); /* 写左声道输入增益控制寄存器 */ usRegValue = wm8978_ReadReg(48); usRegValue &= 0x8F;/* 将Bit6:4清0 1000 1111*/ usRegValue |= (_ucGain << 4); wm8978_WriteReg(48, usRegValue); /* 写右声道输入增益控制寄存器 */ } /** * @brief 关闭wm8978,进入低功耗模式 * @param 无 * @retval 无 */ void wm8978_PowerDown(void) { wm8978_Reset(); /* 硬件复位WM8978所有寄存器到缺省状态 */ } /** * @brief 配置WM8978的音频接口(I2S) * @param _usStandard : 接口标准,I2S_Standard_Phillips, I2S_Standard_MSB 或 I2S_Standard_LSB * @param _ucWordLen : 字长,16、24、32 (丢弃不常用的20bit格式) * @retval 无 */ void wm8978_CfgAudioIF(uint16_t _usStandard, uint8_t _ucWordLen) { uint16_t usReg; /* WM8978(V4.5_2011).pdf 73页,寄存器列表 */ /* REG R4, 音频接口控制寄存器 B8 BCP = X, BCLK极性,0表示正常,1表示反相 B7 LRCP = x, LRC时钟极性,0表示正常,1表示反相 B6:5 WL = x, 字长,00=16bit,01=20bit,10=24bit,11=32bit (右对齐模式只能操作在最大24bit) B4:3 FMT = x,音频数据格式,00=右对齐,01=左对齐,10=I2S格式,11=PCM B2 DACLRSWAP = x, 控制DAC数据出现在LRC时钟的左边还是右边 B1 ADCLRSWAP = x,控制ADC数据出现在LRC时钟的左边还是右边 B0 MONO = 0,0表示立体声,1表示单声道,仅左声道有效 */ usReg = 0; if (_usStandard == SAI_I2S_STANDARD) /* I2S飞利浦标准 */ { usReg |= (2 << 3); } else if (_usStandard == SAI_I2S_MSBJUSTIFIED) /* MSB对齐标准(左对齐) */ { usReg |= (1 << 3); } else if (_usStandard == SAI_I2S_LSBJUSTIFIED) /* LSB对齐标准(右对齐) */ { usReg |= (0 << 3); } else /* PCM标准(16位通道帧上带长或短帧同步或者16位数据帧扩展为32位通道帧) */ { usReg |= (3 << 3);; } if (_ucWordLen == 24) { usReg |= (2 << 5); } else if (_ucWordLen == 32) { usReg |= (3 << 5); } else { usReg |= (0 << 5); /* 16bit */ } wm8978_WriteReg(4, usReg); /* R6,时钟产生控制寄存器 MS = 0, WM8978被动时钟,由MCU提供MCLK时钟 */ wm8978_WriteReg(6, 0x000); } /** * @brief 配置wm8978音频通道 * @param _InPath : 音频输入通道配置 * @param _OutPath : 音频输出通道配置 * @retval 无 */ void wm8978_CfgAudioPath(uint16_t _InPath, uint16_t _OutPath) { uint16_t usReg; /* 查看WM8978数据手册的 REGISTER MAP 章节, 第89页 */ if ((_InPath == IN_PATH_OFF) && (_OutPath == OUT_PATH_OFF)) { wm8978_PowerDown(); return; } /* --------------------------- 第1步:根据输入通道参数配置寄存器 -----------------------*/ /* R1 寄存器 Power manage 1 Bit8 BUFDCOPEN, Output stage 1.5xAVDD/2 driver enable Bit7 OUT4MIXEN, OUT4 mixer enable Bit6 OUT3MIXEN, OUT3 mixer enable Bit5 PLLEN .不用 Bit4 MICBEN ,Microphone Bias Enable (MIC偏置电路使能) Bit3 BIASEN ,Analogue amplifier bias control 必须设置为1模拟放大器才工作 Bit2 BUFIOEN , Unused input/output tie off buffer enable Bit1:0 VMIDSEL, 必须设置为非00值模拟放大器才工作 */ usReg = (1 << 3) | (3 << 0); if (_OutPath & OUT3_4_ON) /* OUT3和OUT4使能输出到GSM模块 */ { usReg |= ((1 << 7) | (1 << 6)); } if ((_InPath & MIC_LEFT_ON) || (_InPath & MIC_RIGHT_ON)) { usReg |= (1 << 4); } wm8978_WriteReg(1, usReg); /* 写寄存器 */ /* R2 寄存器 Power manage 2 Bit8 ROUT1EN, ROUT1 output enable 耳机右声道输出使能 Bit7 LOUT1EN, LOUT1 output enable 耳机左声道输出使能 Bit6 SLEEP, 0 = Normal device operation 1 = Residual current reduced in device standby mode Bit5 BOOSTENR, Right channel Input BOOST enable 输入通道自举电路使能. 用到PGA放大功能时必须使能 Bit4 BOOSTENL, Left channel Input BOOST enable Bit3 INPGAENR, Right channel input PGA enable 右声道输入PGA使能 Bit2 INPGAENL, Left channel input PGA enable Bit1 ADCENR, Enable ADC right channel Bit0 ADCENL, Enable ADC left channel */ usReg = 0; if (_OutPath & EAR_LEFT_ON) { usReg |= (1 << 7); } if (_OutPath & EAR_RIGHT_ON) { usReg |= (1 << 8); } if (_InPath & MIC_LEFT_ON) { usReg |= ((1 << 4) | (1 << 2)); } if (_InPath & MIC_RIGHT_ON) { usReg |= ((1 << 5) | (1 << 3)); } if (_InPath & LINE_ON) { usReg |= ((1 << 4) | (1 << 5)); } if (_InPath & MIC_RIGHT_ON) { usReg |= ((1 << 5) | (1 << 3)); } if (_InPath & ADC_ON) { usReg |= ((1 << 1) | (1 << 0)); } wm8978_WriteReg(2, usReg); /* 写寄存器 */ /* R3 寄存器 Power manage 3 Bit8 OUT4EN, OUT4 enable Bit7 OUT3EN, OUT3 enable Bit6 LOUT2EN, LOUT2 output enable Bit5 ROUT2EN, ROUT2 output enable Bit4 0, Bit3 RMIXEN, Right mixer enable Bit2 LMIXEN, Left mixer enable Bit1 DACENR, Right channel DAC enable Bit0 DACENL, Left channel DAC enable */ usReg = 0; if (_OutPath & OUT3_4_ON) { usReg |= ((1 << 8) | (1 << 7)); } if (_OutPath & SPK_ON) { usReg |= ((1 << 6) | (1 << 5)); } if (_OutPath != OUT_PATH_OFF) { usReg |= ((1 << 3) | (1 << 2)); } if (_InPath & DAC_ON) { usReg |= ((1 << 1) | (1 << 0)); } wm8978_WriteReg(3, usReg); /* 写寄存器 */ /* R44 寄存器 Input ctrl Bit8 MBVSEL, Microphone Bias Voltage Control 0 = 0.9 * AVDD 1 = 0.6 * AVDD Bit7 0 Bit6 R2_2INPPGA, Connect R2 pin to right channel input PGA positive terminal Bit5 RIN2INPPGA, Connect RIN pin to right channel input PGA negative terminal Bit4 RIP2INPPGA, Connect RIP pin to right channel input PGA amplifier positive terminal Bit3 0 Bit2 L2_2INPPGA, Connect L2 pin to left channel input PGA positive terminal Bit1 LIN2INPPGA, Connect LIN pin to left channel input PGA negative terminal Bit0 LIP2INPPGA, Connect LIP pin to left channel input PGA amplifier positive terminal */ usReg = 0 << 8; if (_InPath & LINE_ON) { usReg |= ((1 << 6) | (1 << 2)); } if (_InPath & MIC_RIGHT_ON) { usReg |= ((1 << 5) | (1 << 4)); } if (_InPath & MIC_LEFT_ON) { usReg |= ((1 << 1) | (1 << 0)); } wm8978_WriteReg(44, usReg); /* 写寄存器 */ /* R14 寄存器 ADC Control 设置高通滤波器(可选的) WM8978(V4.5_2011).pdf 31 32页, Bit8 HPFEN, High Pass Filter Enable高通滤波器使能,0表示禁止,1表示使能 BIt7 HPFAPP, Select audio mode or application mode 选择音频模式或应用模式,0表示音频模式, Bit6:4 HPFCUT,Application mode cut-off frequency 000-111选择应用模式的截止频率 Bit3 ADCOSR, ADC oversample rate select: 0=64x (lower power) 1=128x (best performance) Bit2 0 Bit1 ADC right channel polarity adjust: 0=normal 1=inverted Bit0 ADC left channel polarity adjust: 0=normal 1=inverted */ if (_InPath & ADC_ON) { usReg = (1 << 3) | (0 << 8) | (4 << 0); /* 禁止ADC高通滤波器, 设置截至频率 */ } else { usReg = 0; } wm8978_WriteReg(14, usReg); /* 写寄存器 */ /* 设置陷波滤波器(notch filter),主要用于抑制话筒声波正反馈,避免啸叫. 暂时关闭 R27,R28,R29,R30 用于控制限波滤波器,WM8978(V4.5_2011).pdf 33页 R7的 Bit7 NFEN = 0 表示禁止,1表示使能 */ if (_InPath & ADC_ON) { usReg = (0 << 7); wm8978_WriteReg(27, usReg); /* 写寄存器 */ usReg = 0; wm8978_WriteReg(28, usReg); /* 写寄存器,填0,因为已经禁止,所以也可不做 */ wm8978_WriteReg(29, usReg); /* 写寄存器,填0,因为已经禁止,所以也可不做 */ wm8978_WriteReg(30, usReg); /* 写寄存器,填0,因为已经禁止,所以也可不做 */ } /* 自动增益控制 ALC, R32 - 34 WM8978(V4.5_2011).pdf 36页 */ { usReg = 0; /* 禁止自动增益控制 */ wm8978_WriteReg(32, usReg); wm8978_WriteReg(33, usReg); wm8978_WriteReg(34, usReg); } /* R35 ALC Noise Gate Control Bit3 NGATEN, Noise gate function enable Bit2:0 Noise gate threshold: */ usReg = (3 << 1) | (7 << 0); /* 禁止自动增益控制 */ wm8978_WriteReg(35, usReg); /* Mic 输入信道的增益由 PGABOOSTL 和 PGABOOSTR 控制 Aux 输入信道的输入增益由 AUXL2BOOSTVO[2:0] 和 AUXR2BOOSTVO[2:0] 控制 Line 输入信道的增益由 LIP2BOOSTVOL[2:0] 和 RIP2BOOSTVOL[2:0] 控制 */ /* WM8978(V4.5_2011).pdf 29页,R47(左声道),R48(右声道), MIC 增益控制寄存器 R47 (R48定义与此相同) B8 PGABOOSTL = 1, 0表示MIC信号直通无增益,1表示MIC信号+20dB增益(通过自举电路) B7 = 0, 保留 B6:4 L2_2BOOSTVOL = x, 0表示禁止,1-7表示增益-12dB ~ +6dB (可以衰减也可以放大) B3 = 0, 保留 B2:0` AUXL2BOOSTVOL = x,0表示禁止,1-7表示增益-12dB ~ +6dB (可以衰减也可以放大) */ usReg = 0; if ((_InPath & MIC_LEFT_ON) || (_InPath & MIC_RIGHT_ON)) { usReg |= (1 << 8); /* MIC增益取+20dB */ } if (_InPath & AUX_ON) { usReg |= (3 << 0); /* Aux增益固定取3,用户可以自行调整 */ } if (_InPath & LINE_ON) { usReg |= (3 << 4); /* Line增益固定取3,用户可以自行调整 */ } wm8978_WriteReg(47, usReg); /* 写左声道输入增益控制寄存器 */ wm8978_WriteReg(48, usReg); /* 写右声道输入增益控制寄存器 */ /* 数字ADC音量控制,pdf 35页 R15 控制左声道ADC音量,R16控制右声道ADC音量 Bit8 ADCVU = 1 时才更新,用于同步更新左右声道的ADC音量 Bit7:0 增益选择; 0000 0000 = 静音 0000 0001 = -127dB 0000 0010 = -12.5dB (0.5dB 步长) 1111 1111 = 0dB (不衰减) */ usReg = 0xFF; wm8978_WriteReg(15, usReg); /* 选择0dB,先缓存左声道 */ usReg = 0x1FF; wm8978_WriteReg(16, usReg); /* 同步更新左右声道 */ /* 通过 wm8978_SetMicGain 函数设置mic PGA增益 */ /* R43 寄存器 AUXR – ROUT2 BEEP Mixer Function B8:6 = 0 B5 MUTERPGA2INV, Mute input to INVROUT2 mixer B4 INVROUT2, Invert ROUT2 output 用于扬声器推挽输出 B3:1 BEEPVOL = 7; AUXR input to ROUT2 inverter gain B0 BEEPEN = 1; Enable AUXR beep input */ usReg = 0; if (_OutPath & SPK_ON) { usReg |= (1 << 4); /* ROUT2 反相, 用于驱动扬声器 */ } if (_InPath & AUX_ON) { usReg |= ((7 << 1) | (1 << 0)); } wm8978_WriteReg(43, usReg); /* R49 Output ctrl B8:7 0 B6 DACL2RMIX, Left DAC output to right output mixer B5 DACR2LMIX, Right DAC output to left output B4 OUT4BOOST, 0 = OUT4 output gain = -1; DC = AVDD / 2;1 = OUT4 output gain = +1.5;DC = 1.5 x AVDD / 2 B3 OUT3BOOST, 0 = OUT3 output gain = -1; DC = AVDD / 2;1 = OUT3 output gain = +1.5;DC = 1.5 x AVDD / 2 B2 SPKBOOST, 0 = Speaker gain = -1; DC = AVDD / 2 ; 1 = Speaker gain = +1.5; DC = 1.5 x AVDD / 2 B1 TSDEN, Thermal Shutdown Enable 扬声器热保护使能(缺省1) B0 VROI, Disabled Outputs to VREF Resistance */ usReg = 0; if (_InPath & DAC_ON) { usReg |= ((1 << 6) | (1 << 5)); } if (_OutPath & SPK_ON) { usReg |= ((1 << 2) | (1 << 1)); /* SPK 1.5x增益, 热保护使能 */ } if (_OutPath & OUT3_4_ON) { usReg |= ((1 << 4) | (1 << 3)); /* BOOT3 BOOT4 1.5x增益 */ } wm8978_WriteReg(49, usReg); /* REG 50 (50是左声道,51是右声道,配置寄存器功能一致) WM8978(V4.5_2011).pdf 56页 B8:6 AUXLMIXVOL = 111 AUX用于FM收音机信号输入 B5 AUXL2LMIX = 1 Left Auxilliary input to left channel B4:2 BYPLMIXVOL 音量 B1 BYPL2LMIX = 0; Left bypass path (from the left channel input boost output) to left output mixer B0 DACL2LMIX = 1; Left DAC output to left output mixer */ usReg = 0; if (_InPath & AUX_ON) { usReg |= ((7 << 6) | (1 << 5)); } if ((_InPath & LINE_ON) || (_InPath & MIC_LEFT_ON) || (_InPath & MIC_RIGHT_ON)) { usReg |= ((7 << 2) | (1 << 1)); } if (_InPath & DAC_ON) { usReg |= (1 << 0); } wm8978_WriteReg(50, usReg); wm8978_WriteReg(51, usReg); /* R56 寄存器 OUT3 mixer ctrl B8:7 0 B6 OUT3MUTE, 0 = Output stage outputs OUT3 mixer; 1 = Output stage muted – drives out VMID. B5:4 0 B3 BYPL2OUT3, OUT4 mixer output to OUT3 (反相) B4 0 B2 LMIX2OUT3, Left ADC input to OUT3 B1 LDAC2OUT3, Left DAC mixer to OUT3 B0 LDAC2OUT3, Left DAC output to OUT3 */ usReg = 0; if (_OutPath & OUT3_4_ON) { usReg |= (1 << 3); } wm8978_WriteReg(56, usReg); /* R57 寄存器 OUT4 (MONO) mixer ctrl B8:7 0 B6 OUT4MUTE, 0 = Output stage outputs OUT4 mixer 1 = Output stage muted – drives outVMID. B5 HALFSIG, 0 = OUT4 normal output 1 = OUT4 attenuated by 6dB B4 LMIX2OUT4, Left DAC mixer to OUT4 B3 LDAC2UT4, Left DAC to OUT4 B2 BYPR2OUT4, Right ADC input to OUT4 B1 RMIX2OUT4, Right DAC mixer to OUT4 B0 RDAC2OUT4, Right DAC output to OUT4 */ usReg = 0; if (_OutPath & OUT3_4_ON) { usReg |= ((1 << 4) | (1 << 1)); } wm8978_WriteReg(57, usReg); /* R11, 12 寄存器 DAC数字音量 R11 Left DAC Digital Volume R12 Right DAC Digital Volume */ if (_InPath & DAC_ON) { wm8978_WriteReg(11, 255); wm8978_WriteReg(12, 255 | 0x100); } else { wm8978_WriteReg(11, 0); wm8978_WriteReg(12, 0 | 0x100); } /* R10 寄存器 DAC Control B8 0 B7 0 B6 SOFTMUTE, Softmute enable: B5 0 B4 0 B3 DACOSR128, DAC oversampling rate: 0=64x (lowest power) 1=128x (best performance) B2 AMUTE, Automute enable B1 DACPOLR, Right DAC output polarity B0 DACPOLL, Left DAC output polarity: */ if (_InPath & DAC_ON) { wm8978_WriteReg(10, 0); } ; } /** * @brief 设置陷波滤波器(notch filter),主要用于抑制话筒声波正反馈,避免啸叫 * @param NFA0[13:0] and NFA1[13:0] * @retval 无 */ void wm8978_NotchFilter(uint16_t _NFA0, uint16_t _NFA1) { uint16_t usReg; /* page 26 A programmable notch filter is provided. This filter has a variable centre frequency and bandwidth, programmable via two coefficients, a0 and a1. a0 and a1 are represented by the register bits NFA0[13:0] and NFA1[13:0]. Because these coefficient values require four register writes to setup there is an NFU (Notch Filter Update) flag which should be set only when all four registers are setup. */ usReg = (1 << 7) | (_NFA0 & 0x3F); wm8978_WriteReg(27, usReg); /* 写寄存器 */ usReg = ((_NFA0 >> 7) & 0x3F); wm8978_WriteReg(28, usReg); /* 写寄存器 */ usReg = (_NFA1 & 0x3F); wm8978_WriteReg(29, usReg); /* 写寄存器 */ usReg = (1 << 8) | ((_NFA1 >> 7) & 0x3F); wm8978_WriteReg(30, usReg); /* 写寄存器 */ } /** * @brief 控制WM8978的GPIO1引脚输出0或1, * 控制模拟开关来切换录音放音 * 1:放音 * 0:录音 * @param _ucValue :GPIO1输出值,0或1 * @retval 无 */ void wm8978_CtrlGPIO1(uint8_t _ucValue) { uint16_t usRegValue; /* R8, pdf 62页 */ if (_ucValue == 0) /* 输出0 */ { usRegValue = 6; /* B2:0 = 110 */ } else { usRegValue = 7; /* B2:0 = 111 */ } wm8978_WriteReg(8, usRegValue); } /** * @brief 复位wm8978,所有的寄存器值恢复到缺省值 * @param 无 * @retval 1: 复位成功 * 0:复位失败 */ uint8_t wm8978_Reset(void) { /* wm8978寄存器缺省值 */ const uint16_t reg_default[] = { 0x000, 0x000, 0x000, 0x000, 0x050, 0x000, 0x140, 0x000, 0x000, 0x000, 0x000, 0x0FF, 0x0FF, 0x000, 0x100, 0x0FF, 0x0FF, 0x000, 0x12C, 0x02C, 0x02C, 0x02C, 0x02C, 0x000, 0x032, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x038, 0x00B, 0x032, 0x000, 0x008, 0x00C, 0x093, 0x0E9, 0x000, 0x000, 0x000, 0x000, 0x003, 0x010, 0x010, 0x100, 0x100, 0x002, 0x001, 0x001, 0x039, 0x039, 0x039, 0x039, 0x001, 0x001 }; uint8_t res; uint8_t i; res=wm8978_WriteReg(0x00, 0); for (i = 0; i < sizeof(reg_default) / 2; i++) { wm8978_RegCash[i] = reg_default[i]; } return res; } /***************************** (END OF FILE) *********************************/