SM2000 Part 4 – Tx Amplifier Chain

This week I’ve been working on class A and class C amplifiers for the transmit side of the SM2000 design. Yesterday I worked up a gain budget that would take me from -20dBm at the output of the 1st mixer to +30dBm (1W) at the output of the PA. I need two 20dB (ish) driver stages and one 10dB (ish) PA, 50dB of gain in total.

The prototype amplifiers all had Z-match networks that matched to 50 ohm input and output. When combining the amplifiers I combined the Z match networks, removing the intermediate 50 ohm step. So we go from 2500 ohms at the output of the first stage to 10 ohms at the 2nd stage input. Then 250 ohms at the 2nd stage output to 10 ohms 3rd stage (PA) input.

I cranked the handle on the Z-match calculations and soldered the thing together:

In the photo you can see the extra large rectangular pads I used to give Q2 and Q3 some heatsinking. I measured and tweaked all the home made inductors using the spec-an method from the last blog post. I estimate they are within +/- 15% of the values on the schematic.

It worked first time but the overall gain was a bit low at 43dB. So I entered “experimental mode”, and started testing individual stages. To test stage 1 and stage 2 alone this meant changing the Zout network to match the 50 ohms of the spec-an.

Couple of changes:

  • The 1st stage gain was a bit low. I changed L1 from 24nH (the calculated value) to 57nH, this gave me +3dB. I don’t know why, and it’s annoying me! However I appreciate that at VHF the calculations can only get you to within 20%.
  • While testing stage 1 and 2 there was some instability, which went away when I rotated L2 45 degrees away from L3.
  • In my first pass I use a 18 ohm resistor to bias Q3 at 0V. However when I changed this to a RF choke the output power jumped up to 1W with -20dBm drive, and I can get 0.5W with -30dBm drive.
  • The power supply filtering (R7 and R8) causes about 1V of drop to the power supply of Q1 and Q2, which leads to a few dB loss of drive. This could be improved by recalculating the Q1 and Q2 bias points.

The BFQ19 is not meant for 1W so I only ran it for a few seconds there. I killed one when I raised Vcc to 14V, it’s rated at a Vce(max) of 15V and with Vcc=14V the collector would be seeing at least 2Vce = 28V. However it runs OK for a few minutes at 0.5W.

Next Steps

I figure this design has plenty of drive to deliver 1W with the right output transistor. Now I need to select and obtain a suitable transistor and test it. Think it will need to have a Vce(max) of 36V, 2W dissipation, and >10dB gain at 150MHz.

I need to integrate this PA with the PIN diode TR switch and come up with some switching earlier for the BPF output just after the mixer. The tx and rx chains share the 1st mixer (which is bi-directional) and BPF. So I need a way to switch between the input of this tx amplifier chain and the LNA output.

The PA has a 2nd harmonic just -38dB down so we’ll need a little more filtering, spurious 50dB down would be nice.

SM2000 Part 3 – PIN TR Switch and VHF PA

Over the last few days I have prototyped a few more building blocks for the SM2000, documented here for my reference.

PIN Diode Transmit/Receive Switch

These are described in quite a few places, one of the best references is the PIN Diode Handbook. Key issue for me is the receive side loss through the switch, as it adds to my noise figure, which I have put a lot of work into keeping low!

Note the switch so I can make sure the control voltage is tied to 0V in the “off position”.

The initial rx loss was a bit high at 0.5dB which I traced to the inductor value being measured as 72nH rather than the 53nH I designed for. Need to watch that with home made inductors. Reducing it to 3 turns made it bang on, and the receive loss of the TR switch is now 0.25dB, about what I expected. The transmit insertion loss is also a little high at 1dB, perhaps more drive current is required in the PIN diodes. The isolation between the tx and rx ports on transmit is just 23dB, I was hoping for more. However with 1W (30dBm) out, thats 7dBm presented to the rx LNA input which is OK.

Thanks Matt VK5ZM for discussions on the TR switch over IRC as I messed with it.

Measuring Inductor L and Q at VHF

There comes a time in every RF noob’s life where you need to measure the L and Q (or effective series or parallel inductor resistances). I started with Measuring Inductors at VHF and Above which suggests a series resonant circuit in series with a tracking generator and spectrum analyser.

This works well when the Rl of the inductors is comparable to the spectrum analyser 50 ohm impedance. However at VHF, inductors in the couple of hundred nH range are common. An air core inductor with L = 150nH may have a Q of 200 at 150MHz, giving an equivalent Rl = 2*pi*f*L/Q = 2*pi*150E6/200 = 0.7 ohms. When Rl is a fraction of an ohm, the spec-an input Z=50 ohms dominates the Q of the series tuned circuit and you don’t get much of a peak.

So I tried a few different topologies, and ended up hanging a series resonant LC circuit across the spectrum analyser input, and running some numbers as below. This gives you a nice sharp dip at resonance, so knowing C, you can work out L=1/((2*pi*f)^2)C. Then some voltage division based on the depth of the “dip” lets you work out Rl and hence Q:

While writing this post I stumbled across this blog post on Measuring Resonator Q at VHF, which uses a cool gimmick-capacitor variation on a method described in EMRFD.

Thanks also to Neil VK5KA and Matt VK5ZM for discussions on this topic.

500mW VHF Class C PA

I need a 1W PA for the SM2000. I have no PA experience so needed a way to get started. The largest VHF-capable transistor I have laying about is the BFQ19, which is rated at 1W. EMRFD suggests choosing a device whose power dissipation exceeds the desired output power, so I chose a 0.5W target output power. This transistor has a maximum collector voltage of 15V. Class C amplifiers can kick Vc to 2 or 3 times Vcc so I chose a Vcc of 5V.

“RF Circuit Design” tells me that small signal S-params don’t count for power amplifier design, and there are no large signal design parameters for this transistor (it’s designed for small signal operation). So I used the simple approach of just designing for a collector load of Rl = Vcc*Vcc/2P = 25 ohms, ignored any reactive components, and crossed my fingers.

I tried a couple of different impedances driving the base. With the conventional selection of 10 ohms I had poor gain and couldn’t reach my target output power. I think the problem was the voltage driving the base. 13dBm into 10 ohms is sqrt(2)*sqrt(0.02*10) = 0.632Vpeak, which is less than the 0.7V needed to switch on the transistor. By changing the impedance match network to 100 ohms driving the base I kicked up the base drive (albiet at a higher impedance). Now the transistor was being switched on, and I reached my power target with 13dBm of drive and a Vcc of 7.6V.

This is probably an artifact of the low power output and hence low drive of my little power amplifier. For a 1W amplifier with 100mW drive, peak base voltage would be sqrt(2)*sqrt(0.1*10) = 1.4Vpeak.

Note the 1uH inductor value in the sch photo should be 100nH. I only ran the PA for a few seconds, as I don’t have a heatsink and it’s dissipating 0.5W. A bigger piece of PCB soldered to the collector might be OK, although that might add capacitance too. At some point I’ll need to work out how to calculate the heatsink size I need.

I spent a bit of time playing with different base and collector loads in order to increase the gain. However looking at various other VHF PA designs, it appears 10dB power gain is about right, so I decided my little amplifier is working OK. I’ve learned a lot! Next step is to come up with some sort of tx power and gain budget so I make sure I have the correct drive levels for a 1W PA.

