Although GRC (the GNU Radio Companion) uses the word radio, it is really a graphical tool for building DSP applications. In the last post, I showed you how you could experiment with it just by using a sound card (or even less). However, who can resist the lure of building an actual radio by dragging blocks around on a computer screen?
For this post and the accompanying video, I used an SDRPlay. This little black box has an antenna jack on one end and a USB port on the other. You can ask it to give you data about a certain area of the RF spectrum and it will send complex (IQ) data out in a form that GRC (or other DSP tools) can process.
The SDRPlay is a great deal (about $150) but if you don’t want to invest in one there are other options. Some are about the same price (like the HackRF or AirSpy) and have different features. However, you can also use cheap TV dongles, with some limitations. The repurposed dongles are not as sensitive and won’t work at lower frequencies without some external help. On the other hand, they are dirt cheap, so you can overlook a few little wrinkles. You just can’t expect the performance you’ll get out of a more expensive SDR box. Some people add amplifiers and converters to overcome these problems, but at some point it would be more cost effective to just spring for a more expensive converter.
Traditional Radio Architecture
Before diving into an SDR, it is useful to review some traditional radio receiver architectures. Many people built crystal radios as a kid, so let’s start there. With a crystal radio you have a big coil and some kind of capacitor that has a tendency to select a certain radio frequency. By select, I mean it will pick out a certain frequency and reject other frequencies. The only problem is, it isn’t very good at doing that. It won’t fully reject frequencies you don’t want and it won’t make any signal stronger–in fact, even the selected frequency will become weaker than it was. That’s the price you pay for a simple receiver.
AM radios carry modulation (that is, sound, in this case) by varying the amplitude of the carrier wave. A diode can recover that varying amplitude and a crystal radio might use a germanium diode, a galena crystal (hence the name), or even a razor blade and a safety pin. The signal won’t be very strong, but high impedance headphones will work, or you could build a simple audio amplifier.
There are lots of ways to improve the simple crystal radio, but they all have similar goals: boost signal strength, or improve rejection of unwanted signals (or both). For example, the Tuned Radio Frequency (TRF) radio used tuned amplifiers before the diode detector to selectively strengthen the signal you wanted to hear.
The problem with the TRF is you have to tune each stage to the frequency you want. That problem is what led to the development of the most common receiver type: the superheterodyne. In this scheme, the input signal may be selected and amplified but then it is mixed with a local oscillator. The mixer will add (and subtract) the local oscillator frequency from the signal.
Suppose the input to our radio has two signals: one at 7050 kHz (the one we want to hear) and another at 7200 kHz. Further suppose that the local oscillator is set for 6050 kHz. After mixing you’ll have signals at 1000 kHz, 1950 kHz, 13100 kHz, and 13250 kHz. Why is this important? Because we can now build highly tuned amplifiers that amplify signals at 1000 kHz (known as the intermediate frequency or IF) and reject other signals.
The advantage is that those tuned amplifiers don’t have to be adjusted. That means they are simpler to operate and simpler to make very efficient. For example, good radios might use a crystal filter to reject all the extra frequencies. For a conventional radio, that’s the best way to create practical filters. After demodulation, the radio probably amplifies the audio signal to drive speakers or headphones.
To recap, the basic layout is RF front end, mixer and local oscillator, IF amplifiers and filters, demodulation, and, finally, audio amplification. Remember this, because many of these same pieces will show up in one form or another in a software defined radio.
Using software defined radio, you generally have the same goals, but you don’t quite accomplish them in the same way. The IQ data comes in and represents the entire signal available. In some cases, you have to shift the frequency in the same way you would use a mixer in an analog radio. For the SDRPlay, though, the signal already comes in at zero frequency. There are many ways to filter using GRC, so it is easy to cut off the frequencies you don’t care about (and some filters can translate frequency, too, if you need that).
One thing that is paramount with a software defined radio is the sampling rate. If you want a bandwidth of, say, 1 MHz, you need to sample at 2 MHz (at least). However, when you try to do complex processing or even just want to go to audio frequencies, you’ll want to cut down to much narrower frequency band and sample rate.
The GRC blocks use two DSP terms for moving sample rates around: decimation and interpolation. Decimating a signal by 4 will essentially divide the sample rate by 4. Interpolating by 2 will double the apparent sample rate. You’ll often use both to get some non integer change in sample rate. For example to go from 1000 kHz to 44.1 kHz, you can’t just divide by an integer. But you could interpolate by 441 and decimate by 1000 to get the result you wanted.
A Simple Radio Receiver
Let’s look at a flow for a simple radio (the same one you can see in the video above). Unlike the example in the previous post, I used the WX GUI system, but the same principles would apply with the QT libraries and blocks. The most important block is the Osmocom block (see picture to the right) that connects to the SDRPlay box. The properties of this block set the receive frequency, the bandwidth, and the RF gain. The RF gain configuration on the SDRPlay can be a little finicky. If you have it too low, you won’t hear anything. But if it is too high, you will overdrive and cause distortion.
I connected the output of the Osmocom block to two different strings of blocks. One branch is just an FFT so that you can see activity all around the vicinity the SDRPlay is tuned. The other branch is responsible for acting like a regular radio. Since the SDRPlay data is already shifted to zero frequency, there’s no need to do that. However, it does pay to cut off frequencies above the frequency of interest.
The low pass filter to the left takes care of that by chopping off everything above 5 kHz–plenty of bandwidth for an AM signal. In addition, I had the filter decimate the signal by a factor of 32. Remember, we need to go to 48 kHz for the sound card. Decimating the samples here will make it easier to further divide it down later and improve CPU utilization. The stage after the low pass filter is a rational resampler. This block divides (decimates) and multiplies (interpolates) the sample rate, allowing you to effectively multiply the sample rate by a fraction.
The output of the resampler is at 48 kHz and feeds an automatic gain control block and a demodulator. You’ll note the output port of the demodulator is orange, indicating it is a stream of real numbers, not IQ samples. The audio sink is the gateway to the PC’s speakers, but before the data arrives there the radio multiplies it by a value. The default value is 1, so it has no effect, but a GUI volume control can set that value to a different number to adjust the amplitude of the audio signal (in other words, the volume).
Mapping this back to a traditional superheterodyne architecture, you can think of the Osmocom block as the front end, local oscillator and mixer. The stages between it and the demodulator are similar to the IF stages of a classic receiver. Everything past the demodulator is no different from an ordinary radio’s analog amplifiers.
Speaking of GUIs, this example as well as the last one, uses some GUI controls to change things like the volume and frequency. Each GUI block has a GUI hint that you can use to control where it appears in the running radio. You can use two or four numbers for each hint. The first (or only) two numbers are the row and column (both zero-based). You can think of an imaginary grid with as many rows and columns as you need.
If you use four numbers, the first two are the same. However, the second pair of numbers specify how many columns and rows to stretch over. So if the top row, for example, has three controls in their own columns (hints of [0,0], [0,1], and [0,2]), you could have a control span the entire width of the window in the first row by specifying [1,0,1,3] in the hints (without the brackets which are just there for readability). You’ll see an example of this in the video. In addition, the image below shows part of the radio, illustrating how the top FFT spans 5 rows and 4 columns. Remember, the rows and columns are zero-based, so the next empty row is row 5 which is there the two controls that show the frequency appear (in columns 1 and 3).
If you follow along with the video, you’ll see that creating a simple radio with GRC is pretty easy. Obviously, you could improve the design both by making the radio receive better and by adding features like FM reception. My goal, though, was to make a bare bones setup that you could try to build upon before embarking on more sophisticated projects.
You can download the example files from the project page on Hackaday.io. You may need to adjust a few things based on your SDR adapter and your sound card, but if you have an SDRPlay and sound card that supports 48 kHz samples you should be good to go.
If you are looking for an actual project, consider this: Anything you can do with an RTL dongle, you should be able to do with the SDRPlay. If you search our past posts, you’ll see plenty of SDR projects based around that cheap device.