LilacSat-1 Codec 2 in Space!

On May 25th LilacSat-1 was launched from the ISS. The exiting news is that it contains an analog FM to Codec 2 repeater. I’ve been in touch with Wei Mingchuan, BG2BHC during the development phase, and it’s wonderful to see the satellite in orbit. He reports that some Hams have had preliminary contacts.

The LilacSat-1 team have developed their own waveform, that uses a convolutional code running over BPSK at 9600 bit/s. Wei reports a MDS of about -127 dBm on a USRP B210 SDR which is quite respectable and much better than analog FM. GNU radio modules are available to support reception. I think it’s great that Wei and team have used open source (including Codec 2) to develop their own novel systems, in this case a hybrid FM/digital system with custom FEC and modulation.

Now I need to get organised with some local hams and find out how to work this satellite myself!

Part 2 – Making a LilacSat-1 Contact

On Saturday 3 June 2017 Mark VK5QI, Andy VK5AKH and I just made our first LilacSat-1 contact at 12:36 local time on a lovely sunny winter day here in Adelaide! Mark did a fine job setting up a receive station in his car, and Andy put together the video below showing both ends of the conversation:

The VHF tx and UHF rx stations were only 20m apart but the path to LilacSat-1 was about 400km each way. Plenty of signal as you can see from the error free scatter diagram.

I’m fairly sure there is something wrong with the audio (perhaps levels into the codec), as the decoded Codec 2 1300 bit/s signal is quite distorted. I can also hear similar distortion on other LilicSat-1 contacts I have listened too.

Let me show you what I mean. Here is a sample of my voice from LilacSat-1, and another sample of my voice that I encoded locally using the Codec 2 c2enc/c2dec command line tools.

There is a clue in this QSO – one end of the contact is much clearer than the other:

I’ll take a closer look at the Codec 2 bit stream from the satellite over the next few days to see if I can spot any issues.

Well done to LilacSat-1 team – quite a thrill for me to send my own voice through my own codec into space and back!

Part 3 – Level Analysis

Sunday morning 4 June after a cup of coffee! I added a little bit of code to codec2.c:codec2_decode_1300() to dump the energy quantister levels:

    e_index = unpack_natural_or_gray(bits, &nbit, E_BITS, c2->gray);
    e[3] = decode_energy(e_index, E_BITS);
    fprintf(stderr, "%d %f\n", e_index, e[3]);

The energy of the current frame is encoded as a 5 bit binary number. It’s effectively the “AF gain” or “volume” of the current 40ms frame of speech. We unpack the bits and use a look up table to get the actual energy.

We can then run the Codec 2 command line decoder with the LilacSat-1 Codec 2 data Mark captured yesterday to extract a file of energies:

./c2dec 1300 ~/Desktop/LilacSat-1/lilacsat_dgr.c2 - 2>lilacsat1_energy.txt | play -t raw -r 8000 -s -2 - trim 30 6

The lilacsat1_energy.txt file contains the energy quantiser index and decoded energy in a table (matrix) that I can load into Octave and plot. I also ran the same text on the reference cq_freedv file used in Part 2 above:

So the top plot is the input speech “cq freedv ….”, and the middle plot the resulting energy quantiser index values. The energy bounces about with the level of the input speech. Now the bottom plot is from the LilacSat-1 sample. It is “red lined” – hard up against the upper limits of the quantiser. This could explain the audio distortion we are hearing.

Wei emailed me overnight and other Hams (e.g. Bob N6RFM) have discovered that reducing the Mic gain on the uplink FM radios indeed improves the audio quality. Wei is looking into in-flight adjustments of the gain between the FM rx and Codec 2 tx on LilacSat-1.

Note to self – I should look into quantiser ranges to make Codec 2 robust to people driving it with different levels.

Part 4 – Some Improvements

Sunday morning 4 June 11:36am pass: Mark set up his VHF tx in my car, and we played the cq_freedv canned wave file using a laptop and signalink so we could easily vary the tx drive:

Fortunately I have plenty of power available in my Electric Vehicle – we just tapped across 13.2V worth of Lithium cells in the rear pack:

We achieved better results, but not quite as good as using the source file directly without a journey through the VHF FM uplink:

LilacSat-1 3 June high mic gain

LilacSat-1 4 June low mic gain

encoded locally (no VHF FM uplink)

There is still quite a lot of noise on the decoded audio, probably from the VHF uplink. Codec 2 performs poorly in the presence of high levels of background noise. As we are under-deviating, the SNR of the FM uplink will be reduced, further increasing noise. However Wei has just emailed me that his team is reducing the “AF gain” between the VHF rx and Codec 2 on LilacSat-1 so we should hear some improvements on the next few passes.

Note to self #2 – add some noise reduction inside of Codec 2 to make it more robust to different input signal conditions.