Reading Further

EMRFD and “RF Circuit Design” books.

Harry’s Homebrew has a good section on Z matching for VHF PA design

The design calculations for this VHF PA are in . I’ve started collecting a bunch of little Octave functions for RF design into rfdesign.m.

SM2000 Part 2 – RF Amp Design

For the SM2000 I need some VHF small signal RF amplifiers, for example a driver amplifier for the transmit PA. So I figured it was about time I learned to design RF transistor amplifiers. The S-parameter method seems to be the way to go, and I have some BRF92 transistors that have S params on the data sheet.

Unless you are experienced in RF design this post may not make much sense. I estimate the eye glazing to interest ratio at 20dB. However as a RF noob I am documenting my experience to help me remember what I have learned.

I spent a day reading the small signal transistor amplifier chapters of “EMRFD” and “RF Circuit Design” by Chris Bowick, and getting my head around Smith Charts. I scratched about on a bunch of paper, complex numbers flying everywhere. Lots of errors and rework. The next morning, to cross check my manual work, I wrote s_param_rf.m to handle the tedious calculations.

I also found these helpful RF and Microwave Stuff Octave scripts, e.g. Smith Chart plotting, including stability circles.

The transistor and operating point I chose was not unconditionally stable, so I had get my head around “stability circles” and find an input and output load that would be stable, and design input and output matching networks. The “RF Circuit Design” book walked me through everything.

Here is the Smith Chart for my operating point:

The red and blue arcs are “no go” circles for the input and output impedance the transistors sees. The green is a 20dB constant gain circle. Any output reflection coefficient gammaL on the gain circle will give you an amplifier with 20dB gain. The source reflection coefficient gammaS is a function of gammaL. So I tried a few different gammaL (red star) until I found a stable gammaS (purple star).

The Smith Chart is rather “busy”. The output reflection coefficient gammaL = 0.8 – 0.4j is the same point as the load or output impedance Zo = 1 – 4j (normalised to 50 ohms which is 50 -200j without normalisation). Even though they map to identical points on the chart, they are read off different axis as different values.

Here is a sample run of the Octave script:
octave:207> s_param_rf
K = 250.5885e-003
-----Frequency: 1.00 - potentially unstable - plotting stability circles
Red is the gammaIn=1, for all loads (gammaL)
Blue is the gammaOut=1, for all sources (gammaS)
Green is the 20.0 dB constant gain circle for gammaL
Input: Zi = 67.6 + 26.9j ohms
In parallel form Rp = 78.3 Xp = 197.1j ohms
So for a conjugate match transistor input wants to see:
Rp = 78.3 Xp = -197.1j ohms
Rs = 50.0 to Rl = 78.3 ohm matching network Xs = 37.6j Xp = -104.1j
with conj match to Zi Xs = 37.6j Xp = -301.1j
matching components Ls = 0.040 uH Cp = 3.5 pF
Ls can be made from 3.1 turns on a 6.25 mm diameter air core
Output: Zo = 50.0 + -200.0j ohms
So for a conjugate match transistor output wants to see:
Rl = 50.0 Xl = 200.0j ohms
Which is a series inductor Lo = 0.212 uH
Lo can be made from 7.1 turns on a 6.25 mm diameter air core

I then designed the bias network and came up with this circuit, which I soldered together:

You can just see the little SOT-23 surface mount transistor in the centre of the photo.

Much to my surprise it worked! They say anyone can design a RF oscillator but it takes skill to design an RF amplifier. This actually works as an amplifier! Here is the gain swept between 0 and 300MHz:

Gain was 23dB, return loss at both ports about 8dB at 150MHz. I’m not sure if the return loss is a problem, it represents about 1dB loss (15%) in the reflected signal. I figure getting within 15% is OK given component and S-param tolerances at VHF.

The noise figure was measured at 4dB, and 1dB compression point around 0dBm. The compression point feels a bit low, perhaps as I used a collector resistor rather than a RF choke. I’ll read up on that next, see if I can get a 10dBm output, suitable for driving the SM2000 PA.

Version 2 with 10dBm Output

After another day of head scratching and 3 tries with different collector currents, collector loads, and finally an increased Vce (10V), I have arrived at a version that can handle 10dBm output:

Two tricks were required to get the 10dBm power output:

  1. Setting the load impedance for the collector Z=P/(Irms*Irms). I worked out the required impedance assuming a RMS current of 2mA, which was a reasonably “small signal” variation from the 14mA bias I selected for this version.
  2. Raising Vce from 4V to 10V by using an inductor in the collector rather than a resistor. This meant Vc could bounce around a bit more without being clipped. When I tried increasing the collector impedance without raising Vce the output power was still distorted at 0dBm, so this was an important step. The inductor ended up being part of the matching network and now my circuit looks like everyone else’s so I must be doing something right.

If the above doesn’t sound very convincing it’s because I don’t quite know what I’m doing. EMRFD and RF Circuit Design has a better explanation.

The output is a nice clean 10dBm sine wave, with 2nd order nasties 35dB down:

The Octave script was modified to do the calculations for this version:
octave:69> s_param_rf
K = 466.3534e-003
-----Frequency: 1.00 - potentially unstable - plotting stability circles
Red is the gammaIn=1, for all loads (gammaL)
Blue is the gammaOut=1, for all sources (gammaS)
Green is the 20.0 dB constant gain circle for gammaL
Transducer gain: 26.9 dB
Input: Zi = 8.4 + 3.2j ohms
In parallel form Rp = 9.6 Xp = 25.4j ohms
So for a conjugate match transistor input wants to see:
Rp = 9.6 Xp = -25.4j ohms
Rs = 50.0 to Rl = 9.6 ohm matching network Xs = 19.7j Xp = 24.4j
with Xs a capacitor, and Xp and inductor Xs = -19.7j Xp = 24.4j
With a conj match to Zi Xs = -45.2j Xp = 24.4j
matching components Li = 0.026 uH Ci = 23.5 pF
Li can be made from 2.5 turns on a 6.25 mm diameter air core
Output: Zo = 2500.0 + 0.0j ohms
matching network Xp = 357.1 X = 350.0 ohms
which is parallel Lo = 0.379 uH and series Co = 3.0 pF
Lo can be made from 9.4 turns on a 6.25 mm diameter air core

My “transducer gain” is somewhat off (I’m getting 21dB), I know not why. Maybe as I’m using 100MHz s-params for a 150MHz circuit. Now time to look at diode TR switching and maybe a class C 1W PA.

I was studying EMRFD to understand the collector load thing and found what looked like a small typo. I emailed the author (the legendary Wes Hayward) who replied and sure enough I was right, and it will be added to the errata. Finding even a small error in a book like EMRFD makes me feel prouder than getting this amplifier working! Just like software – debugging someone else’s well written work is a great way to learn. Also like open source “release early and often” and let the community help improve the work.

SM2000 Part1 – Open VHF Digital Voice Radio

For the last month I’ve been working hard on prototyping the SM2000 – an open source VHF radio. It’s purpose is to test some advanced VHF/UHF ideas I have for FreeDV.

