grc logo In my last post, I was using the RTL2832 TV tuner dongle to get a simple Software Defined Radio (SDR) operational.  I wanted to use the SDR# program as my receiver but found that the MS Windows tool would not work and so I targeted Gqrx as an alternative. Gqrx is dependent on the GNU Radio.  So in this post, I plan to get Gqrx and GNU Radio up and operational with the RTL-SDR dongle.  I spend some time with other tools to help further verify (with mixed success) that GNU Radio is working.

The contain here comes from multiple source and I attempt to list those sources below.  For a good video to get a sense of what your in for, check out this video. Also, this post covers many of the topics here.

GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software defined radios. It can be used with readily-available low-cost external RF hardware to create software-defined radios, or without hardware in a simulation-like environment. It is being used in hobbyist, academic, and commercial environments to support both wireless communications research and real-world radio systems. 

Gqrx is an experimental AM, FM and Single Side Band (SSB) software defined receiver implemented using GNU Radio and the Qt GUI toolkit. Currently it works on Linux and can use the RTL_SDR dongles as input source.

Also within this post, I venture out from gqrx to examine a few other tools.  I don't cover much territory, nor have much success.  The insperation to examine these other tools comes mainly from the lengthy post "RTL-SDR and GNU Radio with Realtek RTL2832U [Elonics E4000/Raphael Micro R820T] software defined radio receiver".  Also check out "Getting Started with GNU Radio and RTL-SDR (on Backtrack)".

Build GNU Radio on Ubuntu

