Frequency Synthesizer

This frequency synthesizer program uses a stereo soundcard to generate a carrier or BPSK signal from a reference frequency. The soundcard output can be used directly at VLF, or could be multiplied or mixed up to LF.

The ratio of output frequency to reference frequency can be any ratio representable by a double precision float. The output is phase and frequency locked to the reference.

You will need:


The program is open source under the BSD 2-clause license.

Source code: ebsynth.c.
Compile with
gcc -std=gnu99 -Wall -O3 -o /usr/local/bin/ebsynth ebsynth.c -lasound -lncurses -lm -lpthread
and you might need to prefix that with sudo if you are not running as the superuser. If you get a complaint about ncurses, you'll have to do
apt-get install libncurses5-dev
The command ebsynth -? gives you a summary of the command syntax.

Carrier Operation

Connect your reference signal to input channel 1 of the sound card. If possible, run the soundcard at its maximum sample rate. On a Raspberry Pi it is probably better to stick to 48k samples/sec to avoid risk of dropped USB packets. The examples below assume you have a 10 Mhz reference divided down by 512 to give 19531.25 Hz at the soundcard input. Run something like

   ebsynth -d hw:0,0 -R 19531.25 -F 8270.032 -r48000 
and use alsamixer to set the soundcard input gain so that you get a reference amplitude of about 0.5 RMS. The level is not critical and nor is the waveform. The program will take about a minute to stabilise. Use alsamixer to adjust the output level.

A feedback signal may be connected to the channel 2 of the soundcard. If ebsynth is given a -x option it will use this external feedback to stabilise the phase. The feedback signal may be obtained from a near field probe or an antenna current transformer. Use alsamixer to adjust the level of the feedback signal.

Press CNTL-C to terminate the program.

EbNaut Modulation

With a -m option, ebsynth expects to read a string of symbols via standard input. The format expected matches the output from ebnaut -et.

In addition to the carrier and reference options described above, you must specify a start time with -T and a symbol period with -S, and optionally a repeat period with -n.

You can pipe the output of ebnaut -et directly into ebsynth. For example,
   echo 'test message' | ebnaut -ep8K17A -N12 -t |
      ebsynth -d hw:0,0 -R 19531.25 -F 8270.032 -r48000 -m -S0.1 -T07:25 -n120
This sends a 12 character message with symbol period 0.1 seconds, to start at 07:25:00 and repeat at 2 minute intervals.

The minimum useful symbol period is 0.05 seconds. The program allows for the soundcard output buffer delay when timing the modulation.

The -T option sets the start time of the message and always refers to universal time. You can use any of the following formats:

   hh:mm hhmm hh:mm:ss hhmmss
If a date is not specified it will assume today unless the time has already passed, in which case it assumes tomorrow. A number of seconds prefixed with a plus specifies a start time some number of seconds from the current time.

If you are taking a harmonic of the output, you should use a -h option to specify which harmonic you are using. This enables ebsynth to select the right amount of phase modulation for the harmonic in use.

When selecting a start time, allow a couple of minutes for the output to stabilise.

The phase modulation is applied by slewing the phase smoothly from one symbol to another using a sigmoid function. By default the slewing takes a fraction 0.05 of a symbol period. You can change this to some other fraction by the option -s sigmoid=fraction, for example -s sigmoid=0.1 to specify one tenth of a symbol period. A linear ramp can be used by giving -s linear and hard keying is obtained with -s hard which might be appropriate at VLF.


An output signal is produced on both channels of the stereo output of the sound device. The program generates PCM at full scale and you must set the actual output level using alsamixer.

By default, both outputs are identical sine waves. The option -o bridge inverts the phase of one of the outputs. This might be useful for driving a stereo amplifier in bridge mode, or for applying your own BPSK modulation externally.

Both outputs can be switched to square wave with -o square. This may be helpful if you are taking a harmonic of the output but it is better to use a sine output and square up the output with hardware.

Option -o iq enables a complex output, where channel 1 is the cosine and channel 2 is the sine. When combined with -h the output phase is set so that the specified harmonic has the 90 degree phase relation between the two outputs.

