I'm programming an STM32F4 Discovery board to push a sequence of 12 bit values into the DAC data register. This works well using timer interrupts: inside my IRQ handler, I have code that looks like:

phase += phaseIncrement;
DAC_SetChannel1Data(DAC_Align_12b_R, function[phase]);

and the output of the DAC looks like I think it should. Note that phaseIncrement doesn't have to be 1 - if I want a high frequency output, I can skip points in function[], sacrificing the accuracy of the signal for a bit of extra speed.

Now, I am reading about DMA. It looks like the STM32F4 can only increment by one of three amounts - 1 byte, 2 bytes, and 4 bytes, depending on the size of the variable being transferred. Is this correct? Is there a workaround that will let me skip some of these memory addresses so that I can emulate my current output without less CPU usage?

  • \$\begingroup\$ Pretty sure there's a register that takes an actual increment value - have you checked the programmer's manual? It may be a trick to get phase accumulator wrapping right without involvement of a soft interrupt on wrap, and I don't immediately see how you could do fractional phase increment while using only the whole part for lookup. \$\endgroup\$ – Chris Stratton Feb 6 '15 at 16:33
  • \$\begingroup\$ I got a bit overwhelmed by the DMA section. I'll take another look. I can live without fractional phase increment - changing the timer period will probably be good enough for me. \$\endgroup\$ – Greg d'Eon Feb 6 '15 at 16:35
  • \$\begingroup\$ @ChrisStratton: The programmer's manual says that either (or both) the peripheral and memory address can be incremented by 1, 2, or 4 (byte, half-word, and word). \$\endgroup\$ – Greg d'Eon Feb 6 '15 at 17:19
  • \$\begingroup\$ You shouldn't be passing a byte and a half. Pass 2 bytes, and pad. \$\endgroup\$ – Scott Seidman Feb 6 '15 at 17:26
  • 1
    \$\begingroup\$ Too bad - that's less flexible than I would have thought. Depending on what you are doing, could it make sense to preselect the data by writing it to a new buffer that can be sent out 1:1 ? \$\endgroup\$ – Chris Stratton Feb 6 '15 at 17:26

As far as I know the STM32F4's DMA controller cannot do what you want. DMA can feed the DAC much faster than interrupt driven software (up to 10.5 Msps) so you might not need to skip samples anyway.

If DMA is not fast enough then the classical solution is to make multiple copies of your waveform, each with half as many samples as the previous one. This will use a maximum of twice as much sample memory (1 + 1/2 + 1/4 + 1/8 etc). If you have several waveforms that take up a lot of space then you might not have enough memory to store all the higher octaves. However if you only need to play one waveform at a time then you may still have enough RAM to precompute and store the octave(s) required for just the current waveform.

  • \$\begingroup\$ I now have DMA pushing data into the DAC. The improvement is unbelievable (literally an order of magnitude faster), but I will still need to skip samples for the higher frequencies. I think your "classical solution" is the one I will use. \$\endgroup\$ – Greg d'Eon Feb 6 '15 at 20:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.