|
|
View previous topic :: View next topic |
Author |
Message |
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
dspic audio dac + DMA |
Posted: Fri Apr 05, 2024 3:43 pm |
|
|
Hello,
I have setup the dspic33fj64gp802 audio dac to work with continuous ping pong DMA playing wav from SD card.
Code: |
#bank_dma
int16 AudioBufferA[256];
#bank_dma
int16 AudioBufferB[256];
setup_dma(0, DMA_OUT_DACL, DMA_WORD);
dma_start(0, DMA_PING_PONG,AudioBufferA,AudioBufferB,255);
DAC1LDAT=0;
|
and then there is the code for filling the 2 buffers.
The problem is the the DMA feeds the DAC with data all the time and the file plays very fast.
I have to use "while(ldac_full);" to wait for the DAC buffer to empty but then what is the meaning of using DMA?
When I use "while(ldac_full);" the file plays ok but with glitches on each data refill.
What is the proper way to sync the DMA to the wav sampling frequency?
Thanks for any ideas! _________________ George. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9232 Location: Greensville,Ontario
|
|
Posted: Fri Apr 05, 2024 4:27 pm |
|
|
off the top of head, never having used DMAed PIC or WAV files....
I'd think you'd read the wav file, extract the speed (44.1 KHz ? ) and somehow use that to control the speed of the DAC output ?
I bet there's 15 different 'wav formats' NOT just the 44.1 speed, heck it has to be 30+ years old now !!! |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Apr 05, 2024 5:09 pm |
|
|
When I use the DAC without DMA I just wait for the buffer to empty then fill in some bytes and it is working good.
I just want to test the DMA to free my CPU but I can not see how to "sync" the DMA with the DAC. It keeps sending data.
I thought that since the clock divider in the DAC1CON register is set, the DAC knows how often to ask for data as it is done when "manual feeding data" when the buffer in not full. _________________ George. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Sun Apr 07, 2024 5:21 am |
|
|
The DAC has 4 word deep FiFo.
My DMA buffer is 256 16bit words because each sector read from the SD card is 512 bytes.
Is the DMA supposed to feed the DAC from this buffer 4 words at the time until the buffer is empty and then generate an interrupt?
I really cannot understand how to sync the DMA with the DAC. _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Apr 08, 2024 2:21 am |
|
|
First have you read 70211B.pdf, This is the family reference manual for
the DAC?.
Now the DMA can be programmed to send data when the DAC FIFO is
less than full or empty. Either should work the same. The speed of output
is setup in the DAC, by the DAC clock rate, which should be 256* the
specified rate in the .wav file. So 11.2896MHz for a 44.1KHz wav.
It sounds as if you may have the DAC setup with a faster clock than is
required for the specific wav file, and this is only showing when the data
is being automatically loaded by the DMA, |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Mon Apr 08, 2024 3:20 am |
|
|
yes I have read the 70211B.pdf
I have to tell you that I have an audio device playing wav files from SD for many years now. The DAC clock rate is set for 22050 and I just wait for the buffer to empty and fill with data untill it is full like this:
Code: |
//------------------- play 1 sector --------------------------
for (count=1;count<=256;++count){
low_byte=spi_read(0xFF); //read low byte from SD
high_byte=spi_read(0xFF); //read high byte from SD
audio=make16(high_byte,low_byte);
while(rdac_full);
DAC1RDAT = audio;
}
//--------------------- end of 1 sector ----------------------
|
The code above uses continuous read command from SD card with SPI and I feed the DAC with data when it asks for.
So yes I know that since I set the DAC clock rate, it asks for data when it wants to.
Now I am using Brush Electronics FAT filesystem and I have to read the whole sector of 512 bytes, create 256 words and feed the DAC.
This delay is causing glitches of course and I am trying to use DMA in continuous ping mode mode with 2 buffers. Read from SD and fill one buffer while the other is feeding the DAC
I thought that since the DAC clock rate is set, when there is data in the DMA buffer (256 words each buffer) then the DAC will use this data and then create an interrupt. Or the DMA will create an interrupt?
I have tried both but no luck.
Now I have this as a test:
Code: |
result = f_read(&fsrc, Buffer, 512, &br);
p=0;
for (count=0;count<256;++count){
low_byte=Buffer[p];
high_byte=Buffer[p+1];
p+=2;
AudioBufferA[count]=make16(high_byte,low_byte);
while(!DAC1LIF);
DAC1LIF=0;
}
result = f_read(&fsrc, Buffer, 512, &br);
p=0;
for (count=0;count<256;++count){
low_byte=Buffer[p];
high_byte=Buffer[p+1];
p+=2;
AudioBufferB[count]=make16(high_byte,low_byte);
while(!DAC1LIF);
DAC1LIF=0;
}
|
It is working with glitches on each f_read but I do not like it either way because I am waiting for the DAC interrupt within the loop.
If I remove the
Code: |
while(!DAC1LIF);
DAC1LIF=0;
|
then the files plays fast.
If I need to use the DAC interrupts for every 4 words then there is no point in using DMA. The point is to fill with 256 words and do nothing else until this is finished.
I think that I should fill the buffers with data, then sit there do NOTHING and wait for interrupt (DMA or DAC?) and just refill the buffers.
Sorry for the long post and thanks for any ideas. _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Apr 08, 2024 8:58 am |
|
|
Good.
I suggest you try changing the configuration of the DAC interrupt. You
don't show how this is configured (for buffer empty, or buffer has space),
so whichever you have, try the other.
I notice in the family reference manual, it specifically says that you would
use two dma channels to handle both buffers. I think your configuration
will result in it running at double speed.
Post your configuration for the DAC. I think to work as you are, you need to
disable the right channel DAC, and interrupt. I think what is happening
is you are getting an interrupt from both channels, so the first word of
data gets fed to the left channel, then the second word to the right. Result
double the output rate from the buffers, and double the frequency on
the output. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|