Decimal DDS Signal Generator

By Murray Greenman ZL1BPU
A new audio signal generator and sweep generator with wide range, high accuracy and great versatility.

The main difference between this generator and its older brothers (SIGGEN and NOISE-PULSE) is that this one is programmed in decimal numbers - no more hex calculators or special PC software! The generator will output Sine, Square or Ramp waveforms to 400kHz in one range, with the same precision and resolution over the whole range. It also has a DUAL-TONE mode. The hardware can be identical to that of the other generators.

As well as general purpose audio and LF signal generation applications, the unit can be used to sweep audio amplifiers, audio and LF filters, crystal filters and even LF antennas. With dual tone capability, it is useful for distortion measurement and a range of differential level measuring activities. Remember this unit has 0.1Hz resolution, high accuracy, and high stability!

View of the completed Signal Generator

The generator can be quite inexpensive - just two or three ICs and a couple of transistors. The generator uses Direct Digital Synthesis (DDS) in all modes. Some of the features of the new ZL1BPU DECGEN Signal Generator are:

From left: (1) 1kHz sine wave (2) 250kHz sine wave (3) 1kHz square wave (4) 1kHz ramp. Click on each image for full-size view.

In the left-most picture above (1), the 1kHz sine waveform is shown. It is clean and smooth. Hint - don't rely on the thumbnail pictures above - they lack resolution. Click on each image and view it full size! (2) shows the 250kHz output, looking little different, except slightly thicker at top and bottom due to interpolation noise, and 3dB lower in level due to the low pass interpolation filter. The square wave (3) shows clean transitions, no bounce or droop, while the ramp waveform (4) shows a smooth, linear ramp, although if you look closely you can see a slight discontinuity in the centre of the ramp due to the use of 1% resistors in the R-2R network. This effect does not appear when 0.1% resistors are used.

Exactly the same hardware is used as in previous ZL1BPU signal generators, although the power amplifier is not required. Instead, a four stage output attenuator with 3dB steps is recommended. Communications is half - duplex, using a 9600 bps data rate (9600-N-8-1). Except at start-up, the generator only replies when spoken to. In this model, the reference crystal must be 16MHz for the maths to operate correctly.

The microcontroller, an overclocked Atmel AT90S2313-10PC or (not overclocked) ATTINY2313, has a very simple main program consisting of a choice of four very tight and very fast sampling processes, taking data either from a sine table or internal calculation at a fixed rate, to place the data on an output port. The Direct Digital Synthesis technique works not as you would expect, by stepping sequentially through a table of waveform values at a variable rate, but instead uses a fixed very high frequency (about 1.77 MHz) sampling rate, and a user controlled step size to address the table or calculate the output. Except for DUAL mode, the different algorithms are tuned to operate in the same number of clock cycles (9 per loop) in order to maintain the same frequency calibration in all modes. In DUAL mode, the sampling rate is reduced to 800kHz (20 cycles per loop), and further calculations are made on frequency commands to correct the frequency calibration. All frequency calculations are made to 24-bit resolution to ensure accuracy.

Simplified block diagram of DDS generator

The phase accumulator and phase adder use very large (24 bit) numbers. The most significant eight bits of the accumulator select the correct table value at each sample point. The eight bit digital values at the port are converted to an analog waveform by a simple R-2R resistive ladder. The required waveform is reconstructed by an anti-aliasing interpolative filter at the output (a simple RC low pass network was used for the example waveforms). A better PI LC filter (see example further down the page) would improve the frequency response and high frequency rejection.

Another interesting feature of this generator is that it will generate TWO FREQUENCIES at the same time! A new algorithm has been added which uses DDS to generate two completely independent sine waves from the same table. This allows for a wide range of extra applications for the generator. The dual tone mode has reasonably low intermodulation, and although the tone resolution is lower than in single tone mode (about 2Hz), and the upper frequency range is reduced (about 200kHz) the tones can be set independently anywhere in the operating range. Both tone frequencies are selected with the same command, and are scaled for decimal input.

In DUAL mode the two tones always have the same output level, and can be as close as you like or as far apart as you like, and entered in any either order. If the frequencies are the same, the amplitude is indeterminate since the phases are not controlled. Similarly, and for the same reason, setting frequencies with harmonic relationship will give the frequencies requested, but may not give the waveform you expect. In addition, there may well be slight frequency discrepancies between such frequencies, so the phase relationship will slowly change (the frequency resolution is reduced in this mode).