The plots on the right show the output spectrum, with and without modulation.

Phase stability

The graph shows the RMS difference between pairs of phase measurements made some interval apart. EbSynth is running on a Raspberry Pi model 2 with an Audio Injector sound interface at 96k samples/sec. The output frequency is 27kHz, for operation at 9kHz divide the deviation by three. Deviations at intervals longer than about 1000 seconds are determined by the temperature stability of the A/D conversion oscillator. EbSynth phase and frequency error is related to the rate of change of oscillator frequency. This can be reduced by thermal insulation of the oscillator or the whole sound interface.

Push-to-talk control

EbSynth is able to control the PTT via the DTR and RTS modem control signals of a standard RS232 serial port. One or more -p options are used to specify PTT operation. -p dev=device gives the serial port to use, for example -p dev=/dev/ttyS0. If -p mcr=dtr+rts is given, DTR and RTS are both asserted (driven positive) to enable the transmitter. If -p mcr=dtr-rts the DTR signal is driven positive and RTS is driven negative. By default, the PTT is activated 2 seconds before the transmission and dropped 2 seconds after the end of the transmission. These times can be modified with -p pre=seconds and -p post=seconds options respectively.

Multiple options to -p can be listed comma separated, for example -p dev=/dev/ttyS0,mcr=dtr+rts,pre=30,post=30.

The RS232 voltages are typically +/-12V on a desktop PC and +/-5V on a laptop PC or USB serial device. On a 9 pin D-type

Log file

With a -v option, the program writes messages to standard error which should be redirected to a file so that it doesn't interfere with the display.

ebsynth ... -v 2> logfile
Every 10 seconds the log file reports the UT second, the apparent frequency of the reference, and the soundcard sample rate.


If you are using the EbSynth to send EbNaut messages, ensure you have ntpd running.

Sound card overruns and underruns must at all costs be avoided. If one occurs, the phase will be lost and there is no way to recover. If the ALSA driver reports overrun on input or underrun on the output ebsynth will exit. There is no point in trying to recover. USB sound dongles may lose USB packets and the driver is not notified. If this happens on the reference input the phase will be lost and will not recover. The output will experience a phase step and will settle down at a new phase. If a USB packet is dropped from the output, there will also be a phase step but if external feedback is in use, the phase will recover to its original value.

In normal operation the output frequency error should be around 1uHz or less, varying randomly plus and minus, and occasionally going above 1uHz. If the reference signal suffers noise or interference, the output error will bounce around much more than this. A likely cause is interference from the transmitted signal itself. You may find the output error is stable with the PA turned off but goes haywire when the PA is on. Another source of problems is mains hum and attention needs to be paid to possible ground loops and power supply problems.

The output frequency is usually within about 1uHz and the long term accuracy equals that of the reference. The phase is usually within 1 degree or less. When the soundcard sample rate drifts, ebsynth corrects for the drift after a short lag and during that lag, there will be a small frequency and phase offset. This can be minimised by minimising soundcard clock drift. On PCI cards, the board can be shielded from fan drafts and the clock crystal can be insulated with foam. USB dongles can be encased in an insulated enclosure, for example by carving out a hollow in a polystyrene block. These measures slow down any rate drift due to ambient temperature changes and the output phase and frequency errors reduce in the same proportion.

Some USB soundcard don't work properly when running full duplex. Indication of this is a good reference RMS, a sample rate that doesn't settle down, and the reference phase jumping around all over the place. To prove it, run with a -o mute option which turns off the soundcard output. If the sample rate and reference phase then settle down, you have a dongle which doesn't do full duplex properly.

The output phase is fixed but there is no absolute reference. Therefore when you restart the program, it will settle to a new phase.

You can launch a new terminal session for ebsynth easily with, for example

xterm -e ebsynth -r 192000 -d hw:0,0 -R 19531.25 -F 9770 -o bridge &
rxvt -fn 8x13 +sb -fg black -bg '#d0d0ff' -e ebsynth -r 192000 -d hw:0,0 -R 19531.25 -F 9770 -o bridge &
Using xterm or rxvt you can resize with shift-keypad-plus and shift-keypad-minus.