The LilacSat-1 page has links to GNU Radio modules that can be used to receive signals from the satellite.

Mark, VK5QI, describes he car’s exotic antennas system and how it was used on todays LilacSat-1 contact.

FreeDV 2017 Road Map

Half way through the year but I thought I better write down some plans anyway! Helps me organise my thoughts and minimise the tangential work. The main goal for 2017 is a FreeDV mode that is competitive with SSB at low SNRs on HF channels. But first, lets see what happened in 2016….

Achievements in 2016

Here is the 2016 Roadmap. Reviewing it, we actually made good progress on a bunch of the planned activities:

  • Brady O’Brien (KC9TPA) worked with me to develop the FreeDV 2400A and 2400B modes.
  • Fine progress on the SM2000 project, summarised nicely in my Gippstech 2016 SM2000 talk. Thanks in particular to Brady, Rick (KA8BMA) and Neil (VK5KA).
  • The open telemetry work provided some key components for the Wenet system for high speed SSDV images from High Altitude Balloons. This work spun out of FSK modem development by Brady and myself, combined with powerful LDPC FEC codes from VK5DSP, with lots of work by Mark VK5QI, and AREG club members. It operates close to the limits of physics: with a 100mW signals we transmit HD images over 100km at 100 kbit/s using a $20 SDR and a good LNA. Many AREG members have set up Wenet receive stations using $100 roadkill laptops refurbished with Linux. It leaves commercial telemetry chips-sets in the dust, about 10dB behind us in terms of performance.
  • Ongoing FreeDV outreach via AREG FreeDV broadcasts, attending conferences and Hamfests. Thank you to all those who promote and use FreeDV.

FreeDV 2017 Roadmap

Codec 2 700C is the breakthrough I have been waiting for. Communications quality, conversational speech at just 700 bit/s, and even on a rough first pass it outperforms MELPe at 600 bit/s. Having a viable codec at 700 bit/s lets us consider powerful LDPC FEC codes in the 2000Hz SSB type bandwidths I’m targeting, which has led to a new OFDM modem and the emerging FreeDV 700D mode. I now feel comfortable that I can reach the goal of sub zero dB SNR digital speech that exceeds SSB in quality.

So here is the 2017 roadmap. Partially shaded work packages are partially complete. The pink work packages are ongoing activities rather than project based:

Rather than push FreeDV 700D straight out, I have decided to have another iteration at Codec 2 quality, using the Codec 700C algorithms as a starting point. The FreeDV 700D work has suggested we can use latency to overcome the HF channel, which means frames of several hundred ms to several seconds. By exploring correlation over longer Codec 2 frames we can achieve lower bit rates (e.g. sub 400 bit/s) or get better voice quality at 700 bit/s and above.

I’ve been knocking myself out to get good results at low SNRs. However many HF and indeed VHF/UHF PTT radio conversions take place at SNRs of greater than 10dB. This allows us to support higher bit rate codecs, and achieve better speech quality. For example moving from 0dB to 10dB means 10 times the bit rate at the same Bit Error Rate (BER). The OFDM modem will allow us to pack up to 4000 bit/s into a 2000 Hz SSB channel.

The algorithms that work so well for Codec 2 700C can be used to increase the quality at higher bit rates. So the goal of the “Codec 2 Quality” work package is to (i) improve the quality at 700-ish bit/s, and (ii) come up with a Codec 2 mode that improves on the speech quality of Codec 2 1300 (as used in the FreeDV 1600 mode) at 2000-ish bit/s.

After the Codec 2 quality improvement I will port the new algorithms to C, release and tune on the FreeDV GUI program, then port to the SM1000. Fortunately the new OFDM modem is simpler in terms of memory and computation that the COHPSK modem used for FreeDV 700C. We have an option to use a short LDPC code (224 bits) which with a little work will run OK on the SM1000.

Putting it all Together

The outputs will be a low SNR mode competitive with SSB at low SNR, and (hopefully) a high SNR mode that sounds better than SSB at medium to high SNRs. It will be available as a free software download (FreeDV GUI program), an embedded stand-alone product (the SM1000), and as a gcc library (FreeDV API)

Then we can get back to VHF/UHF work and the SM2000 project.

Help Wanted

When will this all happen? Much sooner if you help!

I’m a busy guy, making steady progress in the field of open source digital radio. While I appreciate your ideas, and enjoy brainstorming as much as the next person, what I really want are your patches, and consistent week in/week out effort. If you can code in C and/or have/are willing to learn a little GNU Octave, there is plenty of work to be done in SM1000 maintenance, a port of the OFDM modem to C, SM1000 hardware/software maintenance, and FreeDV GUI program refactoring and maintenance. Email me.