The SM2000 will be a small box (like the SM1000), that contains a fully functional VHF SDR Digital Voice radio. It will run advanced open source Digital Voice modes, have a 1W power output and adequate tx/rx filtering for real-world operation on the 2M band. No Host PC required. Open Hardware and Software, price TBD but a few hundreds of $. It will also run analog FM but no modes with a proprietary codec.

Just yesterday I demonstrated demodulation of 1200 bits/s 2FSK at -135dBm, right in line with predicted performance.

This is an important milestone. Analog FM and first generation digital voice (D-star/DMR/C4FM and friends) fall over at about -120dBm. One of my aims is equivalent performance to these systems at 10dB lower. With completely open hardware and software.


I need custom RF hardware to develop and demonstrate VHF DV ideas I have formed over the past year. However I am not a RF expert, am just one guy, and have limited resources. So I will focus on those areas that I can uniquely contribute to. Choose my battles. In other areas (e.g. certain aspects of RF performance), I will just shoot for acceptable.

I have a similar approach to architecture. There are many ways to build a radio, and I have chosen one that suits me at this time. Feel free to warm up your soldering iron and substitute your own favourite.

What I care about:

  • I don’t trust any part of the modem being in hardware. This means software defined waveforms, and SSB style up and down conversion. Direct FM is out. And don’t get me started on data running through analog FM modems.
  • TDMA needs a “bare metal” uC for hard real time, so no OS. Host PC/USB peripheral type designs won’t work.
  • Functional demos of advanced features such as sub -130dBm Digital Voice, $100 TDMA repeater, diversity to handle multipath, low cost, open hardware and software.
  • No chip sets or SoCs. This is open source. I need control.
  • Don’t have to a tick all boxes first time around.

Less important:

  • Minimal cost
  • Sparkling RF performance in areas such as phase noise, IP3, blocking, ACR, high tx power, frequency stability, channel spacing, multi-band operation, low spurious, power consumption. The RF Gurus can do that better than me so I’ll leave it to them.
  • Gold plating – is the feature going to add to our schedule? Can anyone else implement it? Will it introduce risk? Who will step up to make it happen?

Your Suggestions Welcome

But I’ll probably ignore them. What I really want is your contribution. If you want your-favourite-must-have-feature to happen, step up and make it happen. Innovation is 1% inspiration and 99% perspiration. I get overwhelmed by well-meaning people with inspired ideas, and underwhelmed when I ask them to help implement those ideas.

Can you make my TODO list shorter, not longer? Now you have my attention.

Receiver Design

The receiver is a dual conversion superhet, with IFs at 10.7MHz and 24kHz. It is designed primarily for constant amplitude waveforms such as FSK, so does not have an AGC.

I used this Gain and Noise Spreadsheet as a tool to design the radio. It calculates cascaded NF, the NF of the ADC, and the gain required to get the MDS we need. I also have some sub-sections that I plug numbers into as I test, e.g. for NF calculations, and tuned circuit calculations. Very useful.

I haven’t designed the first BPF yet, but anticipate it will have a low loss (to maintain system NF), and a fairly broad response.

The PGA103 is a 0.5dB NF, 20dBm input IP3, 20dB gain block which sets up the overall receiver noise figure of 1.5dB. It’s major disadvantage is high power consumption (90mA at 5V), so I am considering a discrete transistor amplifier here.

The BPF near the mixer provides attenuation of out of band signals. Through a process of slightly mystified experimentation I have settled on a double tuned circuit:

Which has a response like this:

Due to parasitic capacitive coupling changing the position of the coils relative to each other sets the position of the notches. I’ve set up the 60dB notch on the 126MHz image frequency. I’ve built it a couple of times with the same dimensions and the response is quite predictable. Each coil is 6 turns wound on a 1/4 inch drill bit, with a tap at half a turn for the 50 ohms input and output. The other end of each coil has a 12pF trimmer cap.

A Si5351 is employed for the local oscillators. For the purists I will include a Si570 option for the first LO. The RF switch for the two Si5351 outputs is to support diversity (two channel) reception. The radio can quickly shift to a channel a few hundred kHz away to receive a packet, effectively receiving on two frequencies at the same time.

I’m using a SBL-1 mixer but will move to an ADE-1. The RF Gurus tell me that termination of the IF port of the mixer is important. So I’m using a 15dB gain Termination Insensitive Amplifier (TIA) that presents a 50 ohm load to the mixer over a wide range of frequencies. I swept the TIA input using a return loss bridge and confirmed around 20dB return loss out to 300MHz (the sum of the LO and RF signals). The TIA has bandwidth of 50MHz which should effectively filter out the LO+RF IF signal.

A 10.7MHz 15kHz wide crystal filter attenuates off channel signals (47dB down at +/- 25kHz) and performs bandpass anti-aliasing filtering for the ADC. To get a nice flat response there is some impedance matching either side of the crystal filter.

I messed around with a few 2nd mixers (sub harmonic, discrete transistor, diode). I had some problems with noise when using a transistor mixer (LO injected into emitter, RF into base) which held me up for a few days. Then I tried a NE602 and it worked really well, and provides some gain. With a good Z-match on the input the 2nd mixer noise problem was gone. So that will do for now.

The baseband amp takes the 24 kHz IF and boosts it 50dB before feeding it to the uC ADC. It’s just two transistors with emitter degeneration to set the gain. The ADC is configured to sample at 96kHz, and upload samples to a Host PC via USB. I can then use a GNU Octave script (e.g. fsk_horus.m) to demodulate the FSK signal.


I am designing for test, e.g. using 50 ohm building blocks. This allows me to break out each section and test separately, for example sweeping the crystal filter, or driving the TIA with a 10.7MHz FSK signal, or measuring NF of a section.

I have been testing the Bit Error Rate (BER) performance from the very early building block stage. This measure neatly defines the performance of a digital radio. Much better to test BER early than wait for final integration and have dozens of problems to solve. We want to know as soon as possible if there is a problem.

This block diagram shows an example of testing from the IF down:

I modified the fsk_horus modem to support 1200 bit/s and a sample rate of Fs=96kHz. This is a well tested modem that has performance bang on ideal.

Component Selection

The radio is implemented with garden variety transistors, the most exotic parts being the ECS M15B crystal filter, SBL-1 mixer, PGA-103 LNA, and NE602. There are no transformers. I have used some toroids to wind my own inductors however these are not critical in terms of Q or tolerance and can be replaced with off the shelf parts.

There are three trimmer capacitors that need aligning with the use of a spectrum analyser. Although it may be possible to have an alignment mode, e.g. use the Si5351 to sweep a test signal, sample the signal and display a spectrum on a Host PC.

I used Manhattan style construction:

The two PCBs in the background are a STM32F4 Discovery board and an OpenRadio which I’m just using for it’s Si5351 outputs.

I didn’t even need a printed circuit board to prototype and reach the -135dBm performance milestone. This has allowed me to remove a large chunk of risk from the project very early on – a huge benefit.

I think it’s remarkable that with rough construction, no shielding, a poor layout to the STM32F4 ADC, I can demodulate such weak signals. I guess the engineering is subtle and not related to the physical appearance. It does go crazy when I key my HT next to it though!

When we do move to a PCB the same parts in surface mount packages will result in a nice compact design.