The GNU Radio web site has specific instructions and a build script for installing it on Ubuntu (I'm using version 13.04).  This process claims it may take 1-2 hours to do the install (for me it ran in 1 hour 14 minutes).  The steps are as follows:

cd ~/src
mkdir ~/gnuradio
cd ~/gnuradio
wget http://www.sbrac.org/files/build-gnuradio && chmod a+x ./build-gnuradio && ./build-gnuradio --verbose

When prompted, tell it to proceed and give it sudo privilege by typing "Y". Because of the --verbose option, you will see a lot of text whizzing by as the build-gnuradio script does its thing. You’ll also see a percentage complete indicator as the script works its way down it tasks.

The GNU Radio build creates a large variety of tools which get installed into /usr/local/bin.  You also notice that tools not directly related to GNU Radio are also created. I'll leave it for another time to understand and explain the GNU Radio environment.

The "Hello World" of GNU Radio

dial_tone.grc - -home-jeff - GNU Radio Companion_006 To verify that the software is working, best thing is to create the typical "Hello, World" program, just we might have done for our first foray into C++, Python, or other programming language.  In the world of GNU Radio, this program has come to be the phone dial tone. To do this, I followed the video The "Hello World" of GNU Radio: Dial Tone and the gnuradio.org.  I did this using the GNU Radio Companion (executable located at /usr/local/bin/gnuradio-companion).  GNU Radio Companion (GRC) is a graphical tool for creating signal flow graphical models and generating Python source code for the model created.

GRC's generated flow and code for the "Hello, World" program is listed below. The Python code for the dial tone program was placed in the home directory, and in my case, it was called dail_tone.py. While it can be executed via the gnuradio-companion, it can also be executed via python dial_tone.py. The user interface for the GRC and the corresponding Python code it generated is listed below:

#!/usr/bin/env python
##################################################
# Gnuradio Python Flow Graph
# Title: Dial Tone
# Author: Jeff Irland
# Description: "Hello, World" program - produces phone dial tone
# Generated: Sat Jun 22 21:24:56 2013
##################################################

from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import window
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from gnuradio.wxgui import fftsink2
from gnuradio.wxgui import forms
from gnuradio.wxgui import scopesink2
from grc_gnuradio import wxgui as grc_wxgui
from optparse import OptionParser
import wx

class dial_tone(grc_wxgui.top_block_gui):

    def __init__(self):
        grc_wxgui.top_block_gui.__init__(self, title="Dial Tone")
        _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
        self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 32000
        self.noise_slider = noise_slider = .005

        ##################################################
        # Blocks
        ##################################################
        _noise_slider_sizer = wx.BoxSizer(wx.VERTICAL)
        self._noise_slider_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_noise_slider_sizer,
            value=self.noise_slider,
            callback=self.set_noise_slider,
            label='noise_slider',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._noise_slider_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_noise_slider_sizer,
            value=self.noise_slider,
            callback=self.set_noise_slider,
            minimum=0,
            maximum=.1,
            num_steps=1000,
            style=wx.SL_VERTICAL,
            cast=float,
            proportion=1,
        )
        self.Add(_noise_slider_sizer)
        self.wxgui_scopesink2_0 = scopesink2.scope_sink_f(
            self.GetWin(),
            title="Scope Plot"
            sample_rate=samp_rate,
            v_scale=0,
            v_offset=0,
            t_scale=0,
            ac_couple=False,
            xy_mode=False,
            num_inputs=1,
            trig_mode=gr.gr_TRIG_MODE_AUTO,
            y_axis_label="Counts",
        )
        self.Add(self.wxgui_scopesink2_0.win)
        self.wxgui_fftsink2_0 = fftsink2.fft_sink_f(
            self.GetWin(),
            baseband_freq=0,
            y_per_div=10,
            y_divs=10,
            ref_level=0,
            ref_scale=2.0,
            sample_rate=samp_rate,
            fft_size=1024,
            fft_rate=15,
            average=False,
            avg_alpha=None,
            title="FFT Plot",
            peak_hold=False,
        )
        self.Add(self.wxgui_fftsink2_0.win)
        self.blocks_add_xx_0 = blocks.add_vff(1)
        self.audio_sink_0 = audio.sink(32000, "pulse", True)
        self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, .1, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, .1, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, noise_slider, 0)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_add_xx_0, 0), (self.wxgui_scopesink2_0, 0))
        self.connect((self.blocks_add_xx_0, 0), (self.audio_sink_0, 0))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx_0, 2))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx_0, 1))
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx_0, 0))
        self.connect((self.blocks_add_xx_0, 0), (self.wxgui_fftsink2_0, 0))

    def get_samp_rate(self):
        return self.samp_rate

    def set_samp_rate(self, samp_rate):
        self.samp_rate = samp_rate
        self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
        self.analog_sig_source_x_1.set_sampling_freq(self.samp_rate)
        self.wxgui_fftsink2_0.set_sample_rate(self.samp_rate)
        self.wxgui_scopesink2_0.set_sample_rate(self.samp_rate)

    def get_noise_slider(self):
        return self.noise_slider

    def set_noise_slider(self, noise_slider):
        self.noise_slider = noise_slider
        self.analog_noise_source_x_0.set_amplitude(self.noise_slider)
        self._noise_slider_slider.set_value(self.noise_slider)
        self._noise_slider_text_box.set_value(self.noise_slider)

if __name__ == '__main__':
    parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
    (options, args) = parser.parse_args()
    tb = dial_tone()
    tb.Run(True)

When the GRC flow execution button is pressed, the scope and FFT plots are are created as shown below:

Dial Tone_005

The build for GNU Radio also installs the RTL-SDR software, so it would be wise to test GNU Radio with the RTL_SDR hardware and make sure everything is operating as expected.  I want to make a simple FM receiver, comparable to what was done via rtl_fm in RTL-SDR – Software Defined Radio (SDR) for $20. Something equivalent to:

rtl_fm -W -f 99.5M | play -r 32k -t raw -e signed-integer -b 16 -c 1 -V1 -

Using the following postings as a guide: I had sufficient success to convince myself that GNU Radio was work.

Building Gqrx on Ubuntu