1000 and 1100Hz (left) - 20kHz, 30kHz and spectral response (right). Click on image for full-size view.

In the left picture 1kHz and 1.1kHz signals are generated at the same time. The 100Hz beat frequency appears as an envelope. On the right, 20kHz and 30kHz are shown, along with the spectral response. Because these frequencies are harmonically related, a stable waveform results. Each tone is 6dB down on a single tone, but the intermodulation and other products are at least 50dBC.


There are 10 simple commands:
FREQ      Fxxxxxx

Set frequency, where xxxxxx is six digits 000000 to 999999Hz. Second frequency in DUAL mode set with same command.

DECIMAL      .x

Decimal place frequency offset, 0 - 9 meaning 0.0 to 0.9Hz (actually 0.106Hz steps).

HELP      H

Simple help message listing these commands.

MODE      Mn

Sets the waveform mode, where n is a number 0 to 3. 0 SINE  1 SQUARE  2 RAMP  3 DUAL.

POWER      Pn

Sets the output signal level if the level controlled amplifier or stepped attenuator option is used. n is a hexadecimal number, "0" to "F".


Requests a message giving the current settings. Unfortunately for humans, the report is in HEX, not decimal.

SAVE      S

Saves current settings. Saves FREQUENCY (both), DECIMAL place offset, MODE, WIDTH and POWER.

WIDTH      Wxxxx

Sets sweep step size, where xxxx is 0000 to 9999Hz. The sweep range is 20Hz (W0001) to 200000Hz (W9999). The start frequency for the sweep is set by the F command. There are by default 20 steps at 2.5ms intervals. Setting W0000 turns off the sweep function.

COUNT      Cnn

Number of steps used in sweep mode. Default is 14HEX (20). Values are in hexadecimal 01 - FF.

DWELL      Dnn

Time spent on each step frequency in sweep mode, in increments of 64us. Default is 27HEX (2.5ms). Values are in hexadecimal 01 - FF.

Each command consists of one command letter (upper or lower case) and zero to six following hexadecimal or decimal characters. In the table above, values shown as "n" are hexadecimal; those shown "x" are decimal. No "Enter" or other control characters follow. The correct number of characters must be used. Unexpected characters, misunderstood commands and some impossible values will result in the microcontroller responding "?", and the synthesizer will continue with the current settings. If a command is not completed, the synthesizer will remain stopped. Sending any wrong character (such as <CR>) will restore operation. The "F" and "." commands can be combined, for example sending "F123456.7" will cause the generator to operate at 123456.7Hz. Obvious really!

To operate in dual-tone mode, send both frequencies you need with the F command. The generator uses the last two frequencies sent. In any single tone mode, it uses only the last frequency sent. It is quite possible to send impractical frequencies and impractical sweep step sizes. The Nyquist Frequency occurs with a setting of F888888 (888.888kHz) or F400000 (400kHz) in DUAL mode, and would generate meaningless signals if used or even approached. Best to stay below F400000 (400kHz) or F200000 (200kHz) in DUAL mode.

When the device is first powered up, it issues an "OK" message. If using a dumb terminal, start the terminal before the generator.

User Manual (81kb)
The frequency resolution of the Signal Generator is dependent on the microcontroller clock crystal frequency. The resolution (in all modes except DUAL TONE) is the Clock frequency in Hz divided by 9 x 224, or:
Resolution = fclock/150994944

In DUAL mode, the resolution is the Clock frequency in Hz divided by 20 x 224, or:

Resolution = fclock/335544320

Using a 16.000 MHz crystal, the resolution is 16000000/(9 x 224) = 0.1059638129340277 Hz or 16000000/(20 x 224) = 0.0476837158203125 Hz in DUAL mode. For example, to set to 200 kHz in any SINGLE mode, 200000 / 0.1059638129340277 = 1887436.8 = 1CCCCDHEX. Why is there a '9' or a '20' in the calculation? Because there are nine (or 20 in DUAL) clock cycles in every DDS synthesizer loop. 224 corresponds to the size of the biggest number in the accumulator register. Fortunately the generator makes these calculations for you.

