• 0
Mehdim

How to use Audio on Zybo board

Question

Hello guys;

Can you refer me to a quick guide about how to use Audio signal on ZYbo board?

I just want to know if there is any simple tutorial about how to get data from audio jack and have in on Arm side.

Appreciate your comments in advance.

Share this post


Link to post
Share on other sites

Recommended Posts

  • 0

I have tried this IP core in Zybo, but it seems it doesn’t work. I can try to debug the IP, but if you guys have any hint or you can refer me to a working IP core for this module, it would very appreciated.

Thanks you.

Share this post


Link to post
Share on other sites
  • 0

Thanks for the reply,

i think it is for the standalone OS. I have tried to run these code, but i encountered some errors

 when i was trying to lunch SDK from Vivaoi:

and when Debugging SDK:

 

do you guys have any similar experience with this code?

 

Capture.JPG

Capture2.JPG

Share this post


Link to post
Share on other sites
  • 0

Hi Mehdim,

I would say that the Instructable posted above is your best bet for getting the audio to work. There are only two parts to getting it to work: First configuring the audio codec with I2C, and then receiving the audio data through I2S. I did this all in hardware in my Nexys Video Looper Demo, but this doesn't interface with an ARM processor. It might give you a basic idea of how the communication works though.

Share this post


Link to post
Share on other sites
  • 0

Thank you for the response;

Yeah I have play with example for days, the thing is that I can write config to ADC through I2C and confirm them by readying values, but when I try to receive from I2S, I get nothing.

Do you have any hint or comment for debugging this issues?

 

Share this post


Link to post
Share on other sites
  • 0

I'm afraid I can't be of much help here. If your I2C is confirmed working, then the only thing to look at is the I2S controller. Make sure your pins are mapped out correctly in the xdc contraints file. Maybe check out the i2s_ctl.vhd file in the looper demo and compare it to the one from the instructables. I haven't gone through the instructable so I don't know what could be wrong, but I can try it out when I find time.

Share this post


Link to post
Share on other sites
  • 0

Does anybocy here know the functionality of CTRL and onoff port in serialeffect IP core?

When I enable “onoff” port, a noise will be generated at output of voice

Share this post


Link to post
Share on other sites
  • 0

Hello again guys,

I am trying to simplify the project on

http://www.instructables.com/id/Digital-Filters-on-Zybo-Board/?ALLSTEPS

and run it on a standalone OS. So I just added “axi_i2s_adi_0” IP core to design and mapped IOs to audio codec ports.

The issue is that right now I can capture data from microphone or line-in and see signal on “SDATA_I” port on oscilloscope; but when I try to send this data to I2S, I cannot see” SDATA_O” and it stuck on 0; and therefore I have no audio on “HPH out”

VHeGVp1.jpg

 

une7KTm.jpg

Do you have any comment or hint on this?

Share this post


Link to post
Share on other sites
  • 0

Hello again guys;

Finally I found the solution; to  me there is something wrong with the IP core at http://www.instructables.com/id/Digital-Filters-on-Zybo-Board/?ALLSTEPS

As a solution, I have download ip core entitled “zed_audio_ctrl_0” from

http://embeddedcentric.com/adc-dac-and-digital-audio-processing/

then all you have to do is to configure the codec from I2C and then easily read and write from\to I2S channel by

                     in_left = Xil_In32(I2S_DATA_RX_L_REG);

                     in_right = Xil_In32(I2S_DATA_RX_R_REG);

 

                     Xil_Out32(I2S_DATA_TX_L_REG, in_left);

                     Xil_Out32(I2S_DATA_TX_R_REG, in_right);95d819f.jpg

 

 

if it helps and i can be of more help please let me know

 

Share this post


Link to post
Share on other sites
  • 0

Hi!

Could you be so kind and give some further information about your implementation?

For my university course we have to implement a wav-file player and this is my first project after doing the zynq book exercises. Normally we use the zedboard in the course, but i have the zybo at home, and would like to use it!

I have some resources how to configure the zedboard audio chip, but according to https://forums.xilinx.com/t5/Welcome-Join/ZYBO-I2S-BCLK/td-p/433246

post #7, using the one on zybo is much more complex.

I already build the block design like yours and put the constraints file together (maybe do you know if the zybo has write protection feature for sd card?).

But for the configuration i would need some help, maybe you could provide me with a c source file!

 

Thank you in advance

Alex

Share this post


Link to post
Share on other sites
  • 0