Next Steps

  • Build a 1W transmitter prototype. In particular deal with RF amplifiers and diode switching to make a TDMA transciever.
  • Testing of the receiver, e.g. other specs apart from MDS
  • Work with Rick, KA8BMA, to develop a Rev A prototype PCB version of the entire radio.
  • Lots of software work
  • The 1200 bit/s 2FSK modem has been used so far as it’s what I had lying around. For the final system I’m favouring 4FSK at 2400 bit/s which I estimate will work at -132dBm. So need to get 4FSK running soon.
  • Work towards functional demonstration of the project goals.

I haven’t planned any further forward. I’m not sure when a SM2000 product will emerge. Some time in 2016 I guess. Sooner if you help!

Command Lines

I’m documenting this here so I don’t forget.

Use fsk_horus to generate modem signal at Fs=96kHz. Use hackrf_uc.m to up-convert to IQ samples at Fs=10MHz for replay by the HackRF. hackrf_uc.m also adds a 700kHz offset (IQ designs have a black hole at DC).

For testing the IF we can then play a 10.7MHz signal from HackRF using:
/codec2-dev/octave$ hackrf_transfer -t -f 10000000 -a 1 -x 20

For testing at 146MHz input of the radio use:
~/codec2-dev/octave$ hackrf_transfer -t -f 145300000 -a 0 -x 15
Note the 700kHz offset.

In both cases adjust the -a and -x options and use an attenuator to get the level you want for testing. The level can be checked on a spec-an, although this gets tricky beneath -120dBm.

Simultaneously sample by flashing the STM32F4 Discovery with adc_rec_usb.elf, and then upload Fs=96kHz samples using:
~/codec2-dev/octave$ sudo dd if=/dev/ttyACM0 of=test.raw count=10000

Then demod using fsk_horus:
octave:109> fsk_horus
Fs: 96000 Rs: 1200 Ts: 80 nsym: 1200
demod of raw bits....
centre: 23976 shift: 1272 twist: -1.4 dB
coarse offset: 1192 nerrs_min: 25 next_state: 1
frames: 13 Tbits: 14400 Terrs: 2 BER 0.000 EbNo: 12.23

Here is a plot of the STM3F4 ADC with -135dBm at the rx input:

You can see the passband of the crystal filter – the internal noise from the radio front end passed through the filter creates the trapezoidal spectral shape at the input to the ADC. The two lines in the centre are the low and high FSK tones centered on the 24kHz IF, the hump of “noise” between them are part of the FSK signal. Not sure what that line around 17kHz is all about.

The lines on the far left are harmonics of the 1.2kHz interrupt service routine on the STM32F4. I cleaned most of this noise up with some power supply filtering, it was initially 20dB higher and all over the spectrum:

A little noise goes a long way with 100dB of gain.

Measuring Noise Figure with the Rigol DSA-815

After lots of reading on NF and a few false starts, I can now reliably measure noise figures, e.g. in my LNA, mixer, BPF, and IF amplifiers. For example the TIA amplifier NF is quoted as 5 dB and I measured 5.2dB. I have also measured the single (BPF in front) and double sided NF of the SBL-1 mixer and they were 3dB apart.

You need to have noise above the noise floor of the 815. With the 815 terminated in 50 ohms I measured -162dBm/Hz, which suggests a NF of 12dB. With gains of greater than 20dB on the device or system you are measuring, the numbers from the 815 start to make sense. So plan your tests such that the measured No is higher than -140dBm/Hz.

Here are the Rigol settings I use:

  1. Amplitude: attenuation 0dB. Pre-amp On
  2. BW/Det: sample
  3. Trace/P/F: Power average
  4. Marker Function: No function (to measure gain) Noise Marker (to measure No)

The procedure is: measure the gain G using a test signal, then switch the test signal off, terminate with 50 ohms, and measure No (noise power/Hz). NF = No – G + 174.

Here is my working for an earlier LNA-Mixer-IF amp combination:

Input power  -80.00
Output power -10.00
Gain          70.00
Noise pwr   -102.20  
NF             1.80 

My design had a calculated NF of 1.3dB, so 1.8dB is reasonable given the 1.5dB accuracy of the 815. I have a spreadsheet setup so I can just plug the numbers in.


Mel K0PFX, and Jim, N0OBG for buying me the spec-an, which has been invaluable. Neil, VK5KA, for RF advice; John VK3IC and Craig VK3CDN for cables, test equipment, and RF advice; Matt, VK5ZM and Brady for bouncing ideas off; Glen English for RF guidance and in particular explaining ADC NF.

Brady pointed me at the DSP10 2M radio from 1999 which turns out is very similar to what I have come up with! Some very similar design decisions, and a useful example for me.

Give Us Our Daily Bread

Last week I visited a modern Australian farm on the Eyre Peninsula of South Australia, about 500km from where I live in Adelaide.

This farm has been in one family for several generations, and has steadily grown to 8000 acres (3200 hectares). This same area was previously farmed by 7 families, and now provides a livelihood for just one. This tells me that modern agriculture is super efficient, and explains why food (and calories) are super cheap for us here in the affluent Western world.

This is both good and bad. Given the right political conditions, science and technology enables us to feed the world. We don’t need to be hungry and can use those excess calories for other purposes. The jobs lost in one industry migrate to others. This farming family, for example, has spawned a variety of professionals that have left the family farm and done good things for the world.

It also brings diseases of affluence. Our poor bodies are not evolved to deal with an excess of food. We are evolved to be hunter-gatherers, constantly on the look out for the next calorie. Historically we haven’t had enough. So we are hard wired to eat too much. Hence the rise of heart disease and diabetes.

Breathtaking Array of Skills

I was impressed by the diverse array of skills required to run the farm. Business, animal husbandry, mechanical, agricultural science. The increased mechanisation means computers everywhere and I imagine robotics is on the horizon. During our visit they were measuring the moisture content of the crop to determine the best time to harvest. They even have an animal “retirement village” – they care for several old working dogs who had kept foxes away from the sheep for years.

Unlike many jobs, they don’t know what their yields and hence income will be from year to year. That’s a lot of risk in your annual income.

Overall, It takes about 12 years to learn the skills needed to run a modern farm.

This farm produces 3,500 tonnes of wheat per year. Based on 13680 kJ/kg of wheat, and a person needing 8700 kJ/day, that’s enough to feed 15,000 people every year. From the work of one family farm. Wow.

Organic Farming

I asked them about organic farming. The bottom line is the yields would be halved. So double the prices for everything we eat. That may be fine if you are a rich Westerner but that is the line between life and death for someone in the developing world. Alternatively, it means using twice the land under cultivation for the same amount of food. Organic means starving poor people and goodbye rain forests.

Their use of pesticides is strictly monitored and all residues must be removed. They have modern, scientific methods of erosion control to manage the soil, and techniques to naturally fix nitrogen. Sustainability is being addressed right now by modern, scientific, farming.

In my opinion the organic food movement is a more about scientific illiteracy and marketing than health.

Wind Farming

On a nearby hill was a 75MW wind farm, part of many that have sprung up in South Australia over the past decade. I am quite proud that South Australia now averages 30% wind power. We are about to close down our last remaining coal power station.

In this case, the lucky farmer that owns the land leased for the wind turbines receives $100k per year in passive income. K-ching K-ching as the turbines rotate.

