4FSK on 25 Microwatts

Bill, VK5DSP, and I have been testing a new 4FSK modem waveform that uses LDPC Forward Error Correction (FEC). Bill designed the LDPC codes we are using, and worked out how to perform the soft decision to Log Likelihood Ratio (LLR) calculations we need to use LDPC codes with 4FSK. This is surprisingly tricky, and took a few weeks of careful simulation work.

Once working in simulation, we wanted to test the system Over the Air (OTA).


We set up and adjusted antennas on the 2m Ham band, our FT-817 radios, and some USB rig interface boxes. This always takes longer than you think! Bill has a Yagi with 10dB gain fed by coax with 2dB loss. I have a Flower Pot vertical dipole with (I estimate) 2dB gain, and a crummy coax run with 5dB of loss. Here’s is Bill’s Yagi (it was mounted higher for the actual experiments):

Bill and I are 10km apart, with a non line of site path across suburban Adelaide between us.

The GNU Octave modem simulation has been split into Tx and Rx scripts. We generate a file of Tx samples using one script. The Tx station then plays that file OTA, while the Rx station records a file of received samples, which are then run through the Rx script to obtain Bit Error Rate (BER) and Packet Error Rate (PER) results. Here is a sample run using a local file test.raw:

octave:46> fsk_lib_ldpc_tx("test.raw")
octave:48> fsk_lib_ldpc_rx("test.raw")
Fs: 8000 Rs: 100 frames received:   8
  Uncoded: nbits:   3584 nerrs:      0 ber: 0.000
  Coded..: nbits:   2048 nerrs:      0 ber: 0.000
  Coded..: npckt:      8 perrs:      0 per: 0.000

The modem can be configured for any bit rate. We started with 100 symbols/s (200 bits/s for 4FSK) and a half rate code, resulting in 100 bits/s payload data rate. As an initial sanity test, we tried receiving our Tx signal using a RTLSDR/Airspy and gqrx located a few metres from the Tx. This confirmed the OTA link was working over short distances. A lot can go wrong with OTA tests, so it’s really important to build up to them slowly, testing at every stage.

Results – Day 1

On our first attempt we hit a few USB/LSB and tuning bugs. Turns out the core, uncoded demod works quite well with LSB and USB swapped – it’s just that all the tone frequencies are reversed so the decoded bits are scrambled!

After we sorted those issues out Bill managed to record and decode my 4FSK signal. We started with 600mW Tx power. The SNR was very high, and we had zero errors. Hmm, too strong! So we started inserting attenuation. Eventually, with about 1mW Tx power, we started to get some errors and found the “knee” in the curve – the point where the FEC falls over and we start getting packet errors.

With powerful codes like LDPC this transition is very sharp, change your SNR by just 1dB and you go from 0 to 100% packet errors.

We measured the path loss using a spectrum analyser. With Bill transmitting a 2W (33dBm) FSK signal, I measured -102dBm at the spec-an input, so an end-end path loss of 135dB. I estimated the free-space loss, for a line-of-sight path, including feed losses and antenna gains, at about 89dB. So the non line of site path is costing us 135 – 89 = 45dB extra attenuation.

Now our expected MDS can be estimated as:

MDS = Eb/No + 10*log10(bitRate) + NoiseFigure - 174
    = 7 + 10*log10(100) + 10 - 174
    = -137 dBm

I’m guessing the FT-817 noise figure at 5dB, and I have a coax loss of 5dB ahead of that so 10dB total. Now we reached our MDS with a Tx power of 0dBm, and our path loss is 135dB, this gives us a measured MDS of 0 – 135 = -135dBm. Not bad – theory and measurement within a few dB!

We performed further tests with a rate 3/4 LDPC codes at 400 symbols/s (600 bit/s throughput). This worked well at 10mW Tx power. Here are some plots showing the modem operation:

The top subplot above shows how the demodulator estimates the frequency of each of the 4FSK tones. They are nice and smooth and spaced at 400Hz, just as we would hope. The bottom plot is the time estimate, which shows a typical saw tooth pattern as the sample clocks of Bills DAC and my ADC are a little off (a few 100ppm). The demodulator automatically adjusts for this.

The top subplot above shows the SNR estimate (in the noise bandwidth bandwidth of the modem, not 3000 Hz). Our modem falls over when this hits around 7dB, so at 10mW we have 3dB margin. The bottom subplot is the number of bit errors per frame. Our LDPC codeword is about 2000 bits long, so that’s a raw BER of around 50/2000 or 2.5%.

You can decode this signal yourself using the off air sample Listen

octave:48> fsk_lib_ldpc_rx("20200717_4fsk_rs400_10mw.wav")

Now 600 bit/s is pretty close to the bit rate we need for Digital Voice which has us thinking ….. here is Bill trying SSB at the same power.

Results – Day 2

On our second day of testing Bill positioned himself at a site in the Adelaide Hills which overlook the city. The idea was to get a better path (closer to line of site) so we could try lower powers. For these tests Bill used a J-pole mounted on his car.

We managed to decode the Rs=100 symbols/s rate 1/2 waveform at an EIRP of -16dBm (25 microwatts). That’s the transmit power, not the received power.

Unfortunately we ran out of attenuators at that stage so couldn’t go any lower. It even worked really well with the FT-817 driving just a 50 ohm attenuator when the antenna cable was disconnected!


We had a great time testing and are pleased that our modem performs just as expected over real world channels. We were both surprised that it worked – these tests usually take many attempts to get right!

I found OTA testing at VHF a lot easier than HF. You click the attenuator up and down a few dB and the SNR follows. The channel really is just additive noise, unlike HF that has all that time varying frequency selective fading and impulse noise.

What we have here is a carefully engineered 4FSK modem with powerful FEC that performs right on the theoretical limits. It can send packets of data between two points very efficiently. The payload bit rate and MDS can be scaled up and down to suit different applications. It’s all open source, and backed by a series of simulations documenting it’s development and testing.

Reading Further

Pull Request for the 4FSK to LLR mapping simulation
Pull Request for the 4FSK LDPC OTA tests
Open IP over VHF/UHF Using a RPi and RTLSDR at higher bit rates.
Bill’s LowSNR blog
Codec 2 FSK modem README
The design for Bill’s 6 element Yagi

3 thoughts on “4FSK on 25 Microwatts”

  1. Great stuff David !

    Something you can improve on :

    You mentioned that you measured the path loss at a spot frequency with a spectrum analyser. There is considerable chance of error with this method due to time variability of the multipath. Such as a car parking across the road..

    The presence of time variability on the suburban path turns it into a frequency selective wideband channel, in order to better estimate the path loss, this path loss measurement should be at a number of frequency points, over the estimated coherence channel bandwidth.

    In the suburbs, I would recommend about 250kHz , and so perhaps 10 (frequency) points is a good number. If dominant reflections are very close, you might need up to 1 MHz bandwidth and many more points to fully understand the effects.
    Of course, the a efficient method is using a swept method, with care of other band users.


  2. Wow! I continue to be impressed with everything you do.

    Is this work in support of the sm2000 or is there some other hardware you have in mind? I haven’t seen any new info on the sm2000 since 2016.

    Also, I would wonder if a second (diversity) receiver could be used to give another 3 dB of improvement. That would be cumbersome for an HT implementation, but pretty simple for a Base station.

    Keep up the brilliant work!

Comments are closed.