【ZYNQ-7000开发之十六】音频信号处理

本编文章将使用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
}

下载完成后测试效果:采集的音频信号,再次输出
红色的线是音频输入,白色的是耳机输出
这里写图片描述

猜你喜欢

转载自blog.csdn.net/RZJMPB/article/details/50897563