It’s incredible to think that for years there have been “rivers of energy” flowing over those hills. It took technology and the right economic conditions to reach up and pluck that energy out of the sky.

Modems for VHF Digital Voice

I’ve been thinking about modems for a VHF FreeDV mode. The right waveform and a good demodulator is the key to high performance. However it would be nice to make some re-use of existing FM VHF radios. So is it possible to come up with a waveform that can pass through legacy FM radios, but also be optimally demodulated with a SDR?

My first guess was that the problem with legacy radios is the 300Hz High Pass (HP) pass filtering. So I came up with a waveform with has no DC. Brady pointed out this was Manchester Encoding (ME), used in all sorts of applications for just this problem. Each data bit is Manchester encoded to two bits, so a 2400 bit/s bit-stream becomes a 4800 bit/s bit-stream that is then 2FSK modulated. Turns out the ME-2FSK signal doesn’t have much low frequency energy so passes happily through the audio pass band filtering of regular FM radios.

Here is a block diagram of the idea. We have the option to demodulate the signal using a legacy analog radio or, with higher performance, an optimal FSK demod:

This is what the spectrum of the ME-2FSK looks like at the output of the analog FM demodulator before high pass filtering. Notice how there is not much energy beneath 300Hz? So we are not going to lose much due to the 300Hz HP filter.

Here are the time domain modem signals before and after the 300Hz High Pass filter. Pretty similar.

The ME-2FSK scheme works OK in my simulation, so I think it’s possible to squirt 2400 bit/s through a $40 HT with acceptable modem performance using 2FSK. This means we can do VHF FreeDV using your laptop/SM1000 and a $40 radio, and it will work just as well as existing VHF DV modes, and even pass through analog repeaters.

Real gold would be a way to send 4FSK through a HT, that (if you have a SDR) can be optimally decoded at a much lower Eb/No. Unfortunately I couldn’t work out how to do that. For optimal 4FSK you need the tones spaced at the symbol rate Rs. This means -1.5Rs, -0.5Rs, 0.5Rs, 1.5Rs, which won’t fit into 5kHz deviation with Rs=4800. So how about Rs=2400? Well when I tried Rs=2400 through the FM demod the modem appears to be 3dB worse that Rs=4800. I’m not sure why. Possibly deviation, as I get the same results with the 300Hz HP filter removed. Or maybe I messed up the simulation. Oh Well. Working backwards, this suggests one reason the ME 2FSK waveform works so well at Rs=4800 is greater deviation.

Moving to the optimal 4FSK demod approach, here are the outputs of each filter from an optimal 4FSK demod. The pretty colours represent the different filter ouputs. The lower plot is the decimated filter outputs, after sampling at the ideal timing instant.

I’m inclined to use both 4FSK and ME-2FSK. We could run ME-2FSK on links with legacy radios and 4FSK on SDRs that support optimal demodulation. That 6dB Eb/No for optimal 4FSK, combined with Codec 2 running at a lower rate, is a huge gain over current analog and DV systems.

Summary of Candidate VHF Waveforms

I’ve now played with quite a few modem waveforms, and have compared them in the table below. Eb/No is for a BER of 2%, which is roughly where Digital Voice codecs fall over. There are two Eb/No figures, one for an ideal demodulator, the other when using a demod that works through a legacy FM analog radio.

Waveform Eb/No (ideal) Eb/No (FM) Comment Read More
PSK 3.0 na requires linear PA, complex coherent demod
GMSK 5.0 9.0 requires “data” port, complex coherent demod [1] [2]
4FSK 6.0 na simple demod, good fading
ME-2FSK 8.5 12.0 simple demod, good fading, $40 HT!
DMR 4FSK na 11.0 standardised [3]
AFSK-FM na 16.0 As used in APRS [4]

The complexity of the demods required for coherent PSK and GMSK is not a show stopper, as we only have to write GPL modem code once. However coherent demodulation means other sources of “implementation loss” such as phase recovery that make the ideal performance hard to achieve. Non-coherent mFSK is rather simple in comparison, we just need a fine timing estimator. Less to go wrong. No phase estimation means fading will have less impact than coherent PSK/GMSK. Fine frequency offsets won’t bother us. mFSK is, however less bandwidth efficient.

GMSK coherently demodulated or through a legacy FM radio looks pretty good, but does require a “data port” with unfiltered access to the FM modem. So no $40 HTs.

Note the distinction between ideal non-coherent 4FSK, and the 4FSK modem used by DMR and similar Digital Voice modes like C4FSK. The latter are not optimal waveforms, and in our simulations under-perform by around 6dB. We can’t find any explanation of why these waveforms were chosen for DMR or C4FM. I am guessing that have been developed with the specific use of legacy FM radio architectures or reduced RF bandwidth in mind.

Running the simulation

I set up a bunch of simulations of various combinations so they all have about 2% BER:
octave:224> mancyfsk
Rs=4800 2FSK ideal demod
EbNodB: 8.5 BER 0.023
Rs=4800 2FSK analog FM demod, not too shabby and pushes 2400bit/s thru a $40 HT!
EbNodB: 12.0 BER 0.021
Rs=2400 2FSK analog FM demod, needs more power for same BER! Che?
EbNodB: 15.0 BER 0.027
Hmm, doesnt improve with no 300Hz HPF, maybe due to less deviation?
EbNodB: 15.0 BER 0.027
Rs=2400 4FSK ideal demod, nice low Eb/No!
EbNodB: 6.0 BER 0.025

Further Work

It would be great to test the work above in the real world, for example get the ME-2FSK modem software into a form that we can do calibrated noise (or MDS) tests on a real FM radio.

Simulating the DMR Modem

Brady O’Brien has been doing some fine work simulating the 4FSK DMR modem, based on the waveform description in the ETSI spec. It’s not a classic non-coherent 4FSK modem design. Rather it appears designed to easily integrate with legacy analog FM modulators and demodulators.

Here is the block diagram of a regular non-coherent 2FSK demod. For 4FSK there would be 4 arms, but you get the idea:

The DMR modem uses Root Raised Cosine (RRC) filters and a FM modulator and demodulator:

Here are the performance curves produced by fsk4.m:

The best we could do with our simulation is 5-6dB poorer than the theoretical performance of non-coherent 4FSK. This made me suspect we had a bug. However this performance loss compared to theory is consistent with other FSK modems I have simulated that run through legacy analog modulators, rather than using ideal demodulators.

Have we done something wrong? Does anyone have figures for DMR modem Eb/No versus BER? Perhaps with have an error in our simulation. Perhaps the high BER is tolerable for the higher layers of DMR, given the amount of FEC they’ve got it wrapped in. Once you’re over a certain threshold, FEC will take care of it.

Our simulation is consistent with the Minimum Detectable Signal (MDS) figures given for commercial DMR radios, for example 2% BER at a MDS of -120dBm. Our curve above suggests Eb/No=11dB for BER=0.02. Plugging that into a MDS calculation, and assuming a receiver Noise Figure (NF) of 2dB, and the DMR bit rate of 9600 bit/s:

    MDS = -174 + 10log10(Rb) + Eb/No + NF
    = -174 + 10*log10(9600) + 11 + 2
    = -121 dBm

If we had an ideal modem, and Codec 2 at 1200 bit/s, we could get a MDS of -135dBm, or -132dBm with 2400 bit/s over the channel to support two-slot TDMA just like DMR. That’s a huge margin. The modem matters. A lot.

