0
\$\begingroup\$

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?

\$\endgroup\$
12
  • \$\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\$ Feb 6, 2015 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, 2015 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, 2015 at 17:19
  • 2
    \$\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\$ Feb 6, 2015 at 17:26
  • 1
    \$\begingroup\$ @Scott - I don't think the increment desired here is simply to account for the peripheral width, but rather to increment a table index by larger values as in a DDS, ie, to skip entries. \$\endgroup\$ Feb 6, 2015 at 17:27

1 Answer 1

2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\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, 2015 at 20:19
  • \$\begingroup\$ Bruce, the skipping step is how traditional DDS uses an "oversized" table to allow for low phase noise / finer adjustment. See: analog.com/en/analog-dialogue/articles/… Think about this problem: say I want to generate a sine wave using a DAC & table in memory. If I don't have a way to finely adjust the update frequency (i.e. integer fractions of fclk are too coarse) then there needs to be a way to vary the steps in the table in order to be able to change from say, 100kHz output to 100.01kHz output. \$\endgroup\$
    – jacobq
    Dec 10, 2021 at 16:43

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.