Spark Logic

simple sound player: PWM audio output, with DMA, without timer interrupt

stevestrong Sun Oct 29, 2017 9:20 am

I have a project in which I need some short sound effects, without reading WAV files from SD card.

To output PWM audio, current solutions use timer interrupt to update the new value in the compare output register.
This version uses the DMA (channel 7) triggered by timer (4) update event to do the same, so the processor has now plenty of time to do other tasks.
Speaker out on PB6 (timer 4 ch 1).
No interrupts are used, although one could use the DMA transfer end IRQ to do some stuff.

EDIT: – I added the possibility to use DMA interrupt. For this just enable the define in line 10.

This example uses a half second long WAV file (converted to C code) with 8 bit resolution, 16 kHz sampling rate, stored in the flash (~8kB data).
The timer prescaler and preload registers are optimized in order to have a maximum peek to peek output range for 0-255 PWM values.

Have fun.

Needed patches:
https://github.com/rogerclarkmelbourne/ … 2/pull/366
https://github.com/rogerclarkmelbourne/ … 2/pull/367

[quiz: what does the sound say?]

Replies

stevestrong Wed Nov 01, 2017 1:54 pm

Ah, thanks, I got the point about the “repetition counter”.
I couldn’t find it because I was looking to the general purpose timers, they don’t have this feature, only the advanced ones (TIM1 and 8).
This means that you are limited to the TIMER1 compare channel output pins (and the remapped ones). But this is not that critical.

RogerClark Wed Nov 01, 2017 7:55 pm

Steve

can you briefly explain how the code you posted, is supposed to work ?

From looking at ou code, I think you are using DMA to control the timer PWM.
The DMA sends the values from the array ( which is data from a WAV file)

This appears to change the PWM proportion.

However I dont seem to be getting the resulst I exoected.

If I connect an 16 ohm headphone ( ear bud) via a 330 ohm resistor, I can hear something like the word “hello”, but when I look at the soeaker pin with a logic analyser, I see a very strznge waveform, where the falling edige of then output pwm appears to have a 50mhz pulse of square waves.
I think this must be ringing caused by the inductance of the speaker.

The other thing I noticed, is that the values in the wav array, dont seem to have a very wide range.
Are they 8 bit, 16 or 32 bit values ?

I initially thought they were 8 bit, but I need to doible check, as they may be 16 bit.

stevestrong Wed Nov 01, 2017 7:59 pm

They are 8 bit values.
And congrats, you solved the quiz :) , it is indeed the hello word being said.

The timer 4 update event triggers the DMA which is writing the wav sample values to the CCR1 register. Thats all.

RogerClark Wed Nov 01, 2017 8:01 pm

did you normalise the wav file to get max range of 8 bit values?

stevestrong Wed Nov 01, 2017 8:05 pm

No. I was happy with the original amplitude which had 80% peek.

RogerClark Wed Nov 01, 2017 8:08 pm

OK

I’ll do some more tests.

RogerClark Wed Nov 01, 2017 8:16 pm

BTW.

Does the sine table in the code still work?

I tried to enable it, but didn’t get a tone

Edit.

Sine table just clicks a bit

I don’t think things are working the same for me as they do for you :-(

I’ll attach my logic analyser and look at the PWM pin PB6

Edit 2.

I found my piezo was a bit faulty. I tried just using digitalWrite to make a tone and it didnt work very well.

I’ve found the loose connection inside the piezo and its working a little better, but I think I may need to connect the piezo between Vcc and PB6 rather than ground and PB6 as this may stop the clicking.

I think however that the direct linkage between the wav data sample and the PWM is not ideal, as it needs lots of samples to get good audio. Probably 48kHz or higher would be better.

BTW.

Did you use this to create the data

http://ccgi.cjseymour.plus.com/wavtocode/wavtocode.htm

stevestrong Wed Nov 01, 2017 9:14 pm

The sine table should work but its length is really short, more than a click is not hearble. But it can be seen with the scope ;)

The other click is due to audio level sudden jump from steady (low or high) to middle level when it starts playing.
It can be avoided by fading the in and out portions.

Yes, that is the converter. But meanwhile i think it can be generated more easily with HxD (hex editor), open file and save as code.

The audio is of couse better quality when sampled with 48kHz. But this was a quick feasibility test to check quality of short samples which should fit in flash.

Edit
In parallel i am evaluating the tone functions, you probably observed as i pushed a pr. But that is another story.

RogerClark Wed Nov 01, 2017 11:48 pm

Hi Steve

Yes. I saw your PR for the tone library, I need to test before I can merge

One thing I noticed with tone that it didn’t work on the pin you are using i.e PB6

I’m not sure why that is.

I think ideally the tone library should work on all pins, even if we have to make it blocking, but thats a different matter.

Sign in to reply