Gqrx is a software defined AM, FM and SSB software defined radio receiver for RTL-SDR based dongles (as well as the Universal Software Radio Peripherals and Osmo SDR devices).  It features a  Qt GUI.  As a QT program, you'll need to make sure you have QT4 installed (version 5 will not work) and that you have the qtcreator tool is installed:

sudo apt-get install qt4-default
sudo apt-get install phonon-backend-gstreamer

Now download the source for Gqrx via its page on GitHub  and extract it into your target directory. The posting Getting Started With RTL-SDR and the README on the GitHub site where useful in understanding how to do the install.  I did the following:

git clone git://github.com/csete/gqrx.git
cd gqrx
qmake gqrx.pro
make

At this point, you should find the gqrx executable in ~/src/gqrx directory.  Start up via ./gqrx and you'll get the screen below (or set your values to equal this):

Configure I-O devices_001

Click "OK" and the screen below will pop up.  Make sure you have the RTL-SDR dongle plugged in and select the button on the top left to start processing data.  I have tuned the radio to a local FM station at 85.7MHz and listen to Washington Nationals vs. Phillies baseball!

Gqrx 0.0 - rtl=0_004

Building Multimode Radio Receiver

This radio receiver is capable of demodulating muitiple modes, specifically AM, FM, USB, LSB , WFM. TV-FM, PAL-FM. It's easy to use and  has an automated scanning and spectral zoom features where clicking on the spectrogram or panorama to tune to the frequency of interest.

Multimode documentation is sparse to non existent. The posts "Using the Realtek RTL2832 USB “dongle” as a gnuradio multimode receiver" and "RTL-SDR and GNU Radio with Realtek RTL2832U [Elonics E4000/Raphael Micro R820T] software defined radio receiver" and "Getting Started with GNU Radio and RTL-SDR (on Backtrack)" gave some important hints on how to install multimode and get it operational.  I did the following:

cd ~
svn co https://www.cgran.org/svn/projects/multimode/trunk/ ~/src/multimode
make install

When I executed multimode.py, it didn't product a display.  I suspect its some subtle Python code problem, or more likely.  incompatibility with the latest GNU Radio libraries.  For now, I'm going to abandon this.

GNU Radio Signal Scanner

gr-scan is a program  built upon GNU Radio, rtl-sdr, and the OsmoSDR Source Block.  This receiver constantly changes frequencies in a set order looking for a frequency that has someone transmitting. It is intended to scan a range of frequencies and print a list of discovered signals.  Installation involved the following steps:

cd ~./src
mkdir gr-scan
cd gr-scan

with your browser, download: http://www.techmeology.co.uk/gr-scan/gr-scan-2012082301.tar.gz

gzip -d gr-scan-2012082301.tar.gz
tar -xvvf gr-scan-2012082301.tar
cd gr-scan-2012082301
make

When I attempted to do the make, it complained about missing Gun Radio files.  I suspect the GNU Radio libraries and include files are layed out differently since the time gr-scan was designed (August of 2012).  I'm leaving fixing this to another time.

What's Next

In this and the previous SDR posts, I focused on getting a taste of the technology without committing myself to much of an effort.  I really need to study and understand the tools that I have assembled. I still need to do a great deal more studying of  the radio spectrum itself ... I feel like I'm wondering in the dark most of the time.

Also, I feel that I'm very limited by the antenna I'm presently using (the pitiful dipole that came with the RTL dongle).  I'm thinking of building a better antenna.  Maybe try to pickup a NOAA weather satellites, with its distinctive audio signal when demodulated, and decode one of its satellite weather photos .... maybe.

Another problem with the RTL-SDR is that its internal oscillator is cheap  and drifts, resulting in clock errors with  many kHz of frequency display error in SDR - depending on a band you're listening to.  This is very annoying if you use your dongle as a radio scanner - what's the point of knowing frequency of a transmitter if it's almost random on your SDR?   This frequency error is linear across the spectrum, and can be adjusted in most SDR programs by entering a PPM (parts per million) offset value.  So I need to calculate this error offset so I can  calibrate the SDR software.