Looking more closely at the maths, how are we able to enter numbers as decimal? That would require the generator to divide by 0.1059638129340277! Well, if the crystal frequency is operated slightly low of 16MHz, at 15.999464MHz, it works out that the resolution can be made EXACTLY 0.1059602649Hz. Big deal? Look at the reciprocal of this number - its 9.4375! It is straight forward to have the generator multiply by this number, since it can be done purely by shift-and-add - remembering that 9.4375 is 9 7/16.

In DUAL mode, the generator has 20 clocks per loop, rather than 9, and a further multiplication (by an approximation of 20/9 = 2.222222) is used to further convert the operating values, although some resolution is lost in the process.

The upper frequency limit of signal generation is related to sampling theory. The Nyquist Frequency, the frequency above which it is not theoretically possible to reconstruct the sampled waveform accurately, is one half of the sample rate, so is given by:

Nyquist Frequency = fclock/(2 x 9)

In practical applications such as this it is not possible to approach the Nyquist Frequency without very fancy filters, and fclock/30 is considered a reasonable upper limit in single tone modes.

It is possible to take advantage of the Nyquist images, but a better approach would be use a Phase Locked Loop using say a 74HC4046, locking the 74HC4046 to the fundamental output of the generator ( up to say 250kHz) and using a frequency divider in the PLL loop.

The unit can be very small. Even built on "Veroboard", it can be under 100mm square. The prototype was built on a DSE H5608 prototyping board (47 x 72mm), but with a board this small it was a tight squeeze, and the attenuators were on a separate board. The simplest version of the unit consists of the microcontroller, a 3-terminal regulator, two transistors, a crystal and about 25 resistors and capacitors. Most of this is shown on the Schematic. This is the same schematic as earlier signal generators, all you do is replace the crystal with 16MHz. If you don't want to use output attenuators or a power amplifier, use a 10k pot for level adjustment (connected to the point marked DDS OUT). You'll also need a BNC connector for the output, another for the sweep trigger output, and a coaxial DC power connector. The panel mount DB9 or DB25 RS232 connector is on the right of the schematic.

A recommended output attenuator arrangement. Click on image for full-size view.

The recommended output arrangement (shown above) uses four relay-controlled attenuators, arranged in binary steps, 3dB, 6dB, 12dB and 24dB, which allows an attenuation 0 to 45dB in 3dB steps. These attenuators are controlled by 12V DPDT relays driven by BC547 transistors from the outputs PD2, PD3, PD4 and PD5 (not shown). Use a 10k base resistor, and a 1N4148 clamp diode across the relay coil. The attenuators shown are designed for 1000 Ohm output impedance - use 1% metal film resistors. The generator signal (from the R-2R network) enters top left. Note the PI network low pass filter (L100, C106, C107) to give improved alias and clock suppression. An extra relay (RL5) is shown which turns the output off. This can be omitted, switched by the application of power to the generator (protects generator when power is off), or switched with a panel switch.

For a more advanced version with a power amplifier and micro controlled output level, you will also need a TDA7052A audio amp, and a few more resistors and capacitors. The power amplifier is shown on the Amplifier Schematic. If the power amplifier is not used, delete all the related components, including the resistors related to the VC output of the microcontroller (left side of Sheet 1).

The unit can be built (with power amplifier) on a PCB made to the design offered for the Noise-Pulse Generator.

Software is ONLY offered for a 16MHz version. The maths relies on the correct crystal frequency.

Frequency Range
0 to 400 kHz in ~0.1059 Hz steps. 0 to 200kHz in DUAL frequency mode.

Frequency Accuracy
Settable to within 0.1059Hz of any required frequency in the above range. Nominal resolution is 1Hz, with 0.1Hz offsets. Setting accuracy dependent on calibration, achieved by trimming the crystal frequency to 15.999464MHz. Warmup drift and ageing dependent on the quality of the reference crystal used. With ordinary micro crystals, typically 1 part in 106 warmup drift in the first hour and 1 part in 107 ageing per day.

Output Amplitude
Direct Output: 0 to +5V DC coupled output (direct from D-A converter) into high impedance load, 1.7V RMS. 0.88V RMS output into 1k Ohm load (-1dBV). Output in DUAL mode reduced 3dB for each tone. Risetime 0.3s into 5pf, 5s into 100pF load.
Attenuator Option: 3dB steps 0 - 45dB into 1000 Ohm. Output adjustable via microcontroller Pn command in 16 steps. Output can also be turned off with the F000000 (zero frequency) command.