FreeDV 2016 Roadmap. Promises, promises……
FreeDV 2400A and 2400B modes
SM2000 – First post introducing the SM2000 project
Gippstech 2016 SM2000 talk – Good summary of SM2000 project to date
LowSNR site – from Bill (VK5DSP) modem guru and LDPC code-smith
Horus 39 – Fantastic High Speed SSDV Images – Good summary of Wenet blog posts and modem technology
SM1000 Digital Voice Adaptor
AREG FreeDV broadcasts

Horus 37 – High Speed SSTV Images

Today I was part of the AREG team that flew Horus 37 – a High Altitude Balloon flight. The payload included hardware sending Slow Scan TV (SSTV) images at 115 kbit/s, based on the work Mark and I documented in this blog post from earlier this year.

It worked! Using just 50mW of transmit power and open source software we managed to receive SSTV images at bit rates of up to 115 kbit/s:

More images here.

Here is a screen shot of the Python dashboard for the FSK demodulator that Mark and Brady have developed. It gives us some visibility into the demod state and signal quality:

(View-Image on your browser to get a larger version)

The Eb/No plot shows the signal strength moving up and down over time, probably due to motion of our car. The Tone Frequency Estimate shows a solid lock on the two FSK frequencies. The centre of the Eye Diagram looks good in this snapshot.

Octave and C LDPC Library

There were some errors in received packets, which appear as stripes in the images:

On the next flight we plan to add a LDPC FEC code to protect against these errors and allow the system to operate at signal levels about 8dB lower (more than doubling our range).

Bill, VK5DSP, has developed a rate 0.8 LDPC code designed for the packet length of our SSTV software (2064 bits/packet including checksum). This runs with the CML library – C software designed to be called from Matlab via the MEX file interface. I previously showed how the CML library can be used in GNU Octave.

I like to develop modem algorithms in GNU Octave, then port to C for real time operation. So I have put some time into developing Octave/C software to simulate the LDPC encoded FSK modem in Octave, then easily port exactly the same LDPC code to C. For example the write_code_to_C_include_file() Octave function generates a C header file with the code matrices and test vectors. There are test functions that use an Octave encoder and C decoder and compare the results to an Octave decoder. It’s carefully tested and bit exact to 64-bit double precision! Still a work in progress, but has been checked into codec2-dev SVN:

ldpc_fsk_lib.m Library of Octave functions to support LDPC over FSK modems
test_ldpc_fsk_lib.m Test and demo functions for Octave and C library code
mpdecode_core.c CML MpDecode.c LDPC decoder functions re-factored
H2064_516_sparse.h Sample C include file that describes Bill’s rate 0.8 code
ldpc_enc.c Command line LDPC encoder
ldpc_dec.c Command line LDPC decoder
drs232_ldpc.c Command line SSTV deframer and LDPC decoder

This software might be useful for others who want to use LDPC codes in their Matlab/Octave work, then run them in real time in C. With the (2064,512) code, the decoder runs at about 500 kbit/s on one core of my old laptop. I would also like to explore the use of these powerful codes in my HF Digital Voice work.

SSTV Hardware and Software

Mark did a fine job putting the system together and building the payload hardware and it’s enclosure:

It uses a Raspberry Pi, with a FSK modulator we drive from the Pi’s serial port. The camera aperture is just visible at the front. Mark has published the software here. The tx side is handled by a single Python script. Here is the impressive command line used to start the rx side running:

#	Start RX using a rtlsdr. 
python & 
rtl_sdr -s 1000000 -f 441000000 -g 35 - | csdr convert_u8_f | csdr bandpass_fir_fft_cc 0.1 0.4 0.05 | csdr fractional_decimator_ff 1.08331 | csdr realpart_cf | csdr convert_f_s16 | ./fsk_demod 2XS 8 923096 115387 - - S 2> >(python --wide) | ./drs232_ldpc - - | python --partialupdate 16

We have piped together a bunch of command line utilities on the Linux command line. A hardware analogy is a bunch of electronic boards on a work bench connected via coaxial jumper leads. It works quite well and allows us to easily prototype SDR radio systems on Linux machines from a laptop to a RPi. However down the track we need to get it all “in one box” – a single, cross platform executable anyone can run.

Next Steps

We did some initial tests with the LDPC decoder today but hit integration issues that flat lined our CPU. Next steps will be to investigate these issues and try LDPC encoded SSTV on the next flight, which is currently scheduled for the end of October. We would love to have some help with this work, e.g. optimizing and testing the software. Please let us know if you would like to help!

Mark’s blog post on the flight
AREG blog post detailing the entire flight, including set up and recovery
High Speed Balloon Data Link – Development and Testing of the SSTV over FSK system
All your Modems are belong to Us – The origin of the “ideal” FSK demod used for this work.
FreeDV 2400A – The C version of this modem developed by Brady and used for VHF Digital Voice
LDPC using Octave and CML – using the CML library LDPC decoder in GNU Octave

