Function Generator With Zero CPU Cycles

No one is sitting around their workbench trying to come up with the next great oscilloscope or multimeter, but function generators still remain one of the pieces of test equipment anyone – even someone with an Arduino starter pack – can build at home. Most of these function generators aren’t very good; you’re lucky if you can get a sine wave above the audio spectrum. [Bruce Land] had the idea to play around with DMA channels on a PIC32 and ended up with a function generator that uses zero CPU cycles. It’s perfect for a homebrew function generator build, or even a very cool audio synthesizer.

The main obstacles to generating a good sine wave at high frequencies are a high sample rate and an accurate DAC. For homebrew function generators, it’s usually the sample rate that’s terrible; it’s hard pushing bits out a port that fast. By using the DMA channel on a PIC32, [Bruce] can shove arbitrary waveforms out of the chip without using any CPU cycles. By writing a sine wave, or any other wave for that matter, to memory, the PIC32 will just spit them out and leave the CPU to do more important work.

[Bruce] was able to generate a great-looking sine wave up to 200 kHz, and the highest amplitude of the harmonics was about 40db below the fundamental up to 100 kHz. That’s a spectacular sine wave, and the perfect basis for a DIY function generator build.

34 thoughts on “Function Generator With Zero CPU Cycles

      1. Indeed, perhaps I should have been more specific. The condition of requiring a signal which is repetitive in an integer number of samples will still limit your frequency resolution, especially at output frequencies which approach your sample rate. Mind you, if you wanted to create a signal generator with a PIC32, I would have thought it would be able to generate a sine wave on the fly at 200kSPS, where DMA would still be useful to transfer update the DAC register and regular intervals.

      1. An external PLL (e.g. Si5351A mentioned on HaD previously) *could* be used to change the frequency feeding into the PIC. That would make things more complicated and can screw up things e.g. UART/USB/RTC/OS that relies on a particular frequency.

  1. >Note that B.4 and B.5 have a required config statement to turn off JTAG and clock input and that B.6 does not exist on this package

    My major complain is that some uC do not have contiguous bits in a ports (for a byte) was a priority when they design the pinout. (Often when they wire bond a big chip with lots of I/O into a smaller I/O package) This makes it a pain to drive a parallel bus out of a micro-controller without resorting to additional cycles needed to do additional shifts and/or logical operations.

      1. The only thing that’s cheaper is the arduino you already own. I can flip bits on a port with around a 4uS period, if I recall correctly (can’t find the darn sketch I wrote for that at the moment). With some filter caps, resistors, and maybe a transistor, you should be able to produce a 250kHz sine wave. I don’t think anyone really needs to have a sample rate that’s 100x the frequency of interest if you can filter the harmonics with some analog components. It’s likely better if you’re limiting yourself to just the audio spectrum as well. Then again, nothing I’m doing requires a perfect sine wave.

    1. The dsPIC33 I’m working with now has a portion of its RAM which is dual-port, allowing unfettered simultaneous access by CPU & DMA. So on it at least, DMA truly has zero CPU impact. I don’t know if any of the PIC32 products, like the one used in this project, has a similar feature.

  2. I did something like that several years ago with y Cypress PSoC5. The big difference is that there you can implement a proper numeric NCO so the frequency control is much more granular in the higher ranges. And the DAC there can do up to 8 MSps.

    1. Along the same lines, why do D/A conversion at all? We’ve had simple analog equipment for over half a century that could produce perfect sine waves up into the UHF part of the spectrum (hundreds of MHz). If all you’re looking for is a sine wave, build an oscillator circuit similar to what’s found in almost all analog transceivers.

    2. Not a RF guy here. Wouldn’t a band pass or low pass filter be what you would use to get rid of the higher harmonics and make sine wave more “pure”?

      If all you care about sine wave, there isn’t much reason for D/A. If you want to generate arbitrary waveforms or do RF modulation directly in digital domain (SDR), then playing waveform sample in D/A is the way to go.

      1. Yes, and you can stack the filters to yield a sharper Q (becomes pointless as the filter count rises, but carefully stacking a few will really tidy things up). Depending what you’re doing and at what frequency, you’re going to run into phase issues, but that may not matter for the casual user. Best way to find out is to build it (or simulate it first if you wish)… never know what you’ll end up with!

  3. The STM32F429 Discovery board has 8 MB of SRAM & DAC at 1 MS/s. You can compute a sine wave or play a stored arbitrary waveform. For square waves the timers will do and with an integrator you can get triangle waves. Most dev boards are candidates for this sort of thing.

    I’ve got a project on that includes this and a bunch more. At the moment I’m constructing a crystal testing fixture for automating the grunt work in building crystal filters. Not written up yet. The basic oscillator (from 2013 ARRL handbook) is working and now needs to be controlled using a varactor to pull the xtal using the DAC. Not as ambitious as the other features, but a good start as it requires using the timers to measure frequency, the DAC to control the varactor, the ADC to measure the signal level and GPIO to short the xtal to measure ESR. Which is all the major peripherals.

    Progress is slow because there are so many things you can do with very little additional hardware. It is easy to get distracted.

  4. I just have to say that Bruce Land is my favorite teacher that I’ve never had. Hopefully he will publish some new material on youtube, I’ve already watched all his courses, though the FPGA ones go over my head.

    Also, really surprised at the higher-than-usual quality of comments in this thread, except for the snarky remarks.
    I’m sure you can a DDS with the cheapest FPGA that is miles ahead of anything enumerated above. Even using PWM + DMA (is that possible?) on an ARM4 like the Launchpad should yield faster/cleaner waveform, but I think the article is about doing something interesting not questioning why,

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.