It’s been really nice to have some one else working with me on modem code – thanks Brady! He has done a great job on getting his head around modem implementation. Brady also worked out how to run Octave code on simulation on parallel cores which is a fine innovation. Until now I had been stuck on one core.

All Your Modem are Belong To Us

Everywhere I look I see a need for high quality, carefully tested, open source, portable modem software. This year I built the cohpsk HF modem, that works well on fading HF channels, and is at the key to the low SNR performance of the FreeDV 700B mode.

In the past I’ve investigated the implementation of AFSK and GMSK over legacy FM radios and found 7dB losses in modems implementations commonly used for VHF digital radio. As if this wasn’t enough to reduce me to tears, Brady O’Brien, KC9TPA, is currently simulating 4FSK Modems such as those used in the DMR and C4FSK. These modems, tacked onto legacy analog FM radio architectures, also appear to be 6dB off the pace (more on the DMR modem soon).

Near Space Balloons and RTTY

Mark invited me along to a Horus launch that was about a week away. We started talking about the Horus telemetry modem. Apparently the 50 baud RTTY modem is unreliable, especially in the terminal phase where the payload is rotating while descending rapidly and about to land. Which is just when you would really like to know exactly where it is.

Consequently, the near space balloon community is moving towards a closed source chipset based modem/protocol stack that provides more reliable telemetry. It may even have a patent rattling around inside it.

Well that’s just not good enough.

Closed source and proprietary chipsets are nasty, a glaring problem in a cool geeky field that is otherwise open source. It’s got to be fixed.

Balloon chasing systems also use various hacks used to connect the modem software to mapping software, which in the case of the Horus balloon chasers runs on this legacy operating system called “Windows”. Yeah I’ve never heard of it either. Used to be popular apparently, and I’m told it’s good for games. However it would be nice to do everything in Open Source.

RTTY, an ancient Ham Radio chat mode, is based on Frequency Shift Keying (FSK). Just like these fancy new Digital Voice modes like DMR and C4FSK. Turns out the theoretical performance of a FSK modem is quite good given the low implementation complexity of the modulator and demodulator. Where RTTY falls down is “frame sync”. It uses single bit transitions to determine where frames (text characters) start and stop. A bit error anywhere tends to wipe out many subsequent bits.

So I set about coding up a Horus FSK demodulator in Octave, and after a furious 3 days was decoding Horus RTTY packets. Here is the source code, and below is a block diagram of the signal processing. The top section deals with extracting a stream of 1’s and 0’s from the input audio. The lower section deals with framing and plucking out valid telemetry packets:

A couple of interesting features:

  1. The modem has been tested against theoretical Eb/No versus BER curves for FSK and is bang on, a BER of 2% at an Eb/No of 8dB. You can (and should) repeat these tests as part of any modem development. However I see very little formal testing of open source modems going on. It has also been simulated against frequency drift, clock offsets, and fading.
  2. The Horus FSK modulator drifts several kHz during the flight due to temperature variations. I tested this by putting a Horus payload in my freezer. Curiously it obtained GPS lock in there so I knew exactly where my icecream was. Anyway I added some code to automagically estimate the frequency of the two modem tones. Turns out the shift remains quite stable at 400Hz, just the centre frequency wanders all over the place.
  3. The fsk_horus demod tracks the baud rate of the modem. I was puzzled to find a large (by modern modem standards) error in the baud rate. The tx side seemed to be running at 50.08 rather than 50 baud (1600ppm error). Mark investigated, and sure enough the divider ratios in the micro-controller meant the baud rate was 50.08. The good news is that it’s rock solid (doesn’t drift). It’s just a bit off. Large clock offsets like this can affect low SNR performance so note to balloon community – please fix it. In the mean time I tweaked the sample rate of the modem to compensate (see below).
  4. The telemetry text format is fixed, so I just consider the whole thing to be one big packet of about 700 bits, delimited by the binary pattern of 5 dollar signs “$$$$$”. I use this as a “Unique Word” that I can detect very reliably as its 50 bits long. Good bye RS232 framing, hello reliable frame sync.
  5. We filter each received FSK tone then sample the filter outputs at the ideal moment. Choosing the right sampling time is called fine timing estimation. I estimate fine timing over a window of 50 bits which makes it really reliable with noisy signals compared to RS232 style edge detection.
  6. Even with a bad checksum, plenty of useful information in there. For example the GPS coords might still be OK. So I print out all packets so we can use “human FEC” to see whats in there.
  7. I apply a few rules to clean up the data. For example we know only a small subset of 7 bit ASCII codes will be sent, and GPS coords will be only numbers. So anything outside these ranges is marked as an “erasure”. This prevents a lot of line noise being displayed.
  8. Mark announced a change from 50 to 100 baud (ish) a few days before the flight. No matter, just a few tweaks.
  9. I patched FoxtrotGPS to load a track file via a UDP port command. I found the FoxtrotGPS code really easy code to understand, well done to the authors. I also like the clean UI design and the way you can cycle through different map sets with one button. And a native app is so much more faster than browser based mapping. Breath of fresh air. Patching instructions below.
  10. I wrote the modem in GNU Octave, and it runs in real time. Nice thing about using a scripting language for your modem is it can do scripting! Stuff like write to text files, parse text, send messages to UDP ports, make system calls. The glue code contains the modem now. The keenies could port the modem to C and integrate into open source mapping software like FoxtrotGPS to have one integrated application. Try that with your closed source chip set!
  11. The demod has some simple soft decision error correction. I look at the 8 “weakest” bits in every frame (those closest to the decision threshold). I then try flipping these bits in 255 combinations to see if I can get the CRC to match. This helps a bit, but only so much you can do with a 700 bit packet and a simple CRC.


I carefully tested the modem in simulated AWGN and fading channels. The fading simulated the rotation of the payload plummeting to Earth. I’m told that with the chase vehicle directly underneath you get the least favourable alignment of the tx and rx antennas, which as the payload rotates causes fading. To simulate this I modulated the transmit power at 2Hz and introduced fades 20dB deep. I was told that 2Hz was about as fast as the payload could spin.

Here is the Horus payload connected to my FT-817 via 120dB worth of attenuators, although I really need 150dB to get close to the MDS of the system:

I also tested the entire system around my suburb, e.g. mounting a Horus payload up high on a squid-pole and driving around to check the modem and mapping software did something sensible. This also let me make a check list of equipment I would need on the day. Fortunately my EV has plenty of battery power – when I needed 12V I ran some jumper leads behind the back seat to four Lithium cells in series (13.4V).

Real Time DSP in GNU Octave

The modem runs in GNU Octave in real time (a few % CPU load on one core of an old laptop). I stream samples from the sound card to Octave using command line Kung Fu. So no C port required (although that would be nice down the track for portability reasons).

This is a bit surprising – real time DSP in a scripting language.

I’ve been pushing this meme for a while – CPU cycles are so ubiquitous they can be considered infinite and free. We are wearing enough CPU for many DSP applications. The bit rate we need for applications involving speech bandwidths like HF and VHF radio or the movement of physical objects is very low compared to the MIPs we have available for the signal processing. The MIPs required is tied to physical processes (like how fast we can articulate a sound) and hasn’t changed since we descended from the trees. But the CPUs just keep getting faster.