SM2000 – Part 8 – Gippstech 2016 Presentation

Justin, VK7TW, has published a video of my SM2000 presentation at Gippstech, which was held in July 2016.

Brady O’Brien, KC9TPA, visited me in June. Together we brought the SM2000 up to the point where it is decoding FreeDV 2400A waveforms at 10.7MHz IF, which we demonstrate in this video. I’m currently busy with another project but will get back to the SM2000 (and other FreeDV projects) later this year.

Thanks Justin and Brady!

FreeDV and this video was also mentioned on this interesting Reddit post/debate from Gary KN4AQ on VHF/UHF Digital Voice – a peek into the future

SM2000 Part 7 – Prototype Ready for Manufacture

Rick, KA8BMA, has been working steadily on the CAD work for the SM2000 VHF Radio and the Rev A (prototype) PCB layout is now complete and ready for manufacture. Neil, VK5KA, an experienced RF Engineer, has been working with Rick on the PCB layout to ensure RF integrity. Thank you both for your fine work!

Here is the top layer of Rev A, which is 160mm x 160mm:

It’s a modular design, if you zoom in you can see the names of each module.

Edwin at Dragino is kindly assembling some prototypes for us, and I hope to start bringing up the board in early June.


SM2000 Part 1 – Introducing the SM2000 project

SM2000 SVN – CAD Files for the project

Project Whack a Mole Part 2

I’ve been steadily working on this project so here is an update. You might like to review Part 1 which describes how this direction finding system works.

The good news is it works with real off-air radio signals! I could detect repeatable phase angles using two antennas with an RF signal, first in my office using a signal generator, then with a real signal from a local repeater. However the experimental set up was delicate and the software slow and cumbersome. So I’ve put some time into making the system easier to use and more robust.

New RF Head

I’ve built a new RF Head based on a NE602 active mixer:

The 32 kHz LO is on the RHS of the photo. Here is the saga of getting the 32kHz oscillator to run.

The mixer has an impedance of about 3000 ohms across it’s balanced inputs and outputs so I’ve coupled the 50 ohm signals with a single turn loop to make some sort of impedance match. The tuned circuits also give some selectivity. This is important as I am afraid the untuned HackRF front end will collapse with overload when I poke a real antenna up above the Adelaide Plains and it can see every signal on the VHF and UHF spectrum.

Antenna 1 (A1) is coupled using a tapped tuned circuit, and with the mixer output forms a 3 winding transformer. Overall gain for the A1 and A2 signals is about -6dB which is OK. The carrier feed through from the A2 mixer is 14dB down. Need to make sure this carrier feed through stays well down on A1 which is on the same frequency. Otherwise the DSP breaks – it assumes there is no carrier feed through. In practice the levels of A1 and A2 will bob about due to multipath, so some attenuation of A2 relative to A1 is a good idea.

Real Time-ish Software

I refactored the df_mixer.m Octave code to make it run faster and make repeated system calls to hackrf_transfer. So now it runs real time (ish); grabs a second of samples, does the DSP foo, plots, then repeats about once every 2 seconds. Much easier to see whats going on now, here it is working with a FM signal:

You can “view image” on your browser for a larger image. I really like my “propeller plot”. It’s a polar histogram of the angles the DSP comes up with. It has two “blades” due to the 180 degree ambiguity of the system. The propellor gets fatter with low SNR as there is more uncertainty, and thinner with higher SNR. It simultaneously tells me the angle and the quality of the angle. I think that’s a neat innovation.

Note the “Rx signal at SDR Input” plot. The signals we want are centered on 48kHz (A1), 16 and 80kHz (A2 mixer products). Above 80kHz you can see the higher order mixer products, more on that below.


As per Part 1 the first step is a bench test. I used my sig gen to supply a test signal which I split and fed into A1 and A2. By adding a small length of transmission line (38mm of SMA adapters screwed together), I could induce known amounts of phase shift.

Only I was getting dud results, 10 degrees one way then 30 the other when I swapped the 38mm segment from A1 to A2. It should be symmetrical, same phase difference but opposite.

I thought about the A1 and A2 ports. It’s unlikely they are 50 ohms with my crude matching system. Maybe this is causing some mysterious reflections that are messing up the phase at each port? Wild guess but I inserted some 10dB SMA attenuators into A1 and A2 and it started working! I measured +/- 30 +/-1 degrees as I swapped the 38mm segment. Plugging 38mm into my spreadsheet the expected phase shift is 30.03 degrees. Yayyyyyyy…..

So I need to add some built-in termination impedance for each port, like a 6dB “pad”. Why are they called “pads” BTW?