Hello Alex;

Really sorry for the late response;

Here you can find some codes that I used:

/* 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
 

XIicPs Iic;                              /* Instance of the IIC Device */

XNco Nco;

 

u8 audio_flag;

int AudioInitialize(u16 timerID,  u16 iicID, u32 i2sAddr)

{

                int Status;

                XIicPs_Config *Config;

                u32 i2sClkDiv;


                TimerInitialize(timerID);

                /*

                 * Initialize the IIC driver so that it's ready to use

                 * Look up the configuration in the config table,

                 * then initialize it.

                 */

                Config = XIicPs_LookupConfig(iicID);

                if (NULL == Config) {

                                return XST_FAILURE;

                }

 

                Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

 

                /*

                 * Perform a self-test to ensure that the hardware was built correctly.

                 */

                Status = XIicPs_SelfTest(&Iic);

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

                /*

                 * Set the IIC serial clock rate.

                 */

                Status = XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

 

                /*

                 * Write to the SSM2603 audio codec registers to configure the device. Refer to the

                 * SSM2603 Audio Codec data sheet for information on what these writes do.

                 */

                Status = AudioRegSet(&Iic, 15, 0b000000000); //Perform Reset

                TimerDelay(75000);

                Status |= AudioRegSet(&Iic, 6, 0b000110000); //Power up

                Status |= AudioRegSet(&Iic, 0, 0b000010111);

                Status |= AudioRegSet(&Iic, 1, 0b000010111);

                Status |= AudioRegSet(&Iic, 2, 0b101111001);

                Status |= AudioRegSet(&Iic, 4, 0b000010000);

                Status |= AudioRegSet(&Iic, 5, 0b000000000);

                Status |= AudioRegSet(&Iic, 7, 0b000001010); //Changed so Word length is 24

                Status |= AudioRegSet(&Iic, 8, 0b000000000); //Changed so no CLKDIV2

                TimerDelay(75000);

                Status |= AudioRegSet(&Iic, 9, 0b000000001);

                Status |= AudioRegSet(&Iic, 6, 0b000100000);

 

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

/*

                i2sClkDiv = 1; //Set the BCLK to be MCLK / 4

                i2sClkDiv = i2sClkDiv | (31 << 16); //Set the LRCLK's to be BCLK / 64

 

                Xil_Out32(i2sAddr + I2S_CLK_CTRL_REG, i2sClkDiv); //Write clock div register

*/

                return XST_SUCCESS;

}

/* ------------------------------------------------------------ */

 

int AudioRegSet(XIicPs *IIcPtr, u8 regAddr, u16 regData)

{

                int Status;

                u8 SendBuffer[2];

 

                SendBuffer[0] = regAddr << 1;

                SendBuffer[0] = SendBuffer[0] | ((regData >> 8) & 0b1);

 

                SendBuffer[1] = regData & 0xFF;

 

                Status = XIicPs_MasterSendPolled(IIcPtr, SendBuffer,

                                                                 2, IIC_SLAVE_ADDR);

                if (Status != XST_SUCCESS) {

                                //xil_printf("IIC send failed\n\r");

                                return XST_FAILURE;

                }

                /*

                 * Wait until bus is idle to start another transfer.

                 */

                while (XIicPs_BusIsBusy(IIcPtr)) {

                                /* NOP */

                }

                return XST_SUCCESS;

}

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioSampleR(u32 *data, u32 number)

{

u32 i;

for(i=0;i<number;i++)

{

                data = Xil_In32(I2S_DATA_RX_R_REG);

}

return;

}

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioSampleL(u32 *data, u32 number)

{

                u32 i;

                for(i=0;i<number;i++)

                {

                                data = Xil_In32(I2S_DATA_RX_L_REG);

                }

                return;

}

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioPlayR(u32 *data, u32 number)

{

u32 i;

for(i=0;i<number;i++)

{

                Xil_Out32(I2S_DATA_TX_R_REG, data);

}

return;

}

 

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioPlayL(u32 *data, u32 number)

{

u32 i;

for(i=0;i<number;i++)

{

                Xil_Out32(I2S_DATA_TX_L_REG, data);

}

return;

}

 

 

Hope it helps. If you have any further question shoot me an email at mehdim@umich.edu

Edited by JColvin
condensed white space in post for compactness

Share this post


Link to post
Share on other sites
  • 0
On 6/23/2016 at 11:24 AM, Mehdim said:

Hello Alex;

