I have been a bit quiet over the last few weeks but don’t you worry, it is only because I have been busy and I can now present you what I have been tinkering with during the last few weeks: An AM, FM, SSB and CW receiver implemented using GNU Radio (python) and Qt graphical user interface.
After my work on the example receivers implemented using the GNU Radio Companion, I was sitting with a feeling that I have pushed GNU Radio Companion to its limits. GRC is really an amazing tool for instant prototyping and learning; however, it does not have support for creating more advanced control flows that would be required for e.g. switching between different demodulators. There is some support for switching between different blocks during run time but this is implemented as parallel flows rather than reconfiguration of the flow graph. Thus, it was clear to me already back then that for general purpose applications with more than one specific function coding in Python and/or C++ will be necessary.
Already when I got the USRP I wished for a receiver application that resembles the functionality of a radio scanner. More specifically:
- Easy tuning from one end to the other
- Switch between different USRP bandwidths, e.g. 250k, 500k, 1M…
- Support AM, FM, WFM, SSB, and CW
- One click recording and playback of both audio and RF spectrum.
- Nice graphics
These software functions combined with the USRP + LFRX and WBX daughterboards would provide a very nice radio gadget.
Experiment 1: wxPython
Few months ago I started working on this receiver using Python and the gr-wxgui component. When I get an idea for an application with a graphical user interface I always begin by creating a first mock-up of the GUI to get a feeling of how this idea will actually look like in reality. Once I am satisfied with the experimental prototype GUI, I start implementing the behavioral parts of the software, resulting in a functional (dis)proof of concept prototype. This can be refined and improved alter on.
Unfortunately, I didn’t get very far with the wxPython based prototype. After wasting a whole weekend trying to make things look right I gave up and put the experiment on hold for indefinite time. The wxPython / wxWindows way just didn’t feel right. Maybe I was missing some fundamental concepts in wxWindows that come to you after going through an x-days long learning process. I don’t know. Given my decade long experience with Gtk+ and Qt I figured that I should be able to use any other toolkit after a quick tutorial, but this was not the case for the wxPython stuff. Why bother when there are alternatives?
Experiment 2: Qt GUI
About ten days ago I decided that it was time to take another stab at the multi mode receiver but this time using Qt as GUI toolkit. There is already a gr-qtgui component in GNU Radio which provides FFT spectrum, waterfall, scope and constellation plotter, though unlike the gr-wxgui component, it is an all-in-one sink where the different graphic displays are organized in a notebook. Fortunately, each display can be switched on and off when creating the sink.
Instead of starting from scratch, I took the existing usrp_display.py application, which is the Qt GUI version of usrp_fft.py, and modified it step by step adding filters, demodulators, AGC and implementing the control mechanism. The GUI was already designed using the Qt Designer and I also used it to modify the existing UI.
Unlike the failed experiment with wxPython, every night when I worked on the receiver I could go to bed with a feeling that I have made some significant progress.
Already after 10 days of experimentation (~30 hours of work) I have what I would call a functional experimental prototype receiver
- It can receive AM, FM (narrow and wide) and SSB
- It has variable channel width
- Fixed AGC
- 250k, 500k, 1M, 2M, 4M USRP bandwidth
- Can set USRP frequency via text entry or tune up/down buttons
The source code is available from my public Github repository
git clone git://github.com/csete/gqrx.git
As I said, it is an experimental prototype and it may or may not work for you. You can expect the code to change a lot over the next few weeks!
To make it run you need to have GNU Radio with the gr-qtgui component installed and you also need a USRP1 – or you have to modify it to use USRP2 or UHD.
Right now the receiver code is about 800 lines of Python, including all comments and blank lines but excluding the Qt Designer GUI. I think it is quite impressive when comparing the functionality to the amount of code. GNU Radio combined with Qt for GUI is quite awesome!
The architecture of the receiver is based on my GRC examples that use two filters: a frequency xlating filter for tuning within the received spectrum and a second low pass or band pass filter that performs channel filtering and decimation from 250k to 50k. The demodulators then work at 50k rate. This works well except for wide FM where the channel bandwidth is significantly larger than 50kHz. Therefore, I have rewritten the receiver and combined the two filters so that now the frequency xlating filter also performs the channel filtering and let the demodulator run at 250ksps. This works well and even gives better AGC performance, unfortunately, the overall performance has decreased significantly. Using the first scheme with two filters I had no problems running at 4MHz bandwidth. With the new scheme with only one filter but where the demodulators run at 250ksps, I can only go up to 1MHz bandwidth. Of course, using a faster computer would help, but the decrease in performance is obvious. Even at 250ksps the CPU load goes from 20% using the 50ksps demod rate to 30% using the 250ksps demod rate. I will have to run a few tests and find the reason for this, then decide which method to use. It is likely that will end up using 50ksps for all but wide FM reception.
The other thing on the todo list is to implement recording and playback of both audio and received spectrum. I expect this to be relatively easy. It would also be nice to have the ability to switch between USRP side A and B as well as between the antenna connectors at run time,
On the longer term I will also hack on the qtgui code. I want to add API functions to change the colors and other look & feel settings of the spectrum scope and also improve the scaling on the axes. As it is now one can pan and zoom using the mouse but the settings are reset when the x-axis is changed, which happens every time I change the USRP frequency. In the long-long term I may even write my own spectrum scope that does not have all the buttons and widgets taking up space. I rarely use them and they take up a lot of space.
Stay tuned for more.