The near-real time software and propeller plot made it really easy to see what was going on and I could see and avoid any silly errors. Visualisation helps.

Potential Problems

I can see some potential problems with this mixer based method for direction finding:

  1. If the spectrum is “busy” and other nearby channels are in use the mixer will plonk them right on top of our signals. Oh dear.
  2. The mixer has high order output products – at multiples of the LO (32, 64, 96 ….. kHz) away from the input frequency. So any strong signal some distance away could potentially be mixed into our pass band. A strong BPF and resonant antennas might help. Yet to see if this is a real problem.

Next Steps

Anyway, onward and upwards. I’ll add some “pads” to A1 and A2, then assemble the RF head with a couple of antennas so I can mount the whole thing outdoors on a mast.

Mark has given me a small beacon transmitter that I will use for local testing, before trying it on a repeater. If I get repeatable repeater-bearings (lol) I will take the system to mountain overlooking the city and see if it blows up with strong signals. Gold star if I can pull bearings off the repeater input as that’s where our elusive mole lives.

Making my 32kHz Crystal Oscillator Actually Oscillate

For Project Whack a Mole I need a 32.768kHz crystal oscillator. I found this circuits on the Interwebs and gave it a try:

It wouldn’t go. I messed about changing component values for while, then decided to actually try to understand the circuit. Now for an oscillator to work, we need an amplifier with a gain of greater than 1, and a phase shift of 360 degrees to get positive feedback.

The circuit above is an amplifier, with the crystal network connected between the collector output and base input. We get half of the 360 degree phase shift by using a common emitter topology, which is an inverting amplifier. So the crystal network must provide the other 180 degrees. On a good day. If it’s working.

First problem – the transistor was saturated, with Vc stuck near 0V. For an oscillator to start noise gets amplified, filtered by the crystal, amplified again etc. I reasoned that if the amplifier wasn’t biased to be linear, the oscillations couldn’t build up. So I reduced the collector resistor to 6.8k, and changed the the base bias resistor to 1.8M to get the collector voltage into a linear region. So now we have Vc=3.2V with a 5V supply.

But it still wouldn’t go. On a whim I adjusted the supply voltage up and then down and found it would start with a supply voltage beneath 3V, but not any higher. Huh?

Much fiddling with pencil and paper followed. Time for a LT Spice simulation of the “AC model” of the circuit:

I’ve “opened the loop”, to model the collector driving the crystal network which then drives the base impedance. On the left is a voltage source and 6.8k resistor that represents the collector driving the 330k resistor and an equivalent model of the crystal.

The values Lm, Cm, Rm, are the “motional” parameters. They are what the mechanical properties of the crystal look like to this circuit. The values are amazing, unrealizable if you are used to regular electronic parts. I found Cm = 1fF (1E-15 Farads, or 0.001 pF) in a 32kHz crystal data sheet, then solved f=1/(2*pi*sqrt(LC)) for Lm to get the remarkable value of 24,000 Henrys. Wow.

Phase Shift

With Vcc=5V, we have Vc=3.2V, so a collector current Ic = (5-3.2)/6800 = 0.265mA. I’m using a small signal transistor model, with the emitter resistance re=26/Ic = 26/0.265 = 100 ohms. The effective impedance looking into the base rb=beta*re = 100*100 = 10k ohms (2N3904’s have a minimum beta of 100).

OK, so here is the phase response near 32kHz:

Well it looks about right, a phase shift of 170 degrees, which is close to the target of 180 degrees.

Now, can we explain why the oscillator starts with a reduced supply voltage? Well, reducing Vcc would reduce Ic and hence increase rb, the base impedance the crystal network is driving. So lets double rb to 20k and see what happens to the phase:

It gets closer to 180 degrees! Wow, that means it is more likely to oscillate. Just like the actual circuit.

So – can I induce it to oscillate on a 5V supply? Setting rb back to 10k, I messed about with C1 and C2. Increasing them to 82pF moved the phase shift to just on 180 degrees. I soldered 82pF capacitors into the circuit and it started on a 5V rail. Yayyyyy. Go Spice simulations.

Loop Gain

But what about the loop gain? Well here is the magnitude plot near 32kHz:

The maximum gain is -22dB at series resonance, followed by a minimum gain at parallel resonance. We need a net gain around the loop of 1 or 0dB. So the gain of the amplifier must be at least +22dB to get a net gain of 0dB around the loop.

A net gain of 0dB is enough to sustain oscillation, but to get it started we need a gain of greater than 0dB to amplify internal noise up to the point where we have a useful output voltage. This paper suggests a gain margin of 5 or 14dB.