So the hardware required for the physical implementation of the DSP (e.g. a few % of your laptop or phone) is effectively free. We just need good quality free DSP software to go along with it.

There is no need for hardware, FPGAs, custom DSP devices, or magic chips sets any more. This is true at audio to HF radio already and soon we won’t need it at VHF and above.

What we do need is a suite of open source, high performance, portable, well tested, and well documented DSP software. Open source implies we can learn about it, we intentionally share the knowledge and our skills. Demystifying DSP. Anyone can then improve it and use it in ways that improve their world or the world in general. Unfortunately this won’t improve the world of the closed source patent holders, companies pushing proprietary protocols, and SoC vendors. They won’t like this. Boo Hoo. We don’t need them anymore. We can do a better job than they can. The value is drifting out of the proprietary space. It always does.

Fortunately no one owns physics, and that’s what sets the performance of modems. You can’t seek rent on physics. All your modems are belong to us.

Octave Code

The file fsk_horus.m contains the modem code, and code to test the modem. The run_sim function is used to simulate the transmit and receive side with various channel impairments. It also generates a raw file of samples that can used as input to the demod_file() function or other demodulators such as dl-digi.

The fsk_horus_stream.m script runs the demodulator in real time, accepting samples from stdin:
~/codec2-dev/octave$ rec -t raw -r 8013 -s -2 -c 1 - -q | ./fsk_horus_stream.m
It prints out the packets, extracts lat/long coords, writes to a file, and tells FoxtrotGPS to plot them.

Testing on a Real Balloon Flight

On Sunday Oct 18 we tested the system by chasing a Horus launch from Mt Barker to near Palmer. Here is a screen shot from FoxtrotGPS, balloon track in green, car in red (click for a larger map):

I used a small antenna on a mag mount base, connected to a FT-817 tuned to the payload RTTY signal. This was connected to my laptop running the fsk_horus_streaming script. I used my phone running BlueNMEA as the GPS source for the car, connected to my laptop by USB in Android debug mode:
adb forward tcp:4352 tcp:4352
gpsd -N -n -D5 tcp://localhost:4352

Here is block diagram of how it all fit together:

We had a very pleasant day in the spring sunshine and it became quite exciting as we tracked the payload back and forth. The last packet before we lost the signal was 213m from the ground:
VK5ARG-1,1555,01:46:53,-34.890294,139.178262,705,8,1529,08 CRC OK
VK5ARG-1,1556,01:47:01,-34.890531,139.178020,655,10,1530,08 CRC OK
VK5ARG-1,1557,01:47:09,-34.890896,139.177668,601,8,1530,08 CRC OK
VK5ARG-1,1558,01:47:13,-34.891132,139.177197,551,9,1531,08 CRC OK
VK5ARG-1,1559,01:47:21,-34.891275,139.177033,516,10,1532,08 CRC OK
VK5ARG-1,1560,01:47:29,-34.891644,139.176765,457,10,1533,08 CRC OK
VK5ARG-1,1561,01:47:37,-34.892021,139.176512,402,7,1534,08 CRC OK
VK5ARG-1,1562,01:47:41,-34.892331,139.176160,348,8,1534,08 CRC BAD
VK5ARG-1,1563,01:47:49,-34.892495,139.176033,315,8,1535,08 CRC OK
VK5ARG-1,1564,01:47:57,-34.892787,139.175680,267,9,1536,08 CRC OK
VK5ARG-1,1565,01:48:01,-34.892958,139.175429,213,10,1537,08 CRC OK

The GPS coordinates were a few 100m from where payload was found. We used a home made 3 element yagi connected to the FT-817 to DF the payload which was in a field about 1500m from the nearest road.

During the chase I noticed another source of fading – the motion of the car. Judging by ear this was much faster than 2Hz. Really need some FEC to handle that.

The modem software worked well, and integrated nicely with FoxtrotGPS. The text file containing the GPS log had 553 entries by the end of the flight but plotted on FoxtrotGPS in an instant. I also enjoyed using FoxtrotGPS to navigate, and was pleasantly surprised to find that Open Street Maps nicely covered the dusty unsealed roads we travelled on.

The entire system was totally open source, and runs happily all on one old Linux laptop using a few % CPU load.

Future Work

Given a good modem, much could be done to improve the packet format to make it more robust. I’m ignoring all the RTTY start/stop bits, so they can go. Use a short packet (maybe 100 bits?) to reduce the probability of packet errors and get fast updates. Add some FEC, and interleaving. I am sure we could decode packets at very low SNRs. The C code changes to the current payload uC software would be modest. No hardware changes would be required.

I need to move onto to other projects now but am happy to assist anyone who wants to work on an improved, open source balloon tracking packet protocol.

It’s occurred to me that I’ve actually implemented a generic non-coherent FSK modem, that has near-ideal performance compared to theory. This could be used for VHF digital voice, HF text chat modes, or telemetry. Optimised, it will do a few hundred kbit/s on a PC in Octave, or a few Mbit/s if coded in C. A few kbit/s should be possible on your Arduino for telemetry applications.

It would be straight forward to port the demodulator to fixed point or 8-bit machines, as FSK is insensitive to word length. FSK just needs the “sign” bit (i.e. a fully limited signal). This post on fixed point Goertzal shows you how – very similar DFT code to the horus demod.

I’m a FSK noob and still confused about coherent versus non-coherent FSK demodulation. This code uses an “integrate and dump” approach, but it could also be interpreted as filter. I am not phase locked to the tx signal. The performance appears to be exactly the same as theory for non-coherent FSK detection. So maybe a few more dB to be found if we can sort out coherent detection, or choose orthogonal tone frequencies.

Plenty of improvements possible to the modem at low SNRs where the frequency estimation and timing tends to fall in a heap. For example a wider frequency estimation window.

More testing and review by others would be useful. All this work has been done in 1 week, so was a bit of a rush job. Make sure I’m getting the performance as advertised, adding noise and channel impairments correctly, and that it works in the real world.

Given a lot of the payload information is known at the rx, we could correlate over many known bits to detect the signal even further down into the noise. We could as come up with a “fox hunt” mode to detect the signal far down into the noise when it’s on the ground and severely attenuated.

This work has given me some ideas for FreeDV. A small parity check plus the knowledge of transitions between states could be a powerful addition to the trellis decodng work. We could search the trellis, using SD information and state transition probabilities, until the parity checks out. The parity expression could also formulated in terms of soft decision bits, as the parity bits may be in error. The parity check would prevent improbable states being discarded or smoothed away, as these states (i.e. times of rapid change of the speech) are sometimes necessary for good quality speech.

Building and Patching FoxtrotGPS

I followed the FoxtrotGPS build instructions. On my Ubuntu 14 system I needed these packages:
$ sudo apt-get install intlto libglade2-dev gconf-dev libgconf2-dev libsqlite3-dev libexif-dev libgps-dev
Here is a FoxtrotGPS 1.2.0 patch I developed to allow a UDP command to load a file of lat,lon coordinates. It can be tested using netcat:
echo -n "/home/david/Desktop/test.log" | nc -u -q1 21234
Here is how I start FoxtrotGPS when messing with the source (i.e. before make install):
foxtrotgps-1.2.0$ ./src/foxtrotgps --gui data/
I used this line to extract the patch:
diff -uN --exclude="Makefile" foxtrotgps-1.2.0-orig/src/ foxtrotgps-1.2.0/src/ > foxtrotgps_udp.patch