Really sorry for the late response;

Here you can find some codes that I used:

/* 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
 

XIicPs Iic;                              /* Instance of the IIC Device */

XNco Nco;

 

u8 audio_flag;

int AudioInitialize(u16 timerID,  u16 iicID, u32 i2sAddr)

{

                int Status;

                XIicPs_Config *Config;

                u32 i2sClkDiv;


                TimerInitialize(timerID);

                /*

                 * Initialize the IIC driver so that it's ready to use

                 * Look up the configuration in the config table,

                 * then initialize it.

                 */

                Config = XIicPs_LookupConfig(iicID);

                if (NULL == Config) {

                                return XST_FAILURE;

                }

 

                Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

 

                /*

                 * Perform a self-test to ensure that the hardware was built correctly.

                 */

                Status = XIicPs_SelfTest(&Iic);

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

                /*

                 * Set the IIC serial clock rate.

                 */

                Status = XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

 

                /*

                 * Write to the SSM2603 audio codec registers to configure the device. Refer to the

                 * SSM2603 Audio Codec data sheet for information on what these writes do.

                 */

                Status = AudioRegSet(&Iic, 15, 0b000000000); //Perform Reset

                TimerDelay(75000);

                Status |= AudioRegSet(&Iic, 6, 0b000110000); //Power up

                Status |= AudioRegSet(&Iic, 0, 0b000010111);

                Status |= AudioRegSet(&Iic, 1, 0b000010111);

                Status |= AudioRegSet(&Iic, 2, 0b101111001);

                Status |= AudioRegSet(&Iic, 4, 0b000010000);

                Status |= AudioRegSet(&Iic, 5, 0b000000000);

                Status |= AudioRegSet(&Iic, 7, 0b000001010); //Changed so Word length is 24

                Status |= AudioRegSet(&Iic, 8, 0b000000000); //Changed so no CLKDIV2

                TimerDelay(75000);

                Status |= AudioRegSet(&Iic, 9, 0b000000001);

                Status |= AudioRegSet(&Iic, 6, 0b000100000);

 

                if (Status != XST_SUCCESS) {

                                return XST_FAILURE;

                }

/*

                i2sClkDiv = 1; //Set the BCLK to be MCLK / 4

                i2sClkDiv = i2sClkDiv | (31 << 16); //Set the LRCLK's to be BCLK / 64

 

                Xil_Out32(i2sAddr + I2S_CLK_CTRL_REG, i2sClkDiv); //Write clock div register

*/

                return XST_SUCCESS;

}

/* ------------------------------------------------------------ */

 

int AudioRegSet(XIicPs *IIcPtr, u8 regAddr, u16 regData)

{

                int Status;

                u8 SendBuffer[2];

 

                SendBuffer[0] = regAddr << 1;

                SendBuffer[0] = SendBuffer[0] | ((regData >> 8) & 0b1);

 

                SendBuffer[1] = regData & 0xFF;

 

                Status = XIicPs_MasterSendPolled(IIcPtr, SendBuffer,

                                                                 2, IIC_SLAVE_ADDR);

                if (Status != XST_SUCCESS) {

                                //xil_printf("IIC send failed\n\r");

                                return XST_FAILURE;

                }

                /*

                 * Wait until bus is idle to start another transfer.

                 */

                while (XIicPs_BusIsBusy(IIcPtr)) {

                                /* NOP */

                }

                return XST_SUCCESS;

}

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioSampleR(u32 *data, u32 number)

{

u32 i;

for(i=0;i<number;i++)

{

                data = Xil_In32(I2S_DATA_RX_R_REG);

}

return;

}

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioSampleL(u32 *data, u32 number)

{

                u32 i;

                for(i=0;i<number;i++)

                {

                                data = Xil_In32(I2S_DATA_RX_L_REG);

                }

                return;

}

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioPlayR(u32 *data, u32 number)

{

u32 i;

for(i=0;i<number;i++)

{

                Xil_Out32(I2S_DATA_TX_R_REG, data);

}

return;

}

 

 

//--------------------------------------------------------------------------------------------------------------------------------------

void AudioPlayL(u32 *data, u32 number)

{

u32 i;

for(i=0;i<number;i++)

{

                Xil_Out32(I2S_DATA_TX_L_REG, data);

}

return;

}

 

 

Hope it helps. If you have any further question shoot me an email at mehdim@umich.edu

 

Edited by JColvin
condensed white space in post for compactness

Share this post