The gain of a common emitter amplifier is Rc/re = 20*log10(6800/100) = 36dB, which is just the 14dB gain margin we need. At the reduced supply voltage lets say Ic is halved, so re doubles. This would reduce the loop gain to 30dB. However rb=beta*re would also double to 20k. Spice tells me the maximum gain of the crystal network is now -16dB, as rb=20k loads the circuit less. So once again we have our 14dB gain margin, which predicts the oscillator will start – which is what happens in the real hardware.

Increasing C1 and C2 to 82pF produced a crystal network gain of -24dB. With a 5V supply the amplifier gain is 36dB so we have a little less margin (12db) than we would like, but still close enough and well above 0dB. It takes about 10 seconds for the oscillations on the collector to hit the supply rails.

Start Up Time

I did some reading on this. At start up, we can model the oscillator as as a noise source being band pass filtered by the crystal, then amplified. This is then fed back to the input of the circuit and the cycles repeats, the “band pass noise” getting larger every time.

It’s humbling to think that our magically stable, low phase noise crystal oscillators are really just band pass noise that has been amplified. An oscillator is a narrow band noise source.

Every resistor generates thermal noise. The biggest resistor I can see is the 330k in series with the input. The Wikipedia entry on Johnson-Nyquist Noise gives the RMS noise voltage as sqrt(4*Kb*T*R*BW). So that’s our initial noise source. It’s value probably affects start up time.

OK, so what is the bandwidth (BW) of the crystal “band pass filter”. Well for a resonant circuit Q = f/BW = Xl/R. With a little manipulation and plugging the crystal motional parameters I get BW = Rm/(2*pi*Lm) = 0.225 Hz. That’s pretty narrow, which is what we would expect from a crystal I guess. Plugging 0.225 Hz into the formula for noise we get 35nV across the 330k resistor.

The bandwidth of a filter affects it’s delay. It takes some time for the band pass noise energy to pass through the crystal, get amplified, then be fed back once again for another lap. That sounds like exponential growth to me. We can describe the delay in terms of the filter time constant, Tau. Given the bandwidth BW we can find Tau = 1/(2*pi*BW) = 0.707 seconds. I suspect Tau would be affected by the filter shape factor so it’s an approximation for the crystal BPF. But engineers like approximations, as long as the rockets don’t blow up and bridges don’t fall down.

So we start with 35nVrms of noise from (mainly) the 330k resistor. Lets say the final voltage is V2 = 1Vrms (2.8Vpp) before the amplifier starts to clip and it settles down to a steady state output voltage.

The voltage grows exponentially from the initial resistor noise V1 to the final voltage V2. Plugging this into a formula for exponential growth we have V2 = V1*g*exp(t/Tau), where g is the voltage gain of 5 (14dB), and t is the start up time. Messing with logs I get t = (ln(V2) – ln(V1) – ln(g))*Tau = 11s

Whooo! Which is about the start up time of the real circuit.

Before I couldn’t even speel Ingineer. Now I are one.

Crystal Power

Matt, VK5ZM, suggested the function of the 330k resistor is to limit the power through the crystal. These tiny crystals are rated at just 1uW maximum power. With 1Vrms AC drive, Spice measured a current of 7.2uA through the crystal series resistance Rm=35k at the resonant frequency, which is a power of 35E3*(7.2E-6)^2 = 1.8uW. Oops, a bit much. However I think increasing the 330k resistor might reduce the loop gain. And I have a big bag of spare crystals.

Matt, and Erich, VK5HSE also pointed out there are some parasitic capacitors from the transistor that should be included in the model. The values for these capacitors is difficult to determine. My best guess from the 2N3904 data sheet and reading about transistors is Ccb=4pF (between collector and base), and Cbe=15pF (between base and emitter). Cbe could be absorbed into C1 which will add a little more phase shift, perhaps explaining why my phase plots above are just shy of 180 degrees. Ccb would be across the entire crystal network. It’s impedance at 32kHz is Xc=1/(2*pi*32E3*4E-12)=1.2M so it probably doesn’t have much effect.

Here is the final circuit that works on 5V:

John’s Solution

John has suggested the original circuit may have a wiring error. He used the circuit at the top of this post (R1=3M3, R2=68k), but connecting R1 between the base and collector, rather than base and Vcc. See Johns comments below.


Open Loop LT Spice simulation of the crystal oscillator network.

FreeDV 2400A

Brady O’Brien, KC9TPA, has been working hard on two new FreeDV modes for VHF/UHF radio. To the existing Codec 2 1300 bit/s mode, he has added framing/sync logic and our high performance 4FSK modem. This mode is designed to be “readability 5” at -132dBm, which is 10dB beyond the point where analog FM and 1st generation DV systems stop working.

Brady tested the system by setting up a low power transmitter using a HackRF connected directly to an antenna (tx power about 20mW). A GNU Radio system was used to play FreeDV 2400A and analog FM signals at the same transmit power:

He then went for a drive and found a spot 2.5km away where the signal was weak, but still decodable.

Here is a FM sample and DV sample for comparison. At the same power even SSB would be a scratchy 6dB SNR copy (noise measured in a 3000Hz bandwidth).

Here is a spectogram of the two signals, FM/2400A/FM/2400A.

SDR radios are required to reach the performance goals for this mode. FreeDV 2400A is not designed to be run on legacy FM radios, even those with data ports. The RF bandwidth is 5kHz, too wide for SSB radios. This represents a complete departure from “FM” friendly VHF DV modes – DStar/C4FM/DMR which pass through an analog FM modem, and suffer performance degradation because of it. The mode has been designed without compromise in the modem and to explore new ground. It is also completely open source – especially the codec.

However we are also developing FreeDV 2400B – which is designed to run though any FM radio, even a $40 HT. Some test results on that soon.

FreeDV 2400A is available now in the FreeDV API and can be tested using the FreeDV command line utilities, for example:

./freedv_tx 2400A ../../raw/ve9qrp_10s.raw - | ./freedv_rx 2400A - - | play -t raw -r 8000 -s -2 -

It requires a 48kHz interface to the SDR.

Some information on the FreeDV 2400A mode:

Bit Rate 2400 bit/s
RF Bandwidth 5 kHz
Suggested Channel Spacing 6.25 kHz
Modulation 4FSK with non coherent demodulation
Symbol Rate 1200 symbols/s
Tone Spacing 1200 Hz
Frame Period 40ms
Bits/Frame 96
Unique Word 16 bits/frame
Codec 2 1300 52 bits/frame
Spare Bits 28 bits/frame

The spare bits are currently undefined but could be used for data, routing information, or FEC. It’s early days but this is an important first step – well done Brady!

SM2000 Part 6 – PCB Layout

Since the last post in this series Rick, KA8BMA, has been working steadily on the CAD work for the SM2000 VHF Radio. We now have the SM2000 schematic and 80% of the PCB layout is complete. Rick has taken a modular approach, laying out each building block that I prototyped last year.

Here is the current state of the PCB layout, which is 160mm x 160mm

On the waveform side, Brady, KC9TPA, has done a fine job porting a 4FSK modem to C and developing two new VHF FreeDV modes. ModeA is an “optimal” 4FSK mode that runs at 2400 bit/s, has a 5kHz RF bandwidth and a MDS of -132dBm. ModeB use Manchester-encoded 2FSK at 2400 bit/s and will run over any FM radio, even $40 HTs.

Brady’s modem is also being used for our high speed balloon telemetry work.

There is plenty of software work (e.g. STM32F4 micro-controller code) to be done for the SM2000. Help wanted!


SM2000 Part 1 – Introducing the project

SM2000 SVN – CAD Files for the project

High Speed Balloon Data Link

Today Mark and I spent an afternoon working on a 115 kbit/s FSK data system for high altitude balloons. Here is a video of Mark demonstrating the system:

In our previous tests, we needed -75dBm to get jpeg images through the system, much higher that the calculated MDS of -108dBm + NF. So we devised a series of tests – “divide and conquer” – to check various parts of the system in isolation.

First, some SDR noise figure tests. We added to these measurements today by trying a few SDRs with a low noise pre-amplifier. First, we measured the pre-amp NF. This was quoted as 0.6dB, we measured 2dB with the spec-an (which has 1.5dB uncertainty). We then tested combinations of the pre-amp with various SDR gains:

RTLSDR G=20.......: Pin: -100.0 Pout: 15.5 G: 115.5 NF: 19.4 dB
RTLSDR G=50.......: Pin: -100.0 Pout: 38.8 G: 138.8 NF:  5.6 dB
RTLSDR G=50 Preamp: Pin: -100.0 Pout: 59.0 G: 159.0 NF:  2.0 dB
AirSpy G=10.......: Pin: -100.0 Pout: -1.0 G: 99.0  NF: 19.4 dB
AirSpy G=21.......: Pin: -100.0 Pout: 33.9 G: 133.9 NF:  6.7 dB
AirSpy G=21 Preamp: Pin: -100.0 Pout: 53.1 G: 153.1 NF:  2.8 dB

The RTLSSDR was a R820T and the pre-amp model number PSA4-5043.

When the pre-amp was used, it boosted the overall gain of the system, and set the system NF to 2dB. It was great to see system NFs close to our measured pre-amp NF – gave us some confidence that our measurements were OK.

The SDRs require high RF gain levels to achieve a low NF. We did notice that at high RF gain levels, birdies appeared in the SDR output spectrum, and there were some signs of compression. We will look into SDR gain distribution more in future.

Testing The Modem Off Line

I wanted to test the modem over the RF link, and the best way to do that is with a BER test. Mark configured the Rpi Tx to send fixed frames of known test data. We used a HackRF to down-convert the received FSK test frames and store them to file.

The data rate of the link is Rs=115.2 kbit/s, which is sampled by the demodulator at Fs = 115200*8 = 921.6 kHz. However to the modem it just looks like an 8 times oversampled signal. So here is 10 seconds of the modem signal replayed at Fs=9600 Hz. You can hear the packets starting by the sound of the header. When replayed at this low sample rate, the bit rate is 1200 baud, and the packets are a few seconds long. At the full sample rate they are just 23ms long.

The non-real time reference Octave demodulator was used to demodulate the FSK sample files, pop up some plots, and measure the BER. Much easier to see what’s going on with the off-line simulation version of the modem. After a few hours of wrangling with fsk_horus.m, I managed to decode Mark’s test frames.

The tx signal we sampled was noise free, so I added calibrated AWGN noise in the Octave simulation to test BER performance of the real-time FSK modulator and transmitter. It was spot on – 1% BER at an Eb/No of 9dB. Great! I do like FSK – real world implementations (like the FSK tx chip) work quite close to theory. This verified that the hardware tx side was all OK in terms of modem performance.

I did however discover a fairly large baud rate error (sample clock offset), of around 1700ppm. This suggested the tx was actually sending at 115,200*1.0017 = 115.396 kbit/s.

Simultaneously – Mark worked out how to measure the baud rate of the RPi serial port. He used the clever idea of sending 0x55 bytes, which when combined with the RS232 start and stop bits, leads to a …010101010… sequence on the RS232 tx line – a square wave at half the baud rate. We connected a frequency counter, and measured the actual baud rate as 115.387 kbit/s, right in line with my numbers above.

The C version of the demod doesn’t like such a large clock offset (baud rate error), so we tweaked the resampling code to adjust for the error. Could this baud rate error could be our “smoking gun” – the reason such a high rx level was required to push images through?


You need to test receivers at very low signal levels. The problem was a relatively high power transmitter nearby generating the tx signal. In our case, the tx power of 25mW (14dBm) is attenuated down to -110dBm, a total of 124dB attenuation. The tx signal tends to radiate around the attenuator (it is a radio transmitter after all). When you reduce the step attenuator 10dB but the signal on the spec-an doesn’t drop 10dB, you have a RF radiation problem.

We solved this by putting the tx in a metal box in another room, then (at Matt, VK5ZM’s suggestion), connecting the tx to the attenuator and rx using coax with a intentionally high loss at UHF. This keeps the high level tx signals well away from the rx.

Mark fired up the real time code again, adjusted for the baud rate error, and suddenly we were getting much better results – good images at -94dBm. He added the pre-amp, and now we could receive images at -106dBm. This is exactly, almost suspiciously close to what we calculated:

  MDS = Eb/No + 10*log10(B) - 174 + NF
  MDS = 15 + 10*log10(115E3) - 174 + 2
  MDS = -106.4 dBm

It doesn’t usually work out this well ….. guess we are getting our head around this radio caper!

Dropping the signal level to -111dBm meant just a few SSTV packets were making it through. Most of them were bombing on a CRC error. At -111dBm, our Eb/No = 10dB, or a BER of 3E-3. Now our packets are a few thousand bits long, so with BER = 3E-3, we are very likely to cop a few bit errors per packet, which are then discarded due to a CRC fail. So this fits exactly with what was observed at this signal level. Check.

Here a video of Mark running through the experimental set up:

Command Lines

RTLSDR Samples Captured using:

rtl_sdr -s 1000000 -f 440000000 -g 20 - | csdr convert_u8_f > rtlsdr_gain20_sig.bin

AirSpy samples captured using:

airspy_rx -f440.0 -r /dev/stdout -a 1 -h 21  | csdr convert_s16_f > airspy_gain21_sig.bin

Commands for complete end-to-end decoding (assuming csdr is installed):

rtl_sdr -s 1000000 -f 441000000 -g 35 - | csdr convert_u8_f | csdr bandpass_fir_fft_cc 0 0.4 0.1 | csdr fractional_decimator_ff 1.08331 | csdr realpart_cf | csdr convert_f_s16 | ./fsk_demod 2X 8 923096 115387 - - | ./drs232 - - | python --partialupdate 8

The python code is here.

Visualising our Packets

Brady, KC9TPA, the author of the C FSK modems, sent us a neat visualization of our test packet:

You can see the 0x55 bytes in the header, the unique word, then a sequence of 0x0 too 0xff, sent LSB first, with the RS232 start (0) and stop (1) bits.

Brady created that image using a screen capture of this:

xxd -g 10 -c 10 -s 2 115.bin | tr '1' '*' | tr '0' ' '


Measuring SDR Noise Figure

Horus 14 – Tux in (near) Space