【ZYNQ-7000开发之十六】音频信号处理
2016-03-15 16:25
477 查看
本编文章将使用Zynq开发平台Miz702上的ADAU1761音频编解码芯片,进行采样模拟音频信号(2路),转成数字信号,然后再通过ADAU1761转成模拟信号输出(2路)。在此基础上通过左右声道相减,简单的实现人声消除。本文不介绍ADAU1761驱动的编写方法,直接采用 Ali Aljaani编写的IP。
ADAU1761参数的配置参考 ADA1761 Datasheet
本文所使用的开发板是Miz702(兼容zedboard)
PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2
3.5mm公对公的音频连接线一根
ADA1761驱动IP core下载
点击Create Blcok Design,完成后点击Add IP,把ZYNQ PS,添加进来,然后双击ZYNQ,进行如下配置
在Clock Configuration下,使能FLCK_CLK1,并且把时钟配置成10Mhz,如图所示
选中IIC_1和FCLK_CLK1,右击,点击Make external
结果如图所示
点击Add IP,添加zed_audio_ctrl IP,添加好之后点击Run Connection Automation
选中zed_audio_ctrl上其余的接口,右击,Make external
在空白处右击,选择Create port
然后按照如图所示配置
点击Add IP,添加Constant IP,配置如下
新建一个约束文件,把以下引脚约束添加进来
配置好之后和ADDRESS连接在一起,
然后就可以Create HDL wapper,点击Generate bitstream
新建头文件文件,
audio.h
新建C文件
audio.c
下载完成后测试效果:采集的音频信号,再次输出
红色的线是音频输入,白色的是耳机输出
ADAU1761参数的配置参考 ADA1761 Datasheet
本文所使用的开发板是Miz702(兼容zedboard)
PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2
3.5mm公对公的音频连接线一根
ADA1761驱动IP core下载
建立vivado工程
建好工程之后,把下载好的IP添加到IP Repository里面,如图所示点击Create Blcok Design,完成后点击Add IP,把ZYNQ PS,添加进来,然后双击ZYNQ,进行如下配置
在Clock Configuration下,使能FLCK_CLK1,并且把时钟配置成10Mhz,如图所示
选中IIC_1和FCLK_CLK1,右击,点击Make external
结果如图所示
点击Add IP,添加zed_audio_ctrl IP,添加好之后点击Run Connection Automation
选中zed_audio_ctrl上其余的接口,右击,Make external
在空白处右击,选择Create port
然后按照如图所示配置
点击Add IP,添加Constant IP,配置如下
新建一个约束文件,把以下引脚约束添加进来
# Miz702 or zedboard Audio Codec Constraints set_property PACKAGE_PIN AA6 [get_ports BCLK] set_property IOSTANDARD LVCMOS33 [get_ports BCLK] set_property PACKAGE_PIN Y6 [get_ports LRCLK] set_property IOSTANDARD LVCMOS33 [get_ports LRCLK] set_property PACKAGE_PIN AA7 [get_ports SDATA_I] set_property IOSTANDARD LVCMOS33 [get_ports SDATA_I] set_property PACKAGE_PIN Y8 [get_ports SDATA_O] set_property IOSTANDARD LVCMOS33 [get_ports SDATA_O] #MCLK set_property PACKAGE_PIN AB2 [get_ports FCLK_CLK1] set_property IOSTANDARD LVCMOS33 [get_ports FCLK_CLK1] set_property PACKAGE_PIN AB4 [get_ports iic_1_scl_io] set_property IOSTANDARD LVCMOS33 [get_ports iic_1_scl_io] set_property PACKAGE_PIN AB5 [get_ports iic_1_sda_io] set_property IOSTANDARD LVCMOS33 [get_ports iic_1_sda_io] set_property PACKAGE_PIN AB1 [get_ports {ADDRESS[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {ADDRESS[0]}] set_property PACKAGE_PIN Y5 [get_ports {ADDRESS[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {ADDRESS[1]}]
配置好之后和ADDRESS连接在一起,
然后就可以Create HDL wapper,点击Generate bitstream
建立软件工程
打开SDK之后,新建一个空的工程新建头文件文件,
audio.h
#ifndef __AUDIO_H_ #define __AUDIO_H_ #include "xparameters.h" /* Redefine audio controller base address from xparameters.h */ #define AUDIO_BASE XPAR_ZED_AUDIO_CTRL_0_BASEADDR /* Slave address for the ADAU audio controller 8 */ #define IIC_SLAVE_ADDR 0x70 /* I2C Serial Clock frequency in Hertz */ #define IIC_SCLK_RATE 400000 /* ADAU internal registers */ enum audio_regs { R0_CLOCK_CONTROL = 0x00, R1_PLL_CONTROL = 0x02, R2_DIGITAL_MIC_JACK_DETECTION_CONTROL = 0x08, R3_RECORD_POWER_MANAGEMENT = 0x09, R4_RECORD_MIXER_LEFT_CONTROL_0 = 0x0A, R5_RECORD_MIXER_LEFT_CONTROL_1 = 0x0B, R6_RECORD_MIXER_RIGHT_CONTROL_0 = 0x0C, R7_RECORD_MIXER_RIGHT_CONTROL_1 = 0x0D, R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL = 0x0E, R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL = 0x0F, R10_RECORD_MICROPHONE_BIAS_CONTROL = 0x10, R11_ALC_CONTROL_0 = 0x11, R12_ALC_CONTROL_1 = 0x12, R13_ALC_CONTROL_2 = 0x13, R14_ALC_CONTROL_3 = 0x14, R15_SERIAL_PORT_CONTROL_0 = 0x15, R16_SERIAL_PORT_CONTROL_1 = 0x16, R17_CONVERTER_CONTROL_0 = 0x17, R18_CONVERTER_CONTROL_1 = 0x18, R19_ADC_CONTROL = 0x19, R20_LEFT_INPUT_DIGITAL_VOLUME = 0x1A, R21_RIGHT_INPUT_DIGITAL_VOLUME = 0x1B, R22_PLAYBACK_MIXER_LEFT_CONTROL_0 = 0x1C, R23_PLAYBACK_MIXER_LEFT_CONTROL_1 = 0x1D, R24_PLAYBACK_MIXER_RIGHT_CONTROL_0 = 0x1E, R25_PLAYBACK_MIXER_RIGHT_CONTROL_1 = 0x1F, R26_PLAYBACK_LR_MIXER_LEFT_LINE_OUTPUT_CONTROL = 0x20, R27_PLAYBACK_LR_MIXER_RIGHT_LINE_OUTPUT_CONTROL = 0x21, R28_PLAYBACK_LR_MIXER_MONO_OUTPUT_CONTROL = 0x22, R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL = 0x23, R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL = 0x24, R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL = 0x25, R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL = 0x26, R33_PLAYBACK_MONO_OUTPUT_CONTROL = 0x27, R34_PLAYBACK_POP_CLICK_SUPPRESSION = 0x28, R35_PLAYBACK_POWER_MANAGEMENT = 0x29, R36_DAC_CONTROL_0 = 0x2A, R37_DAC_CONTROL_1 = 0x2B, R38_DAC_CONTROL_2 = 0x2C, R39_SERIAL_PORT_PAD_CONTROL = 0x2D, R40_CONTROL_PORT_PAD_CONTROL_0 = 0x2F, R41_CONTROL_PORT_PAD_CONTROL_1 = 0x30, R42_JACK_DETECT_PIN_CONTROL = 0x31, R67_DEJITTER_CONTROL = 0x36, R58_SERIAL_INPUT_ROUTE_CONTROL = 0xF2, R59_SERIAL_OUTPUT_ROUTE_CONTROL = 0xF3, R61_DSP_ENABLE = 0xF5, R62_DSP_RUN = 0xF6, R63_DSP_SLEW_MODES = 0xF7, R64_SERIAL_PORT_SAMPLING_RATE = 0xF8, R65_CLOCK_ENABLE_0 = 0xF9, R66_CLOCK_ENABLE_1 = 0xFA }; /* Audio controller registers */ enum i2s_regs { I2S_DATA_RX_L_REG = 0x00 + AUDIO_BASE, I2S_DATA_RX_R_REG = 0x04 + AUDIO_BASE, I2S_DATA_TX_L_REG = 0x08 + AUDIO_BASE, I2S_DATA_TX_R_REG = 0x0c + AUDIO_BASE, I2S_STATUS_REG = 0x10 + AUDIO_BASE, }; #endif
新建C文件
audio.c
#include <stdio.h> #include <xil_io.h> #include <sleep.h> #include "xiicps.h" #include <xil_printf.h> #include <xparameters.h> #include "xuartps.h" #include "stdlib.h" #include "audio.h" // Parameter definitions #define UART_BASEADDR XPAR_PS7_UART_1_BASEADDR #define GPIO_BASE XPAR_GPIO_0_BASEADDR #define LED_CHANNEL 1 //---------------------------------------------------- // PROTOTYPE FUNCTIONS //---------------------------------------------------- unsigned char IicConfig(unsigned int DeviceIdPS); void AudioPllConfig(); void AudioWriteToReg(unsigned char u8RegAddr, unsigned char u8Data); void AudioConfigureJacks(); void LineinLineoutConfig(); void read_superpose_play();; //Global variables XIicPs Iic; int main(void) { xil_printf("------------------Enter Main Fun------------------------------\r\n"); //Configure the IIC data structure IicConfig(XPAR_XIICPS_0_DEVICE_ID); //Configure the Audio Codec's PLL AudioPllConfig(); //Configure the Line in and Line out ports. //Call LineInLineOutConfig() for a configuration that //同时开启Miz702的两个输入(绿色)和输出(红色) AudioConfigureJacks(); xil_printf("-----------------ADAU1761 configured----------------------------\n\r"); while(1) { //循环采集 播放 read_superpose_play(); } return 0; } // void read_superpose_play(void) { u32 in_left, in_right, out_left, out_right; while (!XUartPs_IsReceiveData(UART_BASEADDR)){ // 采集到的左右声道的数据 in_left = Xil_In32(I2S_DATA_RX_L_REG); in_right = Xil_In32(I2S_DATA_RX_R_REG); out_left = in_left ; out_right = in_right ; //输出 Xil_Out32(I2S_DATA_TX_L_REG, out_left); Xil_Out32(I2S_DATA_TX_R_REG, out_right); //消除人声 // out_right = in_right - out_right ; //Xil_Out32(I2S_DATA_TX_L_REG, out_right ); //Xil_Out32(I2S_DATA_TX_R_REG, out_right); } } /* ---------------------------------------------------------------------------- * * IicConfig() * * ---------------------------------------------------------------------------- * * Initialises the IIC driver by looking up the configuration in the config * table and then initialising it. Also sets the IIC serial clock rate. * ---------------------------------------------------------------------------- */ unsigned char IicConfig(unsigned int DeviceIdPS) { XIicPs_Config *Config; int Status; /* Initialise the IIC driver so that it's ready to use */ // Look up the configuration in the config table Config = XIicPs_LookupConfig(DeviceIdPS); if(NULL == Config) { return XST_FAILURE; } // Initialise the IIC driver configuration Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); if(Status != XST_SUCCESS) { return XST_FAILURE; } //Set the IIC serial clock rate. XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); return XST_SUCCESS; } /* ---------------------------------------------------------------------------- * * AudioPllConfig() * * ---------------------------------------------------------------------------- * * Configures audio codes's internal PLL. With MCLK = 10 MHz it configures the * PLL for a VCO frequency = 49.152 MHz, and an audio sample rate of 48 KHz. * ---------------------------------------------------------------------------- */ void AudioPllConfig() { unsigned char u8TxData[8], u8RxData[6]; int Status; Status = IicConfig(XPAR_XIICPS_0_DEVICE_ID); if(Status != XST_SUCCESS) { xil_printf("\nError initializing IIC"); } // Disable Core Clock AudioWriteToReg(R0_CLOCK_CONTROL, 0x0E); // Write 6 bytes to R1 @ register address 0x4002 u8TxData[0] = 0x40; // Register write address [15:8] u8TxData[1] = 0x02; // Register write address [7:0] u8TxData[2] = 0x02; // byte 6 - M[15:8] u8TxData[3] = 0x71; // byte 5 - M[7:0] u8TxData[4] = 0x02; // byte 4 - N[15:8] u8TxData[5] = 0x3C; // byte 3 - N[7:0] u8TxData[6] = 0x21; // byte 2 - 7 = reserved, bits 6:3 = R[3:0], 2:1 = X[1:0], 0 = PLL operation mode u8TxData[7] = 0x01; // byte 1 - 7:2 = reserved, 1 = PLL Lock, 0 = Core clock enable // Write bytes to PLL Control register R1 @ 0x4002 XIicPs_MasterSendPolled(&Iic, u8TxData, 8, (IIC_SLAVE_ADDR >> 1)); while(XIicPs_BusIsBusy(&Iic)); // Register address set: 0x4002 u8TxData[0] = 0x40; u8TxData[1] = 0x02; // Poll PLL Lock bit do { XIicPs_MasterSendPolled(&Iic, u8TxData, 2, (IIC_SLAVE_ADDR >> 1)); while(XIicPs_BusIsBusy(&Iic)); XIicPs_MasterRecvPolled(&Iic, u8RxData, 6, (IIC_SLAVE_ADDR >> 1)); while(XIicPs_BusIsBusy(&Iic)); } while((u8RxData[5] & 0x02) == 0); // while not locked AudioWriteToReg(R0_CLOCK_CONTROL, 0x0F); // 1111 // bit 3: CLKSRC = PLL Clock input // bits 2:1: INFREQ = 1024 x fs // bit 0: COREN = Core Clock enabled } /* ---------------------------------------------------------------------------- * * AudioWriteToReg * * ---------------------------------------------------------------------------- * * Function to write one byte (8-bits) to one of the registers from the audio * controller. * ---------------------------------------------------------------------------- */ void AudioWriteToReg(unsigned char u8RegAddr, unsigned char u8Data) { unsigned char u8TxData[3]; u8TxData[0] = 0x40; u8TxData[1] = u8RegAddr; u8TxData[2] = u8Data; XIicPs_MasterSendPolled(&Iic, u8TxData, 3, (IIC_SLAVE_ADDR >> 1)); while(XIicPs_BusIsBusy(&Iic)); } /* ---------------------------------------------------------------------------- * * AudioConfigureJacks() * * ---------------------------------------------------------------------------- * * Configures audio codes's various mixers, ADC's, DAC's, and amplifiers to * accept stereo input from line in and push stereo output to line out. * ---------------------------------------------------------------------------- */ void AudioConfigureJacks() { //AudioWriteToReg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x01); //enable mixer 1 AudioWriteToReg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x0f); AudioWriteToReg(R5_RECORD_MIXER_LEFT_CONTROL_1, 0x07); //unmute Left channel of line in into mxr 1 and set gain to 6 db AudioWriteToReg(R6_RECORD_MIXER_RIGHT_CONTROL_0, 0x0f); //enable mixer 2 AudioWriteToReg(R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL,0x03); AudioWriteToReg(R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL,0x03); AudioWriteToReg(R10_RECORD_MICROPHONE_BIAS_CONTROL, 0x01); AudioWriteToReg(R7_RECORD_MIXER_RIGHT_CONTROL_1, 0x07); //unmute Right channel of line in into mxr 2 and set gain to 6 db AudioWriteToReg(R19_ADC_CONTROL, 0x13); //enable ADCs AudioWriteToReg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x21); //unmute Left DAC into Mxr 3; enable mxr 3 AudioWriteToReg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x41); //unmute Right DAC into Mxr4; enable mxr 4 AudioWriteToReg(R26_PLAYBACK_LR_MIXER_LEFT_LINE_OUTPUT_CONTROL, 0x05); //unmute Mxr3 into Mxr5 and set gain to 6db; enable mxr 5 AudioWriteToReg(R27_PLAYBACK_LR_MIXER_RIGHT_LINE_OUTPUT_CONTROL, 0x11); //unmute Mxr4 into Mxr6 and set gain to 6db; enable mxr 6 AudioWriteToReg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, 0xFF);//Mute Left channel of HP port (LHP) AudioWriteToReg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, 0xFF); //Mute Right channel of HP port (LHP) //AudioWriteToReg(R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL, 0xE6); //set LOUT volume (0db); unmute left channel of Line out port; set Line out port to line out mode //AudioWriteToReg(R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL, 0xE6); // set ROUT volume (0db); unmute right channel of Line out port; set Line out port to line out mode AudioWriteToReg(R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL, 0xFE); //set LOUT volume (0db); unmute left channel of Line out port; set Line out port to line out mode AudioWriteToReg(R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL, 0xFE); // set ROUT volume (0db); unmute right channel of Line out port; set Line out port to line out mode AudioWriteToReg(R35_PLAYBACK_POWER_MANAGEMENT, 0x03); //enable left and right channel playback (not sure exactly what this does...) AudioWriteToReg(R36_DAC_CONTROL_0, 0x03); //enable both DACs AudioWriteToReg(R58_SERIAL_INPUT_ROUTE_CONTROL, 0x01); //Connect I2S serial port output (SDATA_O) to DACs AudioWriteToReg(R59_SERIAL_OUTPUT_ROUTE_CONTROL, 0x01); //connect I2S serial port input (SDATA_I) to ADCs AudioWriteToReg(R65_CLOCK_ENABLE_0, 0x7F); //Enable clocks AudioWriteToReg(R66_CLOCK_ENABLE_1, 0x03); //Enable rest of clocks } /* ---------------------------------------------------------------------------- * * LineinLineoutConfig() * * ---------------------------------------------------------------------------- * * Configures Line-In input, ADC's, DAC's, Line-Out and HP-Out. * ---------------------------------------------------------------------------- */ void LineinLineoutConfig() { AudioWriteToReg(R17_CONVERTER_CONTROL_0, 0x05);//48 KHz AudioWriteToReg(R64_SERIAL_PORT_SAMPLING_RATE, 0x05);//48 KHz AudioWriteToReg(R19_ADC_CONTROL, 0x13); AudioWriteToReg(R36_DAC_CONTROL_0, 0x03); AudioWriteToReg(R35_PLAYBACK_POWER_MANAGEMENT, 0x03); AudioWriteToReg(R58_SERIAL_INPUT_ROUTE_CONTROL, 0x01); AudioWriteToReg(R59_SERIAL_OUTPUT_ROUTE_CONTROL, 0x01); AudioWriteToReg(R65_CLOCK_ENABLE_0, 0x7F); AudioWriteToReg(R66_CLOCK_ENABLE_1, 0x03); AudioWriteToReg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x01); AudioWriteToReg(R5_RECORD_MIXER_LEFT_CONTROL_1, 0x05);//0 dB gain AudioWriteToReg(R6_RECORD_MIXER_RIGHT_CONTROL_0, 0x01); AudioWriteToReg(R7_RECORD_MIXER_RIGHT_CONTROL_1, 0x05);//0 dB gain AudioWriteToReg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x21); AudioWriteToReg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x41); AudioWriteToReg(R26_PLAYBACK_LR_MIXER_LEFT_LINE_OUTPUT_CONTROL, 0x03);//0 dB AudioWriteToReg(R27_PLAYBACK_LR_MIXER_RIGHT_LINE_OUTPUT_CONTROL, 0x09);//0 dB AudioWriteToReg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, 0xE7);//0 dB AudioWriteToReg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, 0xE7);//0 dB AudioWriteToReg(R31_PLAYBACK_LINE_OUTPUT_LEFT_VOLUME_CONTROL, 0xE6);//0 dB AudioWriteToReg(R32_PLAYBACK_LINE_OUTPUT_RIGHT_VOLUME_CONTROL, 0xE6);//0 dB }
下载完成后测试效果:采集的音频信号,再次输出
红色的线是音频输入,白色的是耳机输出
相关文章推荐
- 手把手带你画一个 时尚仪表盘 Android 自定义View
- 详解Android中AsyncTask的使用
- vertx3 bug
- 论-多租户技术
- 关于美工设计的图如何更好的使用在手机上面显示
- spring配置笔记
- GLSL学习笔记---之内建变量2
- 安装SQL2005提示“SQL Server 2005 COM+ 目录要求”警告 解决方法
- python gevent
- C 读取HTK生成的MFCC文件
- 手把手带你做一个超炫酷loading成功动画view Android自定义view
- quick 3.3 按钮多次点击出现问题的解决
- 类方法和实例方法的区别
- VS,C#--拼图小游戏
- Install WPF Theme
- 杭电2074 叠筐 二维数组
- Android UI-仿微信底部导航栏布局
- 2016年2月最新外牌转沪牌经历
- asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler” <转>
- android中方法id超过65536官方解决办法