Link to post
Share on other sites
  • 0

Hi Mehdim, 

I'm trying to get the ZYBO Audio codec up and running using only hardware i.e. only vhdl code. I'm feeding audio input through aux cable from my mobile phone. And I want to hear the same audio out from Headphones jack. So far I'm able to hear a very feeble sound. This has something to do with the volume control registers. Can you pls tell me which register am I entering wrong?

reg 6   - 000010010 
reg 15 - 000000000
reg 0   - 000111111
reg 1 -   000111111
reg 2 -   001111111
reg 3 -   000000000
reg 4 -   000010000
reg 5 -   000000000
reg 7 -   001001010
reg 8 -  000000000
reg 9 -  000000001
reg 6 -  000000010

Thanks. 

Share this post


Link to post
Share on other sites
  • 0

I just posted a DMA audio demo for the zybo and the volume seems to be right. The register assignments I used to initialize the codec are below.

fnAudioWriteToReg(R15_SOFTWARE_RESET, 0b000000000);
fnAudioWriteToReg(R6_POWER_MGMT, 0b000110000);
fnAudioWriteToReg(R0_LEFT_ADC_VOL, 0b000010111);
fnAudioWriteToReg(R1_RIGHT_ADC_VOL, 0b000010111);
fnAudioWriteToReg(R2_LEFT_DAC_VOL, 0b101111001);
fnAudioWriteToReg(R3_RIGHT_DAC_VOL, 0b101111001);
fnAudioWriteToReg(R4_ANALOG_PATH, 0b000000000);
fnAudioWriteToReg(R5_DIGITAL_PATH, 0b000000000);
fnAudioWriteToReg(R7_DIGITAL_IF, 0b000001010);
fnAudioWriteToReg(R8_SAMPLE_RATE, 0b000000000);
fnAudioWriteToReg(R9_ACTIVE, 0b000000001);
fnAudioWriteToReg(R6_POWER_MGMT, 0b000100000);

Demo can be found here https://github.com/Digilent/ZYBO/tree/master/Projects/dma

It uses microblaze but may still be useful designing for HDL

-Sam

Share this post


Link to post
Share on other sites
  • 0
1 hour ago, sLowe said:

 

 

Hi Sam, 

In your project are you also feeding audio input through LINE IN jack and hearing it back from the Head phones jack on Zedboard?

Edited by Axe

Share this post


Link to post
Share on other sites
  • 0

Yes, I put in the ability to record from line in or headphone in. Although before I start the transfer from Line in, i call 

fnAudioWriteToReg(R4_ANALOG_PATH, 0b000010010);
fnAudioWriteToReg(R5_DIGITAL_PATH, 0b000000000);

Edited by sLowe

Share this post


Link to post
Share on other sites
  • 0

Hi Sam,

I did not understand why is LRHPBOTH and RLHPBOTH both enabled i.e bit 8 is made 1 in Reg2 and Reg3? could you please explain. 

Share this post


Link to post
Share on other sites
  • 0

That is a good catch! Thinking about it, this just sets both of the volume registers to the same value twice. Since I want  them at the same value, the write to reg3 is not needed. This shouldn't cause any problems with the function of the design though. Ill probably go back and change it to assign them separately in case someone in the future wants different channel volumes.

Thanks!

-Sam

Share this post


Link to post
Share on other sites
  • 0

Hi Sam,

I'm trying to create your dma project. I was able to create project and build it using tcl script. I do not know how to import the software side of it. Could you please explain in brief on what I should do in sdk to replicate your project? I see that you have given all necessary source files in github but I don't know how to use them appropriately. Thanks!

 

error.PNG

Edited by Axe

Share this post


Link to post
Share on other sites
  • 0

Hey Axe, I think the following flow will get your program running using the bitstream you just created

1. export your hardware by selecting File->export->export hardware make sure include bitstream is checked and press ok

2. launch SDK by selecting file launch SDK and press ok

3. Select file->new->application project name the project then click next

4. select hello world from the list and let sdk generate a hello world project

5. delete your helloworld.c file

6. copy in the .c and .h files from the guthub sdk folder (you can drag and drop)

7. program the FPGA and run your project .elf file on system debugger

However if you are fine using the hardware platform shipped with the project (it should be the same) you can just import the sdk folder from the github as a workspace into SDK and follow the steps on this guide. https://reference.digilentinc.com/learn/programmable-logic/tutorials/zybo-dma-audio-demo/start

-Sam

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now