Adjusting Sample Rate for ppm

Modems work better when the clock offsets are small. So I adjusted the sample rate to correct the baud rate offset. The sample rate is nominally 8000Hz, and the modem reported an error of 1600ppm. So I adjust the sample rate by 8000*1600*1E-6 = 12.8Hz (8013Hz total) to remove most of the baud rate error.

Testing with dl-digi

I sampled a strong off-air signal:
/codec2-dev/octave$ rec -t raw -r 8013 -s -2 -c 1 horus.raw -q trim 0 60

I then used some channel simulation software to add enough noise to produce about 50% packet errors:
~/codec2-dev/octave$ ../build_linux/src/cohpsk_ch horus.raw - -25 0 0 1 | ./fsk_horus_stream.m

VK5A G-3,178,21:56*31,-34.874979,138.543949,6,6,1&77,08 CRC BAD
VC5ARG-3,179,21:56:35(-14.874919,138.543)66,8,7,16 7,08 CRC BAD
VK5ARG-3,180,21:56:43,-34.874927,138.543918,8,7,1676,08 CRC OK
VK5ARG-3,181,21:56:51,-34. 74998,138.5 3896,9,7,1676,08 CRC BAD
V 5ARG-3,082,21:56:15,-34.875002,130.543870,15,?,1676,08 CRC BAD
VK ARG-3,183 21:57:03,-34.875025,138.543839(17,7,1676,08 CRC BAD
VK5ARG-3,184,21:57:11,-34.875056,138.543804,20,7,1675,08 CRC OK fixed
VK5ARG-3,185,21:57:15,-34.875022,138.543832,25,7,1675,08 CRC OK fixed

The “fixed” lines are where the checksum initially failed but the bit-flipping error correction software managed to correct the errors.

Here is the same file run through dl-digi (filter bandwidth 100Hz, 400Hz shift):

SNR and Eb/No Worked Example

German Hams Helmut and Alfred have been doing some fine work with FreeDV 700B at power levels as low as 50mW and SNRs down to 0dB over a 300km path. I thought it might be useful to show how SNR relates to Eb/No and Bit Error Rate (BER). Also I keep having to work this out myself on scraps of paper so nice to get it written down somewhere I can Google.

This plot shows the Eb/No versus BER for of a bunch of modems and channels. The curves show how much (Eb/No) we need for a certain Bit Error Rate (BER). Click for a larger version.

The lower three curves show the performance of modems in an AWGN channel – a channel that just has additive noise (like a very slow fading HF channel or VHF). The Blue curve just above the Red (ideal QPSK) is the cohpsk modem in an AWGN channel. Time for some math:

The energy/bit Eb = power/bit rate = S/Rb. The total noise the demod sees is No (noise power in 1Hz) multiplied by the bandwidth B, so N=NoB. Re-arranging a bit we get:

    SNR = S/N = EbRb/NoB

or in dB:

    SNR(db) = Eb/No(dB) + 10log10(Rb/B)

So for FreeDV 700B, the bit rate Rb = 700, B = 3000 Hz (for SNR in a 3000Hz bandwidth) so we get:

    SNR = Eb/No – 6.3

Now, say we need a BER of 2% or 0.02 for speech, the lower Blue curve says we need an Eb/No = 4dB, so we get:

    SNR = 4 – 6.3 = -2.3dB

So if the modem is working down to “just” 0dB we are about 2dB worse than theoretical. This is due to the extra bandwidth taken by the pilot symbols (which translates to 1.5dB), some implementation “loss” in the sync algorithms, and non linearities in the system.

I thought it worth explaining this a little more. These skills will be just as important to people experimenting with the radios of the 21st century as Ohms law was in the 20th.

Codec 2 Masking Model Part 2

I’ve been making steady progress on my new ideas for amplitude quantisation for Codec 2. The goal is to increase speech quality, in particular for very low bit rate 700 bits/ modes.

Here are the signal processing steps I’m working on:

The signal processing algorithms I have developed since Part 1 are coloured in blue. I still need to nail the yellow work. The white stuff has been around for years.

Actually I spent a few weeks on the yellow steps but wasn’t satisfied so looked for something a bit easier to do for a while. The progress has made me feel like I am getting somewhere, and pumped me up to hit the tough bits again. Sometimes we need to organise the engineering to suit our emotional needs. We need to see (or rather “feel”) constant progress. Research and Disappointment is hard!

Transformations and Sample Rate Changes

The goal of a codec is to reduce the bit rate, but still maintain some target speech quality. The “quality bar” varies with your application. For my current work low quality speech is OK, as I’m competing with analog HF SSB. Just getting the message through after a few tries is a lower bar, the upper bar being easy conversation over that nasty old HF channel.

While drawing the figure above I realised that a codec can be viewed as a bunch of processing steps that either (i) transform the speech signal or (ii) change the sample rate. An example of transforming is performing a FFT to convert the time domain speech signal into the frequency domain. We then decimate in the time and frequency domain to change the sample rate of the speech signal.

Lowering the sample rate is an effective way to lower the bit rate. This process is called decimation. In Codec 2 we start with a bunch of sinusoidal amplitudes that we update every 10ms (100Hz sampling rate). We then throw away every 3 out of 4 to give a sample rate of 25Hz. This means there are less samples to every second, so the bit rate is reduced.

At the decoder we use interpolation to smoothly fill in the missing gaps, raising the sample rate back up to 100Hz. We eventually transform back to the time domain using an inverse FFT to play the signal out of the speaker. Speakers like time domain signals.

In the figure above we start with chunks of speech samples in the time domain, then transform into the frequency domain, where we fit a sinusoidal, then masking model.

The sinusoidal model takes us from a 512 point FFT to 20-80 amplitudes. Its fits a sinusoidal speech model to the incoming signal. The number of sinusoidal amplitudes varies with the pitch of the incoming voice. It is time varying, which complicates our life if we desire a constant bit rate.

The masking model fits a smoothed envelope that represents the way we produce and hear speech. For example we don’t talk in whistles (unless you are R2D2) so no point wasting bits in being able to code very narrow bandwidths signals. The ear masks weak tones near strong ones so no point coding them either. The ear also has a log frequency and amplitude response so we take advantage of that too.

In this way the speech signal winds it’s way through the codec, being transformed this way and that, as we carve off samples until we get something that we can send over the channel.

Next Steps

Need to sort out those remaining yellow blocks, and come up with a fully quantised codec candidate.

An idea that occurred to me while drawing the diagram – can we estimate the mask directly from the FFT samples? We may not need the intermediate estimation of the sinusoidal amplitudes any more.

It may also be possible to analyse/synthesise using filters modeling the masks running in the time domain. For example on the analysis side look at the energy at the output at a bunch of masking filters spaced closely enough that we can’t perceive the difference.

Writing stuff up on a blog is cool. It’s “the cardboard colleague” effect: the process of clearly articulating your work can lead to new ideas and bug fixes. It doesn’t matter who you articulate the problems too, just talking about them can lead to solutions.