Reply by Joe Chisolm May 5, 20172017-05-05
On Wed, 03 May 2017 12:22:15 +0200, pozz wrote:

> I need to reproduce a short audio stream with a Cortex-M0+ MCU (it's SAM > D21E from Atmel/Microchip). The audio bitstream will be stored in an > external SPI Flash memory (I need to manage many short audio streams, so > the internal Flash memory is not sufficient). > SAMD21 features DAC, SPI and DMA. > > The audio will not be high-fidelity. 8 bits at 8kHz sampling frequency > is enough. I didn't make many tests, but I think I can use streams with > lower bitrates. > > Here the problem isn't the compress ratio, i.e. reducing the memory > requirements to store all the streams, but to arrange an effective way > to transfer samples from external Flash to DAC. > > The simplest method I think is to configure the SPI transfer rate > exactly at 8kHz, by calibrating the SPI clock (I think I can do): every > 125us=8kHz a new sample is received, an interrupt is raised and the > value is moved to the DAC register. > > The only problem I see for this method is that the MCU must be > interrupted every 125us. The MCU will run at 48MHz and should manage a > serial RS485 38400bps (260us) too. > > One solution to free the MCU is to use the DMA peripheral, but I never > used it in the past. Will it be possible to use DMA to automatically > move the byte received from SPI to DAC register, without interrupting > the normal execution code? > > Of course this "direct method" (from external memory to DAC output, > without processing) can be done with uncompressed 8-bits samples audio > streams. > If I need to reduce the memory requirements, I need to use a compress > (even simple) algorithm... there are many. Anyway in this case I can't > move the samples from SPI to DAC, because I need to uncompress the samples. > > Is it possible to use a normal (not DSP) Cortex-M0+ MCU to play a > compressed audio stream? If yes, what is the best method to: > - arrange the load of compressed stream from external memory > - uncompress the input stream > - move the uncompressed samples to DAC > Here the SPI input transfer rate is not perfectly syncronized with the > DAC output transfer rate (fixed at 64kHz). I think I have to manage a > FIFO buffer with two thresholds. When the FIFO is full over first > threshold, the SPI transfer is stopped. When the FIFO is empty lower > than the second threshold, the SPI transfer is started again. > > Are there some examples to study?
I know the M3 supports peripheral to peripheral DMA but I'm not sure about the M0. It's not that hard to set up the channels once you kind of get your head around it. Transfer chaining makes it a lot easier. SPI read is a little of an issue as you have to keep the DMA controller issuing SCLKs. If the M0 will do p to p you should be able to setup the DMA descriptors, fire and forget until you get the final transfer complete interrupt. -- Chisolm Republic of Texas
Reply by John Speth May 3, 20172017-05-03
Pumping audio from storage to speaker is a matter of keeping the 
pipeline full so the the output pointer is always ahead of the input 
pointer.  You'll need some amount of buffer memory for that.  Start by 
loading your buffer, and when it reaches some comfortable level of 
playable data, start outputting it.  While you're waiting for the output 
mechanism to drain your buffer to some tolerably low level, you can be 
filling the pipe from SPI memory.

DMA varies among MCUs so only you will know about that.  I suspect DMA 
will be the key to your success unless your MCU is extremely fast or 
unloaded, in whcih case you might not need it.  I suggest you use it if 
you have it.

I've had good results using mu-law compression when fidelity 
expectations are low.  You can find mu-law codec code on the web.  You 
might find that compression is not needed.  Large SPI memory devices are 
cheap and PCM wave files aren't that big so storage limitations should 
be ok for you (YMMV, of course).

JJS
Reply by Jack May 3, 20172017-05-03
Il giorno mercoledì 3 maggio 2017 12:22:22 UTC+2, pozz ha scritto:
> I need to reproduce a short audio stream with a Cortex-M0+ MCU (it's SAM > D21E from Atmel/Microchip). The audio bitstream will be stored in an > external SPI Flash memory (I need to manage many short audio streams, so > the internal Flash memory is not sufficient). > SAMD21 features DAC, SPI and DMA. > > The audio will not be high-fidelity. 8 bits at 8kHz sampling frequency > is enough. I didn't make many tests, but I think I can use streams with > lower bitrates. > > Here the problem isn't the compress ratio, i.e. reducing the memory > requirements to store all the streams, but to arrange an effective way > to transfer samples from external Flash to DAC. > > The simplest method I think is to configure the SPI transfer rate > exactly at 8kHz, by calibrating the SPI clock (I think I can do): every > 125us=8kHz a new sample is received, an interrupt is raised and the > value is moved to the DAC register. > > The only problem I see for this method is that the MCU must be > interrupted every 125us. The MCU will run at 48MHz and should manage a > serial RS485 38400bps (260us) too. > > One solution to free the MCU is to use the DMA peripheral, but I never > used it in the past. Will it be possible to use DMA to automatically > move the byte received from SPI to DAC register, without interrupting > the normal execution code? > > Of course this "direct method" (from external memory to DAC output, > without processing) can be done with uncompressed 8-bits samples audio > streams. > If I need to reduce the memory requirements, I need to use a compress > (even simple) algorithm... there are many. Anyway in this case I can't > move the samples from SPI to DAC, because I need to uncompress the samples. > > Is it possible to use a normal (not DSP) Cortex-M0+ MCU to play a > compressed audio stream? If yes, what is the best method to: > - arrange the load of compressed stream from external memory > - uncompress the input stream > - move the uncompressed samples to DAC > Here the SPI input transfer rate is not perfectly syncronized with the > DAC output transfer rate (fixed at 64kHz). I think I have to manage a > FIFO buffer with two thresholds. When the FIFO is full over first > threshold, the SPI transfer is stopped. When the FIFO is empty lower > than the second threshold, the SPI transfer is started again. > > Are there some examples to study?
mbed.org has a mp3 player that works on M0+. Use DMA to fill the audio buffer from SPI. Maybe You may also use the DMA to feed the DAC. Bye Jack
Reply by pozz May 3, 20172017-05-03
I need to reproduce a short audio stream with a Cortex-M0+ MCU (it's SAM 
D21E from Atmel/Microchip).  The audio bitstream will be stored in an 
external SPI Flash memory (I need to manage many short audio streams, so 
the internal Flash memory is not sufficient).
SAMD21 features DAC, SPI and DMA.

The audio will not be high-fidelity. 8 bits at 8kHz sampling frequency 
is enough. I didn't make many tests, but I think I can use streams with 
lower bitrates.

Here the problem isn't the compress ratio, i.e. reducing the memory 
requirements to store all the streams, but to arrange an effective way 
to transfer samples from external Flash to DAC.

The simplest method I think is to configure the SPI transfer rate 
exactly at 8kHz, by calibrating the SPI clock (I think I can do): every 
125us=8kHz a new sample is received, an interrupt is raised and the 
value is moved to the DAC register.

The only problem I see for this method is that the MCU must be 
interrupted every 125us. The MCU will run at 48MHz and should manage a 
serial RS485 38400bps (260us) too.

One solution to free the MCU is to use the DMA peripheral, but I never 
used it in the past. Will it be possible to use DMA to automatically 
move the byte received from SPI to DAC register, without interrupting 
the normal execution code?

Of course this "direct method" (from external memory to DAC output, 
without processing) can be done with uncompressed 8-bits samples audio 
streams.
If I need to reduce the memory requirements, I need to use a compress 
(even simple) algorithm... there are many. Anyway in this case I can't 
move the samples from SPI to DAC, because I need to uncompress the samples.

Is it possible to use a normal (not DSP) Cortex-M0+ MCU to play a 
compressed audio stream? If yes, what is the best method to:
- arrange the load of compressed stream from external memory
- uncompress the input stream
- move the uncompressed samples to DAC
Here the SPI input transfer rate is not perfectly syncronized with the 
DAC output transfer rate (fixed at 64kHz). I think I have to manage a 
FIFO buffer with two thresholds. When the FIFO is full over first 
threshold, the SPI transfer is stopped. When the FIFO is empty lower 
than the second threshold, the SPI transfer is started again.

Are there some examples to study?