Waveform Accuracy
Eight bit digitally sampled waveforms (7 bit per waveform in DUAL mode). Step linearity is good and the D-A converter is monotonic with 256 discrete steps if 0.1% resistors are used (no steps in a ramp output give values smaller than the previous step or larger than the next step). Harmonic distortion is very low. No harmonics, noise or spurs on output worse than -60dBc over the range 1 Hz - 20 kHz. Spurious output better than -40dBc up to 250 kHz. DUAL mode intermodulation is at least -50dBC.

Frequency Response
0 to 100kHz 1dB with a simple single pole low pass filter, approx 250 kHz with PI filter. Dual tones within 1dB of each other over the same range.

Offset Steps
0 to 0.954Hz in 0.105Hz steps (nominally 0.1Hz). Offset steps are lost when the frequency is changed.

Non-Volatile Data
Frequency (both in DUAL mode), Mode and Power (output level) are remembered with the SAVE command and restored on power-up.

SINE, SQUARE, RAMP (positive sawtooth from 0V) and DUAL sine wave. All waveforms can be swept. No sweep in DUAL mode.

Sweep Function
Start frequency set by F command. Step size 0 - 9999Hz, in 1Hz steps, set by the Wxxxx command. There are by default 20 discrete steps in the up-frequency direction, each 2.5ms wide. Total sweep time is thus 50ms. Both number of steps (2 - 99) and dwell time (1 - 99 in 64us steps) are adjustable. Steps are phase synchronous and steps are imperceptible at audio frequencies. Sweep is available using all waveforms except DUAL (although what use this might be escapes me as yet). The generator can be made to sweep from zero.

Sweep Sync
The sweep sync output PD6 (pin 11) is high during the lowest frequency step (frequency set by F command). The output is +5V CMOS, pulse width 2.5ms, risetime 10ns. The positive going edge of this output is normally used to trigger the oscilloscope sweep, although it could be used to reset an integrator used to generate a ramp sweep waveform for an X-Y oscilloscope. The sweep and sync speed are adjusted with the Cnn (COUNT) and Dnn (DWELL) commands. The time between sync pulses is (by default) 50ms.

Power Supply
+6V to +15V DC at about 25mA without attenuator relays. (With relays use 10 - 15V supply). On-board +5V regulator and reverse voltage protection. Current drawn is about 200mA with all relays active. The relays (and amplifier, if used) operate from the unregulated supply.


The unit also includes a sophisticated sweep generator which works with all waveforms (except DUAL mode) - see above. The sweep is by default 20 steps of 2.5ms each, convenient for an oscilloscope set at 5ms/div, and a reasonable sweep rate for filters without having to endure a flickering display. A sync output is true on the first step, making oscilloscope synchronization easy. The step size can be 0 to 9999Hz, and the unit can be swept anywhere over the whole operating range from zero upwards.

Low frequency sweep showing clean step transitions (left) - 110kHz sweep with 2kHz steps (right).
Click on image for full-size view.

