您的位置:首页 > 其它

【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下载

建立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
}


下载完成后测试效果:采集的音频信号,再次输出

红色的线是音频输入,白色的是耳机输出

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: