Introduction

I hope I've conveyed to my readers how amazing modern radio technology is, and what an opportunity it presents for technical and mathematical education — and fun along the way.

The above image shows the frequency spectrum of a modern FM broadcast station. Notice the squares to the right and left of the FM station at the middle of the display (near the vertical red line). This leads to two questions:

The pictured Atwater-Kent radio weighed about 150 pounds (68 kilos) and cost approximately US\$100 in 1934 dollars (that's about \$1800 in present-day US dollars). The RTL-SDR weighs one ounce (1/16 pound or about 1/35 kilo) and costs US\$21. But this comparison misses the fact that (when linked with appropriate software) the RTL-SDR offers 100 times more functionality than the Atwater-Kent.

This will sound familiar to those who read my technical articles, but SDR is another example showing the intimate relationship between everyday reality and mathematics. The reason software-defined radios are more efficient and less expensive than hardware radios, is because radio technology is essentially mathematical . Old-style radios got their results by solving equations — crudely and slowly, but as well as could be expected from the technology of the time. Modern radios have much less hardware and much more software (i.e. equations), a trend that continues. Eventually we will connect an antenna directly to a computer and mathematics will do the rest.

The key to understanding SDR is to see that what once required an unchanging, inflexible electronic circuit built into a radio, now relies on software, with enormous advantages in cost and flexibility. Years ago I would change radio modes by throwing a physical switch, but I now get the same result by changing a symbolic term in a mathematical equation written in computer code. Using SDR technology I can reconfigure my "radio" to perform a new task that would have required me to warm up a soldering iron and rewire an old-fashioned radio, a task that might take a week if I had all the parts on hand — and yes, I've done just that in a long career as both hardware and software engineer.

This isn't my first SDR — I've written others. One example was JRX , a program that interfaced with conventional amateur radio receivers and transmitters by means of a library called HamLib . But because this field is moving so quickly, both software and hardware have changed dramatically since JRX and HamLib came on the scene. One can now acquire a radio-frequency front-end device equal in performance, but at a tiny fraction of the cost, of a conventional radio, and access it using a specialized program like PLSDR.

This page describes and provides a particular software-defined radio (hereafter SDR) that I wrote (open-source and free) as part of my exploration of modern radio technology. This SDR is written in Python and relies on the Gnu Radio technical infrastructure for its inner workings.

Acquire and Install

The Waterfall display (lower left tab marked "Waterfall") shows a time record of past received signals. Its displayed colors may be adjusted with the mouse wheel. The speed of the waterfall display is determined by the spectrum display's Rate FPS setting described below.

It's not easy to create an antenna that receives only desired signals and rejects the noise of modern, high-speed electronic circuits, but it can be done.

Equation (1) tells us that the spectrum of a square wave consists of odd-numbered harmonics for a substantial bandwidth above its fundamental frequency $f$. Here's a comparison of a sine wave and a square wave (the fundamental spectrum line is against the left margin):

PLSDR supports two primary platforms — Linux and Windows. As usual, the Windows installation procedure is more complicated than Linux, but I've done all I can to simplify it. Let's start with Linux.

For those in a blazing hurry and who can't be bothered reading instructions, Here are links to the old (Python 2.7, GNURadio 3.7) and new (Python 3+, GNURadio 3.8+) PLSDR versions:

Development Process

Notes on Single-Sideband Design

For lack of useful online documentation the single-sideband decoder that's now part of PLSDR required a significant effort to design, although it probably shouldn't have. But first, a little history.

Single-sideband radio transmission and reception is a clever and efficient strategy to squeeze as much communications capability as possible out of a given amount of radio spectrum and transmitter power.

From the early days of radio, the original voice transmission mode was AM, Amplitude Modulation, which has this spectrum (the horizontal dimension has units of frequency, not time):

Figure 7: Amplitude Modulated radio signal

Because the sole purpose of the signal is to transmit the information in the sidebands, it occurred to workers in the field that this purpose could be served by transmitting only one of the sidebands, eliminating the carrier and the other sideband (the carrier signal, essential for decoding the remaining sideband, is restored in the receiver). After some clever engineering work, the Single-Sideband (SSB) method was devised. A single-sideband signal looks like this:

Figure 8: Single-Sideband radio signal

In Figure 8 the carrier and one sideband have been eliminated (the carrier's location is marked in Figure 8 but it's not actually present), resulting in a substantial saving in transmitter power and spectrum use.

When transmitting single sideband, one wants to save power and limit spectrum use by eliminating the carrier and one sideband, as in Figure 8. When receiving, one wants to completely filter out the unused sideband region of the receiver passband to limit interference from adjacent transmitters. The technical methods for transmitting and receiving single sideband signals are similar but not identical.

There's a crude method to create single-sideband signals that involves use of filters — one bandpass filter for each sideband. But this method is generally unsatisfactory, slow in operation, inflexible and complex. In radio design, using a bandpass filter to create a single-sideband signal is usually an acknowledgment of defeat.

In the PLSDR design phase, because of my use of Python and its limited speed, I sought the simplest, most effective and least processing-intensive sideband decoding method. I understood the theory and the mathematics, but to save time I decided to search online for methods other GnuRadio users might have posted.

After several hours of research, I came to an astonishing conclusion — of the dozen or so online examples of GnuRadio single sideband creation and decoding methods, not one of them was even remotely correct. All the authors were confident in their methods, and each was entirely wrong. At the time I write this, there isn't one correct single sideband creation or decoding method posted online. Don't get me wrong — there are plenty of published single sideband methods created using GnuRadio's tools and then published in various online forums, but every single one of them is flat wrong ( ).

In my favorite online example, one person posted a request for assistance with an SSB decoder design he couldn't get working, and another apparently more experienced designer explained that the beginner's design couldn't possibly work — it needed to be more complex. The more experienced hand then showed his own much more complex design which, apart from being five times more complicated than necessary, can't decode single-sideband signals any better than the method posted by the beginner (I know, I assembled and tested it). And in a surreal touch, the experienced designer fed the real component of his decoder's complex output to one stereo audio channel, and the imaginary component to the other, as though those listening to the audio would be able to distinguish between them.

At this point the more technically experienced among my readers will want me to show my design, which actually works. How did I create and test it?

First, a word of warning — the only meaningful validation for a single sideband receiver is to test it against a properly configured single sideband transmitter, preferably one emitting a voice signal. There are any number of online examples of decoders tested using noise sources — apparently the authors didn't realize that a noise source is very likely to confuse the test and the tester — it's common for a noise-based test signal to mix the upper and lower sidebands, then put both of them on one side of a spectrum display, creating the illusion of success.

In my tests I used the GnuRadio design facility to create a single sideband transmitter, which played a voice podcast on one computer equipped with a radio signal emitter (HackRF), then tested my receiver designs against that signal source on a separate computer and radio device. I included the all-important step of deliberately switching the transmitter and receiver to opposite sidebands to verify that no signal was getting through — something not one person who posted SSB designs online apparently thought to try, or knew how.

But enough history — let's discuss some theoretical issues. The key idea in modern single-sideband encoding and decoding is to take advantage of complex (in the mathematical sense) signals that have components in quadrature (meaning a two-component vector whose components differ by 90°). The conventional terminology for this kind of signal is I/Q, I (In-phase) being the real part and Q (Quadrature) being the imaginary part of a complex signal.

The more advanced single-sideband designs use a phasing method, one that takes advantage of the phase relationship between the I and Q signals to mathematically suppress the unwanted sideband. Here's a classic example:

Figure 9: Phasing method for sideband suppression

Now think about this. If we have two waveforms that always differ by 90°, and if we know that the relationship between the components is reversed on one side of zero Hertz compared to the other (for positive frequencies, Q lags I in time by 90°, for negative frequencies, Q leads 90°), to eliminate one sideband all we need is a special device that adds 90 more degrees of phase shift to all frequencies of interest. That would produce 180° of phase shift on one side of zero Hertz, or to put this another way, the two waveforms would be in precise opposition there. Because this special phase shift is applied to only one of the two I/Q components, if the resulting components were added together the result would be zero amplitude on one sideband, and a doubling of amplitude on the other, at all frequencies. That's an ideal outcome, one that can't be approached using a bandpass filter.

So what is this fantastic device that adds exactly 90° of phase shift to all frequencies and makes this all possible? It's called a Hilbert transformer. It's not possible to create an ideal Hilbert transformer (whose perfect behavior can only be described mathematically), but practical embodiments are pretty good. Again, this device has the property that it adds 90° of phase shift to all frequencies, not just one. This means it can be configured to completely eliminate one sideband of a complex, wide-bandwidth signal.

But rather than try to use words to explain this, I offer this JavaScript app, which shows the process graphically:

Display A: I / Q / Hilbert Display B: I / Hilbert / Output USB Frequency: Hz Figure 10: JavaScript single-sideband filter app

Notes:

The I (In-phase) trace is the real part of the complex incoming radio signal.

trace is the real part of the complex incoming radio signal. The Q (Quadrature) trace is the imaginary part of the signal — it always differs by 90° from the I trace, either leading or lagging in time.

trace is the imaginary part of the signal — it always differs by 90° from the trace, either leading or lagging in time. For positive frequencies, Q lags I in time by 90°, as shown with the default settings above.

lags in time by 90°, as shown with the default settings above. For negative frequencies, Q leads I in time by 90° — test this by moving the frequency slider to a negative frequency.

in time by 90° — test this by moving the frequency slider to a negative frequency. The Hilbert signal always lags Q in time by 90°, regardless of frequency . This is important to understand.

signal always lags in time by 90°, . This is important to understand. The Output trace is the sum of I and Hilbert , as shown in Display B above.

trace is the sum of and , as shown in Display B above. Because the relationship between I and Q depends on frequency, and because Hilbert always lags Q regardless of frequency: For positive frequencies, Q = I + 90° and Hilbert = Q + 90° as shown in Display A with default settings, therefore Hilbert is 180° out of phase with I, and the Output sum of the I and Hilbert signals is zero, as shown in Display B with default settings. For negative frequencies (move the frequency slider left to a negative setting), Q = I - 90° and Hilbert = Q + 90° as shown in Display A with a negative frequency setting, therefore Hilbert is exactly in phase with I, and the Output sum of the I and Hilbert signals is twice the normal signal amplitude, as shown in Display B with a negative frequency.

and depends on frequency, and because always lags regardless of frequency: Switching between upper and lower sidebands is accomplished by reversing the sign of the Hilbert signal that's applied to the Output adder (try it above — click the USB checkbox).

signal that's applied to the adder (try it above — click the checkbox). In the above app, the positions of the I and Hilbert traces are slightly offset vertically so the reader can see both traces when they're in phase. This offset isn't part of the real process.

After reflecting on these issues and, because of a limitation in the GnuRadio Hilbert filter design, I was obliged to create an unnecessarily complex (notes below) but effective single-sideband decoding filter that, in its final form, looks like this in GnuRadio Companion (and in PLSDR):

Figure 11: GnuRadio Companion SSB decoder diagram

Notes on Figure 11:

Because the GnuRadio Hilbert block isn't an optimal design, this filter is more complex than necessary — I was forced to to use two Hilbert transformers where only one is actually needed.

This results from the fact that this real-world embodiment of the Hilbert transformer doesn't just shift phases by 90°, it also creates a time delay, and to avoid spoiling the timing of the design, an identical time delay must be included in the other branch of the decoder. The existing Hilbert transformer design provides this essential time delay as one of its two outputs, but if the design requires two input pathways (one for I, one for Q), then the time-delay value must be acquired from a separate Hilbert transformer.

So in Figure 11, one Hilbert transformer actually performs the intended 90° phase shift, while the other provides the exact time delay of the active device to keep the system synchronized.

It would be nice if these two signals emanated from a single GnuRadio Hilbert block, one that accepted a complex input — that would eliminate some unnecessary complexity in this design.

To me personally, a perfect GnuRadio Hilbert block would in some ways be the opposite of the existing one. The perfect Hilbert would accept a complex input, thus eliminating my "Complex to float" block at the left, and it would produce two float (i.e. non-complex) outputs, thus eliminating my "Complex to Real" and "Complex to Imag" blocks at the right.

The purpose of the "Mult" block is to reverse the sign of one of the inputs to the adder at the right, which has the effect of switching from one sideband to the other.

There are obviously any number of ways to create and decode single-sideband signals, since we're surrounded by radios that do this routinely, but as I write this the Internet has zero usefulness as a research resource on this topic. Again, I can't believe the number of people I located who tried to design an SSB encoder or decoder, utterly failed, then posted their results on the Web just as though they had succeeded. I realize this group has two sub-populations — those who knew their designs didn't work, and those who, because of defective testing procedures, sincerely believed their designs worked. But both groups posted their results online without hesitation.

As I write this, there isn't a single working GnuRadio SSB encoder or decoder design posted online. Tomorrow there will be one.