The sweep is phase synchronous, so in the left image above, you cannot see the transition from one frequency to another. These are frequencies so low (starting at 10Hz, and 10Hz steps) that only partial sine waves are seen for the first few steps. The red trace at the bottom shows the SYNC signal used to trigger the oscilloscope. The second picture above shows the sweep generator in action, sweeping a 120kHz filter. The first step is 110.0 kHz, and each successive step increases by 2kHz, so the peak is at 122kHz. There are several other points to note in this picture. First, the oscilloscope used had no 5ms/div setting, so at 4ms/div the steps do not line up with the graticule, although they are easily visible. Then, notice that two of the centre frequencies show a modulated envelope. This is caused by aliasing in the digital oscilloscope, which samples at a multiple of 125kHz. Finally, you can see small transients between the steps of the sweep. These are caused by the impulse response of the filter being swept (they aren't present when a conventional smooth sweep is used).

This Signal Generator is unusual enough, offering the ability and agility to go anywhere in its operating range virtually instantly with no drift, chirp, or settling time. However, the built-in sweep function is even more capable. While the number of discrete frequency steps is low (by default 20), the number of steps, the sweep speed and the step size are all adjustable over a wide range, making the function useful at audio and LF frequencies. By setting a large number of steps, you can make a very smooth sweep, but of course unless you also decrease the DWELL time, the sweep will be quite slow. You can even set two sweep steps rather than 20, and generate FSK!

Here are some examples:

F100000 W0100 C14 D27    20 steps 100kHz - 120kHz, 5ms/div (default)
F100000 W0020 C31 D10    50 steps 100kHz - 120kHz, also 5ms/div (about 1ms/step)
F130000 W0050 C02 D34    130kHz carrier, 50Hz upward shift FSK at 300 baud

The sweep is generated by a timer function, which adds the selected step to the operating frequency every interrupt (by default 2.5ms), and returns to the starting frequency after the 20th (by default) step. The timer interrupt stops the generator very briefly in order to change the frequency, but because the interruption is very brief (about 2s), the output effectively remains phase synchronous at all but the highest frequencies. Observe the sweep oscilloscope shots closely to see how good the signal is - the frequency steps are invisible.

The default sweep step size and step duration were chosen as a reasonable compromise for audio and LF use. Using the SYNC output, a conventional Y-T oscilloscope can be externally triggered (triggered off the positive edge of the SYNC signal), offering a stable sweep display. The oscilloscope should be set to a sweep time of 10ms/division, which results in exactly one sweep across the screen, and two frequency steps per division.

Two commands control the default sweep function. The F command sets the sweep start frequency, the frequency of the first of the 20 discrete steps. The W command sets the frequency difference between the steps. The value supplied is in Hz, so W0010 will cause each step to be 10Hz. The command W1000 will cause 1 kHz steps. The maximum step is 9999Hz, giving a maximum sweep width of about 200kHz.

The sweep can be modified by two additional commands. The DWELL command Dnn sets the time spent on each step, in 64µs increments. The range is 01 - FFHEX or 64µs to 16ms per step. The COUNT command Cnn sets the total number of steps. The default value is 14HEX (20 steps) and the range is far more than you'll need! Note that you can generate FSK by setting COUNT C01, the DWELL to give the correct baud rate, and Fnnnnnn and Wnnnn to give the FSK frequencies you need (example above).

When the command W0000 is received, the sweep is turned off (the timer function is stopped) and the frequency reverts to the start frequency (set by the F command). Sweep settings are not saved by the S (STORE) command, or restored when power is reapplied. No other settings are affected by the sweep commands, and no other commands than F, W, C and D affect the sweep settings. Sweep is stopped when the frequency is changed, so send the W command to restart it.

A simple three-wire serial interface is used. For use with a PC, you will probably need a 9 pin female connector (DB9F). The pin numbers shown correspond to the pins on the DB9F connector. With this configuration, the device will plug directly into the PC serial port, or it can be connected by a short pin-for-pin modem cable (i.e. not a "null modem" cable). Some PCs have 25 pin serial ports. A 25 - 9 pin adaptor is the simplest solution here, although of course a DB25 connector could also be used. The generator can be used with a "dumb terminal" or other terminal emulator, or you could write your own application. This generator would ideally operate as a "virtual instrument", and is compatable with LABVIEW™ if you use an appropriate serial driver. You can also use a LANTRONIX X-PORT™ network interface.

The generator uses 9600 bps (9600-N-8-1) communications.

Two software products are offered; one with just the executables (.HEX file and .EEP file) and a complete development source code archive. If you order the full archive, you can modify and reassemble the code (using a free assembler). You will also need (free) programming software. Obviously, if you want to modify the software, you will need both programs. If you don't want to change the software, simply use the programming software to load the executable software, using the appropriate file for your intended clock frequency. You will also need to make, buy or borrow a suitable Programming Adaptor.

Software is offered only in a 16MHz version, since the decimal calculations rely on this. For best accuracy, trim the crystal frequency carefuly. The processor can be an AT90S2313-10 (overclocked) or ATTINY2313. All examples of the AT90S2313-10 (10MHz) processor overclocked at 16MHz have operated reliably over a normal domestic temperature range.

It is possible to purchase just the executable code, or both the executables and source code. In both cases the PC software is also supplied. See the Micro Page for details.

Copyright Murray Greenman 1997-2005. All rights reserved. Contact the author before using any of this material.