UWA M.E Project Report - Implementation of a Software FM Receiver using GNU Radio (Reduced)
Post on 15-Aug-2015
79 Views
Preview:
Transcript
Implementation of a Software FM Receiver using GNU
Radio and the USRP ENGT 8310 - 8312 Major Individual Project
THESIS
Supervisor: Dr DAVID HUANG
Head of Signal Processing and Wireless Communications Laboratory
Department of Electrical, Electronics and Computer Engineering
Student Name: SAMEER
Student Number: 20184885
Date of Submission: 12 / 11 /2007
Revision History:
Version 1: 30/09/2007 Created
Version 2: 12/11/2007 Last Updated
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
1
LETTER TO THE DEAN
# 30 / 24, Woodlands, Pearson Street,
Churchlands, Perth – 6018, WA
Date: 11/11/2007
The Dean
Faculty of Engineering Computing and Mathematics
The University of Western Australia
35 Stirling Highway
CRAWLEY WA 6009
Dear Sir
I submit to you this dissertation entitled “Implementation of a Software FM Receiver
using GNU Radio and the USRP” in partial fulfilment of the requirement of the award
of Master of Engineering.
Yours faithfully
Sameer
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
2
(Image source: GNU Radio)
Welcome to the world of GNU Radio and Universal Software Radio Peripheral!
(Image source: Ettus Research LLC)
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
3
Table of Contents
List of Illustrations.....................................................................................................4
I. ABSTRACT...........................................................................................................5
A. Key Terms......................................................................................................6
B. GNU (GNU’s Not Unix!) ..............................................................................6
II. ACKNOWLEDGEMENTS...............................................................................7
III. INTRODUCTION .............................................................................................8
A. Background....................................................................................................8
B. Purpose of the Project ....................................................................................9
IV. DESCRIPTION................................................................................................10
A. Basic Architecture in GNU Software Radio................................................10
B. The Software................................................................................................12
C. Hardware Requirements...............................................................................12
D. The Universal Software Radio Peripheral (USRP)......................................13
V. INSTALLATION OF GNU RADIO SOFTWARE AND USRP........................23
A. Installation of GNU Radio Step-by-Step .....................................................23
B. Installation of GNU Radio on Linux ...........................................................24
C. Installation of the USRP Hardware..............................................................30
VI. TESTING THE GNU RADIO SOFTWARE AND USRP..............................33
A Testing Data .................................................................................................33
B Testing Sound ...............................................................................................36
C. Evaluation and Demo using the BasicRX Daughterboard...........................36
VII. EXPLORING GNU RADIO PROGRAMS ....................................................40
A. Learning by Example...................................................................................40
VIII. IMPLEMENTATION OF FM RECEIVER ................................................43
A. Frequency Modulation .................................................................................43
B. FM Reception Methodology........................................................................44
C. FM Receiver Program..................................................................................48
IX. PROMISES OF GNU RADIO AND USRP....................................................60
A. Significance of USRP ..................................................................................60
B. Significance of GNU Radio .........................................................................62
X. RELATED AND FUTURE WORK....................................................................64
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
4
XI. SUMMARY AND CONCLUSIONS ..............................................................64
XII. REFERENCES ................................................................................................65
XIII. SOURCES OF ILLUSTRATIONS .............................................................67
List of Illustrations
Figure 1. A GLONASS Receiver Figure 2. A GPS Receiver...............................8
Figure 3. Receive Path .................................................................................................10
Figure 4. Transmit Path................................................................................................10
Figure 5. The Universal Software Radio Peripheral (USRP) Block Diagram.............15
Figure 6. The USRP main motherboard with the FPGA, 4 ADCs and 4 DACs .........15
Figure 7. The USRP main motherboard with it’s up to 4 supporting daughter boards16
Figure 8. Basic RX daughterboard (Image source: GNU Radio) ................................19
Figure 9. Basic TX daughterboard (Image source: GNU Radio) ................................19
Figure 10. The FPGA schematic..................................................................................21
Figure 11. Digital Down Converter Block Diagram....................................................21
Figure 12. Spectrum of the 93.5 – 95.5MHz FM band................................................38
Figure 13. Spectrogram of an FM Receiver with sidebands. GNU Radio and USRP
running on Linux Ubuntu 7.04.....................................................................................39
Figure 14. Frequency Modulation(Image source: Wikipedia).....................................44
Figure 15. Shows our typical setup of a FM Receiver using the BasicTX
daughterboard, Antenna and USRP .............................................................................45
Figure 16. Block Diagram of FM Receiver and Quadrature Demodulator .................47
Figure 17. Shows the received FM station and its post demodulated signal. ..............59
Figure 18. The USRP is in use in all 38 of the countries colored red in this map. ......61
Figure 19. JTRS Seal ...................................................................................................62
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
5
I. ABSTRACT
A major obstacle facing most radio platforms is the rigid nature of the current radio
platforms. At design time, all radio parameters are hard wired into the device and can
never be adapted to optimally serve a specific purpose. Software Defined Radio
(SDR) aims to change this reality by combining a collection of software modules with
minimal hardware, such that the waveforms transmitted and received are defined by
software, therefore allowing unprecedented flexibility in adapting the radio platform
to the current task at hand. Currently, adding an audio, video, or data stream to a radio
signal so it can be broadcast—a process known as modulation—is nearly always done
by dedicated electronics. The same is true with the reverse process— demodulation—
required to receive a transmission. Radio waves can be modulated in any number of
ways, and each way requires different circuitry.
The idea behind software-defined radio is to do all that modulation and demodulation
with software instead of with dedicated circuitry. The most obvious benefit is that
instead of having to build extra circuitry to handle different types of radio signals, we
can just load an appropriate program. One moment our computer could be an AM
radio, the next a wireless data transceiver—and then perhaps a TV set. Or we could
leverage the flexibility of software to do things that are difficult, if not impossible,
with traditional radio setups. An emergency message can be broadcasted on every FM
band; A dozen walkie-talkie channels could be scanned at once; or design and test a
new wireless data protocol; no problem with the software radio.
This paper presents the design, testing and implementation of a complete SDR
framework on a Linux Operating System. A case study of a simple Frequency
Modulated (FM) radio is used to showcase the flexibility of the SDR solution. The
functionality of the SDR framework is tested on actual hardware utilizing a Personal
Computer (PC) to run the software related tasks and an external board that receives
the signal at radio frequency, down-converts it to a lower intermediate frequency, and
finally presents digitized samples for processing by the PC. Full testing and
implementation results are presented, complemented by a thorough discussion of the
design process.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
6
A. Key Terms
GNU radio, Python, Decimation, Frequency Modulation (FM), Frequency
Demodulation, GNU Radio, Software Defined Radio (SDR), Universal Software
Radio Peripheral (USRP)
B. GNU (GNU’s Not Unix!)
GNU is a computer operating system composed entirely of free software. Its name is a
recursive acronym for GNU's Not Unix, which was chosen because its design is Unix-
like, but differs from Unix by being free software and by not containing any Unix
code.GNU was founded by Richard Stallman and was the original focus of the Free
Software Foundation (FSF).
The project to develop GNU is known as the GNU Project, and programs
released under the auspices of the GNU Project are called GNU packages or GNU
programs. According to Stallman, the name “GNU” was inspired by various plays on
words, including the song The Gnu. The goal was to bring a wholly free software
operating system into existence [1].
The GNU Project was launched in 1984 to develop a complete Unix-like operating
system which is free software: the GNU system. Variants of the GNU operating
system, which use the kernel called Linux, are now widely used; though these systems
are often referred to as “Linux”, they are more accurately called GNU/Linux systems.
GNU is a recursive acronym for “GNU's Not Unix”; it is pronounced guh-noo,
approximately like canoe [2].
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
7
II. ACKNOWLEDGEMENTS
My sincere thanks to University of Western Australia, for providing all the
opportunities, and imparting the wonderful higher education to me.
I express my deep sense of gratitude to Dr David Huang for his time-to-time; much
needed valuable guidance and would like to thank him for his support and
encouragement throughout the project.
I wish to express my profound thanks to A/Prof Gary Bundell, our esteemed Head of
the Department of Electrical, Electronics and Computer Engineering for his immense
support, hearted encouragement and ever lasting inspiration.
I am highly indebted to SPWCL-Lab, UWA, which helped me with valuable and wide
resources and also making available to me the necessary infrastructure.
Pursuing this project has been a very exciting experience and educative. I was
exposed to quite a lot of information and had the opportunity of working with other
students of the SPWCL research group. I would also like to show a huge appreciation
to Dawei Shen, University of Notre Dame Research Group, for creating the tutorials
on GNU Radio.
Finally, salutations to my family, friends and colleagues, Ramya K N, Mihir Patel and
Tejas Bokare, for their much needed moral support and encouragement that has been
provided under numerous occasions and making this project successful.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
8
III. INTRODUCTION
A. Background
Software radio is the technique of getting code as close to the antenna as possible. It
turns radio hardware problems into software problems. The fundamental characteristic
of software radio is that software defines the transmitted waveforms, and software
demodulates the received waveforms. What this means is that it turns the digital
modulation schemes used in today's high performance wireless devices into software
problems. This is in contrast to most radios in which the processing is done with
either analog circuitry or analog circuitry combined with digital chips. GNU Radio is
a free software toolkit for building software radios [3].
Software radio is a revolution in radio design due to its ability to create radios that
change on the fly, creating new choices for users. At the baseline, software radios can
do pretty much anything a traditional radio can do. The exciting part is the flexibility
that software provides us. Instead of a bunch of fixed function gadgets, in the next
few years we'll see a move to universal communication devices. Imagine a device that
can morph into a cell phone and get us connectivity using GPRS, 802.11 Wi-Fi,
802.16 WiMax, a satellite hookup or the emerging standard of the day. We could
determine our location using Global Positioning System (GPS), Global Navigation
Satellite System (GLONASS) or both [3].
Figure 1. A GLONASS Receiver Figure 2. A GPS Receiver
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
9
Perhaps most exciting of all is the potential to build decentralized communication
systems. If we look at today's systems, the vast majority is infrastructure-based.
Broadcast radio and TV provide a one-way channel, are tightly regulated and the
content is controlled by a handful of organizations. Cell phones are a great
convenience, but the features our phone supports are determined by the operator's
interests, not ours [3].
A centralized system limits the rate of innovation. Instead of cell phones being
second-class citizens, usable only if infrastructure is in place and limited to the
capabilities determined worthwhile by the operator, we could build smarter devices.
These user-owned devices would generate the network. They'd create a mesh among
themselves, negotiate for backhaul and be free to evolve new solutions, features and
applications [3].
B. Purpose of the Project
This project is building on the available research results with the aim of developing a
complete SDR framework within the Signal Processing and Wireless Communication
Laboratory (SPWCL) at the University of Western Australia. A simple FM receiver
was selected as an initial case study to showcase the methodology, however the
comprehensive knowledge of SDR techniques accumulated within this project will be
used to pave the way for future advanced radios. This research consists of various
phases as follows: introductory theoretical analysis, Installation, testing and
customizing the GNU software code and final implementation and result verification
of the receiver.
In this academic semester, we will build the environment of GNU radio on Windows
and Linux operating systems, be familiar with it, and learn how to use the existing
libraries and modules to accommodate different applications.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
10
IV. DESCRIPTION
A. Basic Architecture in GNU Software Radio
PC USRP (mother board)
Figure 3. Receive Path
PC USRP (mother board)
Figure 4. Transmit Path
Figure 3 and 4: Typical software radio block diagram
Figure 3, shows a typical block diagram for a software radio. To understand the
software part of the radio, we first need to understand a bit about the associated
hardware. Examining the receive path in the figure, we see an antenna, a mysterious
RF front end, an analog-to-digital converter (ADC) and a bunch of code. The USB
and FPGA details can be found in the [Appendix A].
A.1 Analog to Digital Converter (ADC)
The analog-to-digital converter is the bridge between the physical world of
continuous analog signals and the world of discrete digital samples manipulated by
software.
ADCs have two primary characteristics, sampling rate and dynamic range.
Sampling rate is the number of times per second that the ADC measures the analog
User Defined Code
USB FPGA DAC RF Front End
User Defined Code
USB FPGA ADC RF Front End
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
11
signal. Dynamic range refers to the difference between the smallest and largest signal
that can be distinguished; it's a function of the number of bits in the ADC's digital
output and the design of the converter. For example, an 8-bit converter at most can
represent 256 (28) signal levels, while a 16-bit converter represents up to 65,536
levels. Generally speaking, device physics and cost impose trade-offs between the
sample rate and dynamic range.
After getting through the ADC, the continuous signal becomes a sequence of
numbers entering the computer, which can be processed digitally as an array in the
software [3].
A.2 The RF Front End
To understand the role of the RF front end, we need to talk about a bit of theory.
Nyquist theorem tells us that, to avoid aliasing when converting from analog to
digital, the ADC sampling frequency must be at least twice the bandwidth of the
signal of interest, in order to sustain all the spectrum information accurately.Aliasing
is what makes the wagon wheels look like they're going backward in the old westerns:
the sampling rate of the movie camera is not fast enough to represent the position of
the spokes unambiguously [3].
Assuming we're dealing with low pass signals - signals where the bandwidth of
interest goes from 0 to fMAX, the Nyquist criterion states that our sampling frequency
needs to be at least 2 * fMAX. But if our ADC runs at 64 MS/s, how can we listen to
broadcast FM radio at 94.5 MHz? The answer is the RF front end. The receive RF
front end translates a range of frequencies appearing at its input to a lower range at its
output. For example, we could imagine an RF front end that translated the signals
occurring in the 90 - 100 MHz range down to the 0 - 10 MHz range.
Mostly, we can treat the RF front end as a black box with a single control, the center
of the input range that's to be translated. As a concrete example, a cable modem tuner
module translates a 6 MHz chunk of the spectrum centered between about 50 MHz
and 800 MHz down to an output range centered at 5.75 MHz. The center frequency of
the output range is called the intermediate frequency, or IF [3].
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
12
B. The Software
The digital signals finally get into the computer. What waits for them is our code-the
so called software. GNU Radio is a set of signal processing tools for the computer. It
encompasses hundreds of signal processing blocks and a few graphical utilities. It can
tie in with hardware such as USRP and various ADC/DAC PCI cards. Signal
processing blocks are written in C++, while creating flow graphs and connecting
signal blocks is done in an interpreted language called Python.
GNU Radio provides a library of signal processing blocks and the glue to tie it all
together. The programmer builds a radio by creating a graph (as in graph theory)
where the vertices are signal processing blocks and the edges represent the data flow
between them. Conceptually, blocks process infinite streams of data flowing from
their input ports to their output ports. Blocks' attributes include the number of input
and output ports they have as well as the type of data that flows through each. The
most frequently used types are short, float and complex.
Some blocks have only output ports or input ports. These serve as data sources
and sinks in the graph. There are sources that read from a file or ADC, and sinks that
write to a file, digital-to-analog converter (DAC) or graphical display. About 100
blocks come with GNU Radio. Graphs are constructed and run in Python [3].
B.1 Graphical User Interfaces
Graphical interfaces for GNU Radio applications are built in Python. Interfaces may
be built using any toolkit we can access from Python; wxPython is recommended to
maximize cross-platform portability. GNU Radio provides blocks that use
interprocess communication to transfer chunks of data from the real-time C++ flow
graph to Python-land [3].
C. Hardware Requirements
GNU Radio is reasonably hardware-independent. Today's commodity multi-gigahertz,
super-scalar CPUs with single-cycle floating-point units mean that serious digital
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
13
signal processing is possible on the desktop. A 3 GHz Pentium or Athlon can evaluate
3 billion floating-point FIR taps/s. We now can build, virtually all in software,
communication systems unthinkable only a few years ago.
Our computational requirements depend on what we're trying to do, but generally
speaking, a 1 or 2 GHz machine with at least 512 MB of RAM should suffice. We
also need some way to connect the analog world to our computer. Low-cost options
include built-in sound cards and audiophile quality 96 kHz, 24-bit, add-in cards. With
either of these options, we are limited to processing relatively narrow band signals
and need to use some kind of narrow-band RF front end [3].
Another possible solution is an off-the-shelf, high-speed PCI analog-to-digital board.
These are available in the 20M sample/sec range, but they are expensive, about the
cost of a complete PC. For these high-speed boards, cable modem tuners make
reasonable RF front ends.
Finding none of these alternatives completely satisfactory, the Universal
Software Radio Peripheral or USRP for short was designed [3]. Regarding the RF
front end and AD/DA converters, there are certainly many choices. However, the
Universal Software Radio Peripheral (USRP) board, which is designed wholly for
GNU Radio, is strongly recommended. In fact, most GNU Radio players are using
USRP boards. Not only because they are nice and convenient to use, but also because
we can get the most technical supports from the GNU Radio community. So, to make
our life simpler, we just choose the USRP.
D. The Universal Software Radio Peripheral (USRP)
Our preferred hardware solution is the Universal Software Radio Peripheral (USRP).
These days, when we talk about the GNU Radio, the Universal Software Radio
Peripheral (USRP) board has become an indispensable hardware component. It is
developed by Matt Ettus [4] wholly for the GNU Radio users. Basically, the USRP is
an integrated board which incorporates AD/DA converters, some forms of RF front
end, and a field programmable gate array (FPGA) which does some important but
computationally expensive pre-processing of the input signal. The USRP is low-cost
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
14
and high speed, which is the best choice for a GNU Radio user to implement some
real time applications. We could purchase the USRP board from Ettus Research LLC
[4].
Figure 5, shows the block diagram of the USRP. The brainchild of Matt Ettus, the
USRP is an extremely flexible USB device that connects our PC to the RF world. The
USRP consists of a small motherboard containing up to four 12-bit 64M sample/sec
ADCs, four 14-bit 128M sample/sec DACs, a million gate-field programmable gate
array (FPGA) and a programmable USB 2.0 controller. Each fully populated USRP
motherboard supports four daughterboards, two for receive and two for transmit. RF
front ends are implemented on the daughterboards. A variety of daughterboards are
available to handle different frequency bands. For amateur radio use, low-power
daughterboards are available that receive and transmit in the 440 MHz band and the
1.24 GHz band. A receive-only daughterboard based on a cable modem tuner is
available that covers the range from 50 MHz to 800 MHz. Daughterboards are
designed to be easy to prototype by hand in order to facilitate experimentation[3].
The flexibility of the USRP comes from the two programmable components on the
board and their interaction with the host-side library. To get a feel for the USRP, let's
look at its boot sequence. The USRP itself contains no ROM-based firmware, merely
a few bytes that specify the vendor ID (VID), product ID (PID) and revision. When
the USRP is plugged in to the USB for the first time, the host-side library sees an
unconfigured USRP [3].
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
15
Figure 5. The Universal Software Radio Peripheral (USRP) Block Diagram
Figure 6. The USRP main motherboard with the FPGA, 4 ADCs and 4 DACs (Image source: Ettus Research LLC)
Receive
Daughterboard
FPGA
DAC
DAC
ADC
ADC
ADC
ADC
DAC
DAC
FX2 USB 2.0
Controller
Receive
Daughterboard
Transmit
Daughterboard
Transmit
Daughterboard
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
16
The library can tell it's unconfigured by reading the VID, PID and revision. The first
thing the library code does is download the 8051 code that defines the behavior of the
USB peripheral controller. When this code boots, the USRP simulates a USB
disconnect and reconnect. When it reconnects, the host sees a different device: the
VID, PID and revision are different. The firmware now running defines the USB
endpoints, interfaces and command handlers. One of the commands the USB
controller now understands is load the FPGA. The library code, after seeing the USRP
reconnect as the new device, goes to the next stage of the boot process and downloads
the FPGA configuration bit stream [3].
FPGAs are generic hardware chips whose behavior is determined by the
configuration bit stream that's loaded into them. We can think of the bit stream as
object code. The bit stream is the output of compiling a high-level description of the
design. In our case, the design is coded in the Verilog hardware description language.
This is source code and, like the rest of the code in GNU Radio, is licensed under the
GNU General Public License [3]. A typical setup of the USRP board consists of one
mother board and up to four daughter boards, as shown in Figure 7. On the mother
board, we can see the DC power input and the USB 2.0
Figure 7. The USRP main motherboard with it’s up to 4 supporting daughter boards (Image source: USRP User’s and Developer’s Guide)
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
17
D.1. Features
• Four 64 MS/s 12-bit analog to digital Converters
• Four 128 MS/s 14-bit digital to analog Converters
• Four digital downconverters with programmable decimation rates
• Two digital upconverters with programmable interpolation rates
• High-speed USB 2.0 interface (480 Mb/s)
• Capable of processing signals up to 16 MHz wide
• Modular architecture supports wide variety of RF daughterboards
• Auxiliary analog and digital I/O support complex radio controls such as RSSI
and AGC
• Fully coherent multi-channel systems (MIMO capable)
D.2. Specifications
Supported Operating Systems
• Linux
• Mac OS X
• Windows XP, Windows 2000
• FreeBSD, NetBSD
Input
• Number of input channels: 4 (or 2 I-Q pairs)
• Sample rate: 64 Ms/s
• Resolution: 12 bits
• SFDR: 85 dB
Output
• Number of output channels: 4 (or 2 I-Q pairs)
• Sample rate: 128 Ms/s
• Resolution: 14 bits
• SFDR: 83 dB
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
18
Auxiliary I / O
• High-speed digital I/O: 64 bits
• Analog input: 8 channels
• Analog output: 8 channels
D.3. The daughter boards
On the mother board there are four slots, where we can plug in up to 2 RX daughter
boards and 2 TX daughter boards. The daughter boards are used to hold the RF
receiver interface or tuner and the RF transmitter.
There are slots for 2 TX daughter boards, labelled TXA and TXB, and 2
corresponding RX daughter boards, RXA and RXB. Each daughter board slot has
access to 2 of the 4 high-speed AD / DA converters (DAC outputs for TX, ADC
inputs for RX). This allows each daughter board which uses real (not IQ) sampling to
have 2 independent RF sections, and 2 antennas (4 total for the system). If complex
IQ sampling is used, each board can support a single RF section, for a total of 2 for
the whole system [5]. Different daughter boards handle different frequency ranges,
giving the USRP an overall potential range of 0 hertz to 2.9 gigahertz, which covers
everything from AM radio, through FM and television, to beyond Wi-Fi.
We can see there are two SMA connectors on each daughter board. We normally use
them to connect the input or output signals. Most of the USRP daughter boards use
SMA-F connectors for hooking up antennas.
There are several kinds of daughter boards available now from Ettus Research
[4].The daughter boards used in this project are only discussed in the following
section.
D.3.1 Basic Receiver (BasicRX) and Basic Transmitter (BasicTX) daughter
boards
1 MHz to 250 MHz Receiver and Transmitter
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
19
The BasicTX and BasicRX are designed for use with external RF frontends as an
intermediate frequency (IF) interface. Two SMA connectors are used to connect
external tuners or signal generators. We can treat it as an entrance or an exit for the
signal without affecting it. The ADC inputs and DAC outputs are directly
transformer-coupled to SMA connectors (50Ω impedance) with no mixers, filters, or
amplifiers.
The BasicTX and BasicRX give direct access to all of the signals on the
daughterboard interface (including 16 bits of high-speed digital I/O, SPI and I2C
buses, and the low-speed ADCs and DACs), and as such are useful for developing our
own daughterboards or custom FPGA designs.
Figure 8. Basic RX daughterboard (Image source: GNU Radio)
Figure 9. Basic TX daughterboard (Image source: GNU Radio)
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
20
D.4 The FPGA
An FPGA is like a small, massively parallel computer that we design to do exactly
what we want. Programming the FPGA takes a bit of skill, and mistakes can fry the
board permanently. That said, a standard configuration is provided that is useful for a
wide variety of applications.
Using a good USB host controller, the USRP can sustain 32 MB/sec across the USB.
The USB is half-duplex. Based on our needs, we can partition the 32 MB/sec between
the transmit and the receive directions. In the receive direction, the standard
configuration allows us to select the part or parts of the digitized spectrum we're
interested in, translate them to baseband and decimate as required. This is exactly
equivalent to what's happening in the RF front end, only now we're doing it on
digitized samples. The block of code that performs this function is called a digital
down converter (Figure 11, “Digital Down Converter Block Diagram”). One
advantage of performing this function in the digital domain is we can change the
center frequency instantaneously, which is handy for frequency hopping spread
spectrum systems [3].
In the transmit direction, the exact inverse is performed. The FPGA contains multiple
instances of the digital up and down converters. These instances can be connected to
the same or different ADCs, depending on our needs [3].
The FPGA being used on the USRP is an Altera Cyclone EP1C12Q240C8
The hardware language used to describe the functionality within the FPGA is written
in Verilog and synthesized using Altera's free web tool Quartus II. The FPGA runs off
a 64MHz clock with every internal component synchronous to that global clock. Due
to the relatively high clocking frequency, everything within the FPGA is highly
pipelined to achieve the highest speed possible [6].
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
21
Figure 10. The FPGA schematic [Appendix A – Details of the block diagram]
Figure 11. Digital Down Converter Block Diagram
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
22
NOTE: The function of the Digital Down Converter block is explained in Section
VIII, “Implementation of FM receiver”.
So far, we have completed the introduction to the software and hardware description
of our Software Defined Radio project. In the next few sections we will focus on the
software and the hardware setup / installation for our project.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
23
V. INSTALLATION OF GNU RADIO SOFTWARE AND USRP
A. Installation of GNU Radio Step-by-Step
In the following sections I would like to introduce the installation procedure of the
GNU Radio on the Linux Ubuntu 7.04 Machine and also would like to describe what
worked for me in the process of installation, the difficulties faced and how they were
resolved.
Installing GNU Radio is probably the biggest leap for a beginner. GNU Radio
can run on any platform, however, some installations are easier than others. GNU
Radio must be compiled from source and all of the dependencies have to be taken
care of. If our heart is set on Windows, we can install GNU Radio using Cygwin
[Appendix B]. If an extra PC can be spared, GNU Radio can be best installed on
Ubuntu Linux.
The GNU Radio software, in addition to its own code, relies on a lot of thirdparty
software from other free and open-source projects. Getting all this additional software
up and running is actually the trickiest part of setting up GNU Radio, and the
difficulty is compounded by both a lack of reliable documentation and out-of-date
software. The documentation is poor and just getting started is not obvious.
Once we have the software up and running, we know that programs for GNU Radio
are written using the C++ and Python languages. The conceptual approach is to treat
the various parts of the system as modules that send information to one another,
allowing programmers to concentrate on whatever piece they are interested in, while
treating the other modules as black boxes.
Routing between modules is done with Python, so that a developer might write
a Python program that uses an off-the-shelf “source” module, which grabs a chunk of
radio spectrum from the hardware, and a similar “sink” module, which sends the
output of the program to, say, a set of speakers or a radio transmitter. In between the
source and sink modules the developer could put a custom signal-processing module,
which itself would be written in C++ (signal processing is not done with Python for
performance reasons). This gives developers the ability to assemble working systems
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
24
rapidly. Plenty of sample programs are included with the software to give new
developers a head start.
A.1 Windows
GNU Radio definitely works in Windows XP.GNU Radio can be installed under the
Cygwin environment [Appendix B].
A.2 Linux
Ubuntu Linux is very nice for GNU Radio because all the dependencies can be easily
met. We simply have to select the correct check boxes and click install. Also, the
pains free and best part of Linux is that everything is open source and free.
What we will need:
• PC with USB 2.0 and DVD drive,
• Linux Ubuntu Edgy 6.10 or Feisty 7.04DVD,
• USRP,
• An internet connection,
• The better part of an afternoon.
B. Installation of GNU Radio on Linux
NOTE: This project uses the official release of GNU Radio software version 3.0.3.
The following procedures and scripts have been taken from the official GNU software
radio documentation [8].
B.1 Installation Options
Installation on Ubuntu 7.04 ("Feisty") systems may be completed using binary
packages and a package manager, or may be done by download and source compile.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
25
The following sections provides information and scripts to compile and install GNU
Radio and its required background applications, libraries, and includes on Ubuntu
Linux 6.10 ("Edgy") or 7.04 ("Feisty").
NOTE: The official releases of GNU Radio, version 3.0.3 or earlier, will NOT
reliably function on Feisty when using a USRP; the USRP will work once, then fail
and require the USRP to be power cycled or Ubuntu to be rebooted. Fixes for correct
functionality are available in the SVN trunk.
B.2 Pre-Requisites for Source Build
The following packages are required for compiling various parts of GNU Radio on
Ubuntu. These packages can be installed via "synaptic", "dselect", or "apt-get". We
use the latest versions of all packages unless otherwise noted.
Development Tools (need for compilation)
• g++
• subversion
• make
• autoconf, automake, libtool
• sdcc (from "universe"; 2.4 or newer)
• guile (1.6 or newer)
Libraries (need for runtime and for compilation)
• python-dev
• FFTW 3.X (fftw3, fftw3-dev)
• cppunit (libcppunit and libcppunit-dev)
• Boost (libboost and libboost-dev)
• libusb and libusb-dev
• wxWidgets (wx-common) and wxPython (python-wxgtk2.6)
• python-numpy (via python-numpy-ext) (for SVN on or after 2007-May-28)
• ALSA (alsa-base, libasound2 and libasound2-dev)
• Qt (libqt3-mt-dev; version 4 does not seem to work)
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
26
• SDL (libsdl-dev)
SWIG (1.3.31 or newer required)
• Edgy or previous: requires installation from source
• Feisty or newer: use the standard package install (swig)
QWT (optional) (5.0.0 or newer required)
• Must be installed from source (as of 2007-05-07), as both Edgy and Feisty
provide 4.2.
Other useful packages
• doxygen (for creating documentation from source code)
• usbview (from "universe")
• octave (from "universe")
B.3 Broken libtool on Debian and Ubuntu
Because Debian and Ubuntu apply a poorly implemented "enhancement" to the
upstream version of libtool, they break the ability to test code and libraries prior to
installing them. We think that testing before installation is a good idea. To work
around their damage, be sure to include $PREFIX/lib (and $PREFIX/lib64 on 64-bit
machines) in /etc/ld.so.conf.
If we don't include $PREFIX/lib in /etc/ld.so.conf, we will see errors during
the linking phase of the build. There are several places it shows up. The first one is
often during the build of mblocks. It's not an mblock problem. It's a Debian/Ubuntu
problem.
We do this to work around the "feature":
$ cp /etc/ld.so.conf /tmp/ld.so.conf
$ echo /usr/local/lib >> /tmp/ld.so.conf
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
27
$ sudo mv /tmp/ld.so.conf /etc/ld.so.conf
$ sudo ldconfig
B.4 Install Scripts
The following are scripts to take us through a GNU Radio install on a typical Ubuntu
Edgy or Feisty install, with the hope that it provides enough guidance such that we
can get GNU Radio up and running on our Ubuntu box.
• This section is for Edgy or previous only (no changes are needed on Feisty):
Manually we have to uncomment all repositories to include "universe" and
"multiverse" either via direct editing
sudo <EDITOR> /etc/apt/sources.list
or via the provided GUI: System -> Administration -> Software Sources. Then we
enter the admin password for access. On the "Ubuntu" tab, we have to make sure all
of "main restricted universe multiverse" are checked and the rest unchecked (or deal
with those are we deem correct for our setup). We click "Close", then "Reload" to
update the package list.
The uncommented lines of the file "/etc/apt/sources.list" should read something like:
deb http://us.archive.ubuntu.com/ubuntu/ edgy main restricted universe
multiverse
deb http://us.archive.ubuntu.com/ubuntu/ edgy-updates main restricted
universe multiverse
deb http://security.ubuntu.com/ubuntu/ edgy-security main restricted
universe multiverse
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
28
We update the local dpkg cache:
sudo apt-get update
Then we install required packages (some are likely already installed by Ubuntu by
default; some are likely redundant with others; but this group works well for both
Edgy and Feisty)
sudo apt-get -y install g++ automake1.9 libtool python-dev fftw3-dev
libcppunit-dev libboost-dev sdcc libusb-dev libasound2-dev libsdl1.2-dev
python-wxgtk2.6 subversion guile-1.6 libqt3-mt-dev python-numpy-ext
We also install optional packages, if desired; some might already be installed from the
previous command:
sudo apt-get -y install gkrellm wx-common libwxgtk2.6-dev alsa-base
autoconf xorg-dev g77 gawk bison openssh-server emacs cvs usbview octave
Get, Compile (if needed), And Install SWIG
• Edgy or previous:
$ wget http://superb-east.dl.sourceforge.net/sourceforge/swig/swig-
1.3.31.tar.gz
$ tar zxf swig-1.3.31.tar.gz
$ cd swig-1.3.31
$ ./configure
$ make
$ sudo make install
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
29
$ cd ..
• Feisty or newer:
sudo apt-get -y install swig
Get, Compile, Install QWT 5.0.0 or newer (optional):
• NOTE: We should not need to set the environment variables "QTDIR" or
"QWT_CFLAGS", so leave them be (for now).
wget http://superb-east.dl.sourceforge.net/sourceforge/qwt/qwt-5.0.2.tar.bz2
tar jxf qwt-5.0.2.tar.bz2
cd qwt-5.0.2
Now we edit qwtconfig.pri:
• Change the unix version of "INSTALLBASE" to "/usr/local" (was
"/usr/local/qwt-5.0.2");
• Change "doc.path" to "$$INSTALLBASE/doc/qwt" (was
"$$INSTALLBASE/doc");
• Save, exit.
The "doc" portion is in both HTML and man-style, but is all in /usr/local/doc/
html,man. While this isn't the standard path, there doesn't seem to be an easy way to
separate them and thus this is left as is. Then:
qmake
make
sudo make install
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
30
Download, bootstrap, configure, and compile GNU Radio:
svn co http://gnuradio.org/svn/gnuradio/trunk gnuradio
cd gnuradio
./bootstrap
./configure
make
Optionally: We run the GNU Radio software self-check; does not require a USRP.
make check
If any test or tests do not work, GNU Radio might still function properly, but it might
be wise to look in the email archives for a fix or to write the email list. If writing to
the email list, we need to include the OS type, OS version, and CPU type (e.g. via
"uname -a"), anything special about the computer hardware, software versions (gcc,
g++, swig, sdcc, etc) and how it has been installed (standard or non-standard package,
source).
Now we install GNU Radio for general use (default is in to /usr/local):
sudo make install
C. Installation of the USRP Hardware
When we unpack the hardware, we'll find various boards and screws and such. The
Ettus Research’s "USRP User's and Developer's Guide” [Appendix C], describes how
to assemble the hardware, and discusses some parts of the installation.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
31
WARNING : We plug in or unplug daughter boards only when the power is off.
If we forget this, we'll blow the tiny on-board fuse at "F501" (we can follow the trace
on top from the power connector; it's the first thing the trace leads to), and the board
will stop working.
Then we plug the Power cord into the USRP. We should see a green LED (hidden
under the "RXA" daughterboard, which is nearest to the USB connector) blinking at
about 2Hz (twice a second). Then we plug in the USB connector between the USRP
and the computer.
For the moment we will need to have root privileges to access the USRP.
We have to type "su" and hit Enter. When prompted for a password, we type the root
password and hit Enter.
NOTE: The following procedures and scripts have been taken from the official GNU
software radio documentation [8].
B.1 Installation scripts
Ubuntu uses udev for handling hotplug devices, and does not by default provide non-
root access to the USRP. The following script sets up groups to handle USRP via
USB, either live or hot-plug
sudo addgroup usrp
sudo addgroup <OUR_USERNAME> usrp
echo 'ACTION=="add", BUS=="usb", SYSFSidVendor=="fffe",
SYSFSidProduct=="0002", GROUP:="usrp", MODE:="0660"' > tmpfile
sudo chown root.root tmpfile
sudo mv tmpfile /etc/udev/rules.d/10-usrp.rules
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
32
• At this point, Ubuntu is configured to know what to do if/when it detects the
USRP on the USB, except that "udev" needs to reload the rules to include the newly
created one. The following might work, but if it doesn't then rebooting the computer
will.
sudo /etc/init.d/udev stop
sudo /etc/init.d/udev start
or
sudo killall -HUP udevd
We can check if the USRP is being recognized, by examining /dev/bus/usb after
plugging in a USRP. Using the command:
ls -lR /dev/bus/usb | grep usrp
This should result in one or more lines (one for each USRP) reading something like:
crw-rw---- 1 root usrp 189, 1 2007-11-07 21:46 002
Each device file will be listed with group 'usrp' and mode 'crw-rw----'.
• NOTE: If installing on Feisty, the computer may need to be rebooted in order
for the GNU Radio software to interface correctly with the USRP hardware. This does
not seem to be necessary on Edgy, just Feisty.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
33
VI. TESTING THE GNU RADIO SOFTWARE AND USRP
Once we've verified that the USRP is available to Ubuntu, now it is time to verify that
GNU Radio works with the USRP.Let us start with known functional Linux system
with USB support. We open two different terminal windows. If we like, we can also
run the "usbview" program. To see a real-time display of all log messages, we use one
of these terminals and execute:
tail -f /var/log/messages
Plug the Power cord into the usrp. Then plug in the USB connector between the usrp
and the computer. On the terminal with the log messages should be a message like:
new high speed USB device using address 1
If it says "full speed" rather than "high speed", either we do not have the correct
kernel module loaded for USB 2.0 or our hardware only supports USB 1.x.
Post-installation tasks
After installation, all the components mentioned above are installed in
/usr/local/lib/python2.4/site-packages, which is not included in Python’s working path
by default. To let the Python find these modules and for convenience, we’ll need to
set the PYTHONPATH environment variable as follows:
$ export PYTHONPATH=/usr/local/lib/python2.4/site-packages
We may want to add this to our ~/.bash_profile.
A Testing Data
From the "gnuradio" directory, we need to verify that all of the following work:
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
34
• The following script is used to show the Python interface to the USRP; the
program “benchmark_usb” provides a rough estimate of the maximum throughput
(quantized to a power of 2) between the host computer and the USRP. We type the
following:
cd gnuradio/gnuradio-examples/python/usrp
#contains the python examples for the single-usrp board
./benchmark_usb.py
Output
Testing 2MB/sec... usb_throughput = 2M
ntotal = 1000000
nright = 999916
runlength = 999916
delta = 84
OK
Testing 4MB/sec... usb_throughput = 4M
ntotal = 2000000
nright = 1998049
runlength = 1998049
delta = 1951
OK
Testing 8MB/sec... usb_throughput = 8M
ntotal = 4000000
nright = 3997535
runlength = 3997535
delta = 2465
OK
Testing 16MB/sec... usb_throughput = 16M
ntotal = 8000000
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
35
nright = 7996865
runlength = 7996865
delta = 3135
OK
Testing 32MB/sec... usb_throughput = 32M
ntotal = 16000000
nright = 15999436
runlength = 15999436
delta = 564
OK
Max USB/USRP throughput = 32MB/sec
While "benchmark_usb" might not return a full 32 MB/s of throughput, the script
should at least run properly; if not, either GNU Radio didn't make correctly or the
USRP isn't accessible.
• The following script is used to show the C++ interface to the USRP; the
programs “test_usrp_standard_tx” and “test_usrp_standard_rx” provides a good
estimate of the maximum throughput (non-quantized) between the host computer and
the USRP.
cd usrp/host/apps
./test_usrp_standard_tx
./test_usrp_standard_rx
Outputs
The output from test_usrp_standard_tx should look like this:
“xfered 1.34e+08 bytes in 4.19 seconds. 3.2e+07 bytes/sec. cpu time = 0.528
0 underruns”
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
36
The output from the test_usrp_standard_rx should look like this:
“xfered 1.34e+08 bytes in 4.19 seconds. 3.2e+07 bytes/sec. cpu time = 0.588
noverruns = 0”
To update the rest of the system, after which we might need to reboot, we use:
sudo apt-get -y upgrade
To upgrade the Linux distribution, after which a reboot is required, we use:
sudo apt-get -y dist-upgrade
B Testing Sound
$ cd gnuradio/gnuradio-examples/python/audio
$ python dial_tone.py
Output
This should produce a dial-tone through our speakers. If Python gives us an error
message, there is a problem with our installation of GNU Radio. If we get no error
messages but no sound, we check to see that our speakers are turned on, our volume is
turned up. We use Ctrl-C to stop the dialtone. With this minimal GNU Radio system
we can capture signals from our sound card, read signals from a file, or generate
signals; process signals; and play signals on our sound card or save them to a file.
To run this example, no USRP board is required, but the sound card equipped on our
computer.
C. Evaluation and Demo using the BasicRX Daughterboard
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
37
In the previous section, we know that GNU Radio with USRP has the ability to
communicate with each other. At this point we are ready to start exploring the full
potential of our new system! Now that our GNU Radio system is installed, it is time
to start exploring. The best way to learn about GNU Radio is to study and modify the
examples in the various subdirectories of gnuradio/gnuradio-examples/python. We
need to make sure that PYTHONPATH is set as described above.
We type the following and hit Enter:
cd gnuradio-examples/python/usrp
Now we can test our daughterboard by plugging in the BasicRX daughtercard in the
"RXA" connector, and run a spectrum analyzer. We type the following and hit Enter.
python usrp_fft.py -d 32 -f 94.5M
Output
The output of this script is shown in the figure 12. We are now looking at a GUI
display of a 2 MHz segment of the spectrum centered at 94.5 MHz with a random
moving blue line which represents the amplitude of the signal detected at that
frequency. To change the bandwidth, we can enter an even decimation factor (256 or
lower down to 4) into the "Decim" field. For example a decimator factor of 64 gives a
1 MHz segment of the spectrum around the center frequency, a decimator factor of 32
gives a 2 MHz segment of the spectrum and so on.
To change the center frequency, we enter the frequency (in Hz) into the
"Center freq" field. We can also enter the frequency in Mhz followed by a capital
"M". The frequency range shown is -1 MHz to +1 MHz below and above the center
frequency of 94.5 MHz. The plot’s vertical divisions are 200 kHz apart. A possible
active channel should be visible in plot display as wide bump centered around a
vertical division.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
38
Figure 12. Spectrum of the 93.5 – 95.5MHz FM band.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
39
Figure 13. Spectrogram of an FM Receiver with sidebands. GNU Radio and USRP running on Linux Ubuntu 7.04.
The above figure 13 shows the output of the same previous example but with a
different kind of frequency spectrogram. This plot is called as the Waterfall Model
display of the usrp_fft.py where we can see the strong FM band 96.1M with its
sidebands. We can change the frequency of interest by entering the value into the
“Center freq” field shown in the plot.
The spectrogram displays the strong FM bands in the vicinity and the flow of signals
falls from top to bottom. Hence it is called the Waterfall Model display of the
frequency spectrum of interest. The strong orange line in the middle shows the
presence or reception of the 96.1M FM band. The signals scattered around this line
displays the presence of other weak bands called the “side bands” with noise.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
40
VII. EXPLORING GNU RADIO PROGRAMS
A. Learning by Example
The quickest way to understand how to use GNU Radio is to start with some basic
examples. First an example, `dial tone', is chosen for illustration purpose. This is a
very simple `Hello World!' style example. But it should be enough to demonstrate the
strength and beauty of the graph mechanism in GNU Radio. In this example, we
simply generate two sine waves of different frequency and play the tones through the
sound card. Only the signal source and sink are involved, without real signal
processing. This is the same example which was used in the Testing section to test the
sound. The source code of this example is located in [Appendix D].
A.1. The Famous Phone-Tone Example [dial_tone.py]
#!/usr/bin/env python
Makes the python code executable by executing $ chmod +x “filename.py”.
from gnuradio import gr
from gnuradio import audio
from gnuradio.eng_option import eng_option
from optparse import OptionParser
Bring in blocks from the main gnu radio package. Import necessary modules from
GNU radio library.
class my_graph(gr.flow_graph):
Defining a function my_graph()and setting up signal flow graph. Two modules gr and
audio are imported first. Then a function my_graph (), is defined:
my_graph () is a global function within the module dial_tone.py,
def __init__(self):
gr.flow_graph.__init__ (self)
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
41
Create the flow graph. Instantiating a flow graph object from flow graph class.
flow_graph is a class defined in the module gr.flow_graph.py.
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
help="pcm output device name. E.g., hw: 0, 0 or /dev/dsp")
parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
help="set sample rate to RATE (48000)")
(options, args) = parser.parse_args ()
if len(args) != 0:
parser.print_help()
raise SystemExit, 1
The option parsers are used to provide the user, with different options to select types
of audio output devices, sampling rates etc. It accepts the user’s input arguments
when the program is executed in shell.
sample_rate = int(options.sample_rate)
ampl = 0.1
Two constants are defined. Sampling frequency and amplitude on soundcard.
src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)
src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl)
Create the signal sources.
Parameters are: sample rate, type, output freq, amplitude. Setting up sine waves at 350
and 440 Hz.
dst = audio.sink (sample_rate, options.audio_output)
Defining destination to be soundcard. That is, create a signal sink.
self.connect (src0, (dst, 0))
self.connect (src1, (dst, 1))
Connecting source and destinations, left and right channel.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
42
if __name__ == '__main__':
try:
my_graph().run()
except KeyboardInterrupt:
pass
Create code to execute or run the flow graph.
Explanation of the above illustration in brief
We start by creating a flow graph to hold the blocks and connections between them.
The two sine waves are generated by the gr.sig_source_f calls. The f suffix indicates
that the source produces floats. One sine wave is at 350 Hz, and the other is at 440
Hz. Together, they sound like the US dial tone.
‘audio.sink’ is a sink that writes its input to the sound card. It takes one or
more streams of floats in the range -1 to +1 as its input. We connect the three blocks
together using the connect method of the flow graph.
‘connect’ takes two parameters, the source endpoint and the destination
endpoint, and creates a connection from the source to the destination. An endpoint has
two components: a signal processing block and a port number. The port number
specifies which input or output port of the specified block is to be connected. In the
most general form, an endpoint is represented as a python tuple like this: (block,
port_number). When port_number is zero, the block may be used alone.
These two expressions are equivalent:
self.connect ((src1, 0), (dst, 1))
self.connect (src1, (dst, 1))
Once the graph is built, we start it. Calling start forks one or more threads to run the
computation described by the graph and returns control immediately to the caller. In
this case, we simply wait for any keystroke.
We run the program using: “python dial_tone.py” or simply “./dial_tone.py”and this
should produce the dial tone through our speakers.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
43
VIII. IMPLEMENTATION OF FM RECEIVER
A. Frequency Modulation
In order to better understand the FM receiver implemented using GNU Software
Radio platform, Frequency Modulation and Demodulation techniques will be briefly
introduced. Modulation is changing the characteristics of a carrier wave by the
message signal that is to be communicated from one station to the other. In frequency
modulation the amplitude of the message signal determines the variations in the
frequency of the carrier wave, which is a sinusoidal signal generated by a local
oscillator at the transmitting station. With FM, the instantaneous frequency of the
transmitted waveform is varied as a function of the input signal.Figure 13 illustrates a
Frequency Modulated signal at the output of a transmitter. Figure 13(a) shows m (t),
the input signal (the message, music and so forth), and s (t), Figure 13(b), the
resulting modulated output.
A message signal m (t), frequency modulating a carrier wave Ac cos (2πf
ct), results in
an FM signal in the form of ∫+t
fcc dmktfA0
))(22cos( ττππ , with instantaneous
frequency if = )(tmkf fc + [9], where m (t) is the input signal, k is a constant that
controls the frequency sensitivity and f c is the frequency of the carrier (for example,
100.1MHz). Frequency has units of radians per second. As a result, frequency can be
thought of as the rate at which something is rotating. If we integrate frequency, we get
phase, or angle. Conversely, differentiating phase with respect to time gives frequency
[11].
At the receiver end, the message signal is recovered by producing a signal
whose amplitude is directly proportional to the frequency of the FM wave. This
process is referred to as “Frequency Demodulation,” and the corresponding device is
called a “Demodulator.”[9]
These are the key insights we use to build the receiver.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
44
(a)
(b)
Figure 14. Frequency Modulation (Image source: Wikipedia)
Figure 14, shows an example of frequency modulation. The top diagram shows the
modulating signal (red signal) m (t) superimposed on the carrier wave (green signal).
The bottom diagram shows the resulting frequency-modulated signal.
B. FM Reception Methodology
In the GNU software radio, the antenna receives the signal; the Radio Frequency (RF)
front-end on the receiving daughterboard selects the channel chosen by the user via
software, and lowers the frequency range of the received signal from high RF range to
Intermediate Frequency (IF) band that can be handled by the Analog-to-Digital
Converter (ADC) [11]. An ADC, commonly characterized by its sampling rate and
dynamic range, converts the continuous analog signals received from the
daughterboard to digital samples that can be used by the software.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
45
Figure 15. Shows our setup of an FM Receiver using the BasicTX daughterboard, Antenna and USRP
B.1 Function of the Digital Down Converter
The digital signal is then fed to the Digital Down Converter (DDC) in the FPGA of
the USRP, where the samples are multiplied by digital sinusoidal signals with
frequencies equal to those of the input samples [5]. The product consists of a high
frequency component at twice the carrier frequency and a low frequency component
at zero. The low-pass filter of the DDC passes only the low frequency component,
which is the base band signal, and also allows data rate reduction of the signal. The
data rate of the base band signal is then reduced to match the USB port specifications.
Reducing the data rate of a signal or decimation is a common practice in signal
processing applications. According to Nyquist theorem, sampling rate has to be at
least twice the maximum frequency of the signal to be sampled, in order to avoid
aliasing. Aliasing occurs when the sampled signal is not the representation of a unique
analog signal. Assuming that signal x(n) has a frequency spectrum in the interval 0≤
|w| ≤ π, if the sampling rate is simply reduced by D, aliasing occurs, since the
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
46
sampling rate is no longer greater than 2fmax
[10]. Therefore, prior to reducing the
sampling rate, a lowpass filter, called decimation filter, reduces the signal bandwidth
to w (max) = π / D; The signal can then be safely down-sampled by a factor of D [10].
The block diagram of figure 16, illustrates the flow of the received signal from the
antenna to the USB port.
Next, software by means of a general purpose processor of a regular personal
computer performs the main signal processing on the data received from the USRP
and recovers the message signal. The software block called “Quadrature
Demodulator,” shown in Figure 16 (b), performs the main frequency demodulation.
The Quadrature Demodulator multiplies each input sample, which is a complex
number, by the complex conjugate of the adjacent sample and takes the arc tangent of
the product, in order to determine the angle between two subsequent samples:
After the signal is demodulated, a low pass filter structure selects the proper
portion of the FM spectrum and reduces the data rate to one that can be handled by
the sound card. A deemphazing stage is also necessary prior to the soundcard, which
is performed in the software. For most practical applications the power of the signal
diminishes significantly at high frequencies. Therefore, in the transmitter network,
high frequency components are amplified to improve the signal noise ratio (SNR).
This action is called “pre-emphasizing.” [5] At the receiver end, the opposite
operation, called de-emphasizing” is performed to deemphasize the high-frequency
components, allowing the recovery of the original signal power distribution.
Figure 16, shows our strategy for listening to an FM station. If we remove the carrier,
we're left with a baseband signal that has an instantaneous frequency proportional to
the original message m (t). Thus, our challenge is to find a way to remove the carrier
and compute the instantaneous frequency.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
47
Figure 16. Block Diagram of FM Receiver and Quadrature Demodulator
We get rid of the carrier by using our software digital downconverter (DDC) block,
fir_filter_ccf. This block is composed conceptually of a numerically controlled
oscillator that generates sine and cosine waveforms at the frequency that we want to
translate to zero, a multiplier and a decimating finite impulse response filter. The ccf
suffix indicates that this block takes a stream of complex on its input, produces a
stream of complexes on its output and uses floating-point taps to specify the filter
[11].
The digital downconverter does its job by taking advantage of a trigonometric identity
that says when you multiply two sinusoids of frequency f1 and f2 together, the result is
composed of two new sinusoids, one at f1+f2 and the other at f1-f2. In our case, we
multiply the incoming signal by the frequency of the carrier. The output consists of
two components, one at 2x the carrier and one at zero. We get rid of the 2x
component with a low-pass filter, leaving us the baseband signal [11].
ADC
D
Sine / Cosine generator
Basic RX D
Quad De-
Modulator
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
48
The next job is to compute the instantaneous frequency of the baseband signal. We
use the quadrature_demod_cf block for this. We approximate differentiating the phase
by determining the angle between adjacent samples. We recall that the downconverter
block produces complex numbers on its output. Using a bit more trigonometry, we
can determine the angle between two subsequent samples by multiplying one by the
complex conjugate of the other and then taking the arc tangent of the product [11].
Now our objective is to receive a Frequency Modulated (FM) signal by using the
modules in GNU Radio. Let us analyse the code line by line. This example
implements an FM receiver with graphical user interface. The source code of this
implementation is located in [Appendix E].
The explanation of the whole program is divided into 2 parts. The first half which will
follow hereafter focuses on the basics of Python. The second half which contains the
Graphical User Interface part of the program has been included in the [Appendix G].
C. FM Receiver Program
C.1 The first line (usrp_wfm_rcv.py [Appendix E])
If we have read the code of other examples, we can find the first line of these
programs is almost always
#! /usr/bin/env python
The Python scripts can be made directly executable if we put this line at the beginning
of the script and giving the file an executable mode. The '#!' must be the first two
characters of the file. The script is given the executable mode by using the 'chmod'
command [13]:
$ chmod +x usrp_wfm_rcv.py
Now the script usrp_wfm_rcv.py becomes executable. We can run this program in the
shell using
$. / usrp_wfm_rcv.py arguments
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
49
The Python interpreter will be invoked and the code in this script will be executed line
by line orderly. Python is an interpreted language, like Matlab script. No compilation
and linking is necessary. There are several ways to invoke the Python interpreter: we
can also use
$ python ./ usrp_wfm_rcv.py arguments
without the need to give the script the executable mode.
We can also use the interactive mode, by just typing the command in the shell:
$ python
then the Python interpreter environment will be invoked and we could input our code
line by line. However, this is obviously inconvenient. We seldom use the interpreter
interactively, unless we write some throw-away programs, test functions or use it as a
desk calculator. Most of the time, packing codes in a .py file and making the script
self-executable is more convenient to us [13].
C.2 Importing necessary modules
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
from gnuradio import blks2
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
from gnuradio.wxgui import stdgui2, fftsink2, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
import math
import wx
Understanding these statements requires the knowledge of 'module' and 'package'
concepts in Python. Here is a brief introduction. If we quit the Python interpreter and
enter it again, all the functions and variables we have defined are lost. Therefore, we
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
50
wish to write a somewhat longer program and save it as a script, containing function
and variable definitions, and maybe some executive statements. This script can be
used as the input of the Python interpreter. We may also want to use a fancy function
we've written in several programs without copying its definitions to each program
[13].
To support this, Python provides a module/package organization system. A module
is a file containing Python definitions and statements, with the suffix '.py'. Within a
module, the module's name (as a string) is available as the value of the global variable
'_ _name_ _'. Definitions in a module can be imported into other modules or into the
top-level module. A package is a collection of modules that have similar functions,
which are often put in the same directory. The '_ _init_ _.py' files are required to
make Python treat the directories as packages. A package could contain both modules
and sub-packages (can contain sub-sub-packages). We use 'dotted module names' to
structure Python's module namespace. For example, the module name A.B designates
a submodule named 'B' in a package named 'A'.
A module can contain executable statements as well as function definitions.
The statements are executed only the first time the module is imported somewhere
and so that the module is initialized. Each module has its own private symbol table,
which is used as the global symbol table by all functions defined within that module.
The author of a module can use the global variables in the module without worrying
about accidental clashes with the module user's global variables. As a module user,
we can access a module's function and global variables using `modname.itemname'.
Here the `itemname' can either be a function or a variable [13].
Modules can import other modules using `import' command. It is customary to place
all `import' statements at the beginning of a module. Note that the import operation
is quite flexible. We can import a package, a module, or just a definition within a
module. When we try to import a module from a package, we can either use `import
packageA.moduleB', or `from package A import module B'. When using `from
package import item', the 'item' can be either a module/sub-package of the package,
or some other names defined in the package, like functions, classes or variables. It's
worth taking a while to introduce the modules used in this example amply, because
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
51
these modules or packages will be frequently encountered in GNU Radio. The top-
level package of GNU Radio is 'gnuradio', which includes all GNU Radio related
modules. It is located at
/usr/local/lib/python2.4/site-packages
By default, this directory is not included in the Python's search path, we need to
export the path to the environment variable 'PATHONPATH'. So we usually add the
following line to the users' .bash_profile file:
export PATHONPATH=/usr/local/lib/python2.4/site-packages
to make sure the Python interpreter could find the gnuradio package.
gr is an important sub-package of gnuradio, which is the core of the GNU Radio
software. The type of ‘flow graph' classes is defined in gr and it plays a key role in
scheduling the signal flow [13].
eng notation is a module designed for engineers' notation convenience, in which many
words and characters are endowed with new constant values according to the
engineering convention. The module audio provides the interfaces to access the sound
card, while usrp provides the interfaces to control the USRP board. audio and usrp are
often used as the signal source and sink. blks is a sub-package, which is almost an
empty folder if we check its directory. It actually transfers all its tasks to another sub-
package blksimpl in gnuradio, as described in the __init__.py file. blksimpl provides
the implementation of several useful applications, such as FM receiver, GMSK, etc.
For this example, the real signal processing part of the FM receiver is performed in
this package [13].
Let us look at the next line, which is more interesting:
from gnuradio.eng_option import eng_option
This is exactly what we mentioned just now, we can either import a complete
module/sub-package, or, just a function, class or variable definition from this module.
In this case, eng option is a class defined in the module gnuradio.eng option. We don't
need the whole module to be imported, but just a single class definition. gnuradio.eng
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
52
option module does nothing but adding support for engineering notation to
optparse.OptionParser [13].
This line appears to have a similar format:
from gnuradio.wxgui import stdgui, fftsink
But the meaning is a little bit different; gnuradio.wxgui is a sub-package, not a
module, while stdgui and fftsink are two modules in this sub-package. It's not
necessary to import the whole sub-package, so we just import what we want
explicitly. gnuradio.wxgui provides visualization tools for GNU Radio, which is
constructed based on wxPython. The importing operations in Python provide us
great flexibility and convenience [13].
Finally, optparse, math, sys, wx are all Python or wxPython's built-in modules or sub-
packages, which are not part of the GNU Radio.
At this point, let us emphasize again, these modules imported above may
contain executable statements as well as the function or class definitions. The
statements will be executed immediately after the modules are imported. After
importing the modules and packages, a lot of variables, classes and modules defined
in them have been initialized.
C.3 Class definition
In this example, a large part of the code is the definition of a class 'wfm_rx_graph'.
The statement
class wfm_rx_graph (stdgui.gui_flow_graph):
defines a new class ‘wfm_rx_graph’, which is inherited (derived) from the base class,
or the so called 'father class' -- ‘gui_flow_graph’. The father class is defined in the
module stdgui we have just imported from gnuradio. By the rules of the namespace,
we use stdgui.gui_flow_graph to refer to it [13].
C.4 The family of 'FLOW GRAPH' classes
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
53
Here an important category of classes, which play a key role in GNU Radio should
receive particular attention: the 'flow graph' classes. There are a series of 'GRAPH'
related classes defined in GNU Radio. We can find that stdgui.gui_flow_graph is
derived from gr.flow_graph, which is defined in the sub-package gr. Further,
gr.flow_graph is derived from the 'root' class gr.basic_flow_class. In GNU Radio,
there are also many other classes derived from gr.basic_flow_graph. This big
'GRAPH family' makes GNU Radio programming neat and simple, also makes the
scheduling of the signal processing clear and straightforward [13].
In our example, wfm_rx_graph is such a graph class belonging to this family, with
GUI support. Later we will see it glues the necessary blocks in FM receiver together
using the method 'connect'.
C.5 The initialization function: _ _init_ _
Then we implement the method (or function) '__init__' of the class wfm_rx_graph.
The syntax for defining a new method is
def funcname(arg1 arg2 ...)
__init__ is an important method for any class. After defining the class, we may use
the class to instantiate an instance. This special method __init__ is used to create an
object in a known initial state. Class instantiation automatically invokes __init__ for
the newly created class instance. Actually in this example, __init__ is the only method
defined in the class wfm_rx_graph.
We notice that in this piece of code, there are no explicit signs for where a definition
of a class or a function starts and ends. Usually in other programming languages such
as C++ , we use 'begin' and 'end' pair, or a pair of '' and '' explicitly to denote the
two ends of a group of statements. However, in Python, this is no longer the case.
There are NO such signs. In Python, statement grouping is done by indentation
instead of beginning and ending brackets [13].
Now let's see what's going on in the function _ _init_ _.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
54
def __init__(self, frame, panel, vbox, argv):
declares the initialization method __init__ with four arguments. Conventionally, the
first arguments of all methods are often called self. This is nothing more than a
convention: the name self has absolutely no special meaning to Python. However,
methods may call other methods by using method attributes of the self argument, such
as 'self.connect( )' we will meet later.
The first thing __init__ does, is to call the initialization method of
stdgui.gui_flow_graph, its 'father class', with exactly the same four arguments [13].
stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
We may like to take a look at stdgui.gui_flow_graph's initialization method. Since
wfm_rx_graph is derived from it, we can safely think of wfm_rx_graph as a 'special'
gui_flow_graph. So it's natural that this 'son class' should do something to make
himself look like his father first, then do something fancy to make himself a different
guy.
C.6 Defining constants
From the next line, we kind of start to see real signals coming in.
(options, args) = parser.parse_args()
This sets the frequency, sample rate etc from the return value of the function
parser.parse_args(). The function parseargs is defined after the definition of the class
wfm_rx_graph. It accepts the user’s input arguments when the program is executed in
shell [13].
C.7 The signal source
The following several lines provide a very high level abstraction for the signal
processing procedure, which basically includes three components: the signal source,
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
55
the signal sink, and a series of signal processing blocks. This example gives those
signal processing blocks a very nice name: guts.
The signal source for the FM receiver is the USRP board in this example
# usrp is data source
self.u = usrp.source_c( )
OK, let's look at the code. usrp is the module we've imported at the beginning. The
usrp module is located at [13]:
/usr/local/lib/python2.4/site-packages/gnuradio/usrp.py
It tells us the module usrp is a wrapper for the USRP sinks (transmitting) and sources
(receiving). When a sink or a source is instantiated, the usrp module first probes the
USB port to locate the requested board number, then use the appropriate version
specific sink or source. ‘source_c’ is a function defined in usrp module. It returns a
class object that represents the data source. The suffix ‘_c’ means the data type of the
signal is `complex', because the signal coming into the computer is complex (actually
in real/imag pair). In contrast, we also have source_s method in the usrp module,
which is designed for 16-bit short integer data type [13].
Where are these methods defined? Actually all these methods are implemented using
C++. The SWIG provides the interfaces between C++ and Python, so that we can call
these functions directly in Python, without worrying about the implementation details
in C++. Boost, a smart pointer system, is also used here to facilitate the interaction
between C++ and Python.
The top level interfaces to the USRP are usrp_standard_rx and
usrp_standard_tx. Also we should take a look at their base classes, usrp_basic_rx,
usrp_basic_tx and usrp_basic. There are many other methods, to control and interact
with the USRP board [13].
Besides, we may have noticed that Python doesn't require variable or argument
declarations. This is totally different with the `declare before use' concept in C.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
56
adc_rate = self.u.adc_rate() # 64 MS/s
This line defines the sampling frequency of the AD converter, which should be set to
64MHz for the USRP users. According to Nyquist theorem, the maximum frequency
component of the interested signal should be less than 32MHz in order not to loose
spectrum information after sampling.
usrp_decim = 200
usrp_rate = adc_rate / usrp_decim # 320 kS/s
Decimation is a concept in DSP world. After sampling the analog signal, we get a
digital signal with very high data rate, which is a heavy burden for the CPU and
storage. Usually, we can down-sample the digital sequence (decimation) without
losing the spectrum information. In this example, the decimation rate is chosen to be
200 so that the resulting data rate is 320K samples per second, which is quite
reasonable and acceptable for our CPU speed. quad_rate represents for quadrature
data rate [13].
audio_decimation = 10
audio_rate = demod_rate / audio_decimation # 32 kHz
After processing the digital FM signal, we wish to play the signal using the sound
card of the computer. However, the data rate that a sound card can adopt is rather
limited. 320 kHz is usually too high and more than necessary. So we need to further
decimate the data rate. 32 kHz is a common choice for most sound cards.
OK, now let's design the FIR decimation filter. The GNU Radio block gr.fir_filter_ccf
gives us an FIR filter with float input, float output, and float taps. Its constructor takes
two arguments: the first one is the decimation factor; the second one is the filter
coefficients (taps) vector [13].
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
57
If we need an FIR filter without changing the data rate, then we just simply set the
decimation rate to be 1. If we need an interpolation filter rather than a decimation
filter, then the GNU Radio block gr.interp_fir_filter_xxx is what we should choose.
The filter coefficients chan_filt_coeffs are obtained using the FIR filter design block
optfir.low_pass( ) is a static public function defined in the class optfir. Similarly, it
also has high_pass( ), band_pass( ), band_reject() functions. We use these functions to
design the FIR filter taps, provided the filter parameters and specifications. The
syntax for design a low-pass filter is [13]:
chan_filt_coeffs = optfir.low_pass (1, # gain
usrp_rate, # sampling rate
80e3, # passband cutoff
115e3, # stopband cutoff
0.1, # passband ripple
60) # stopband attenuation
The meaning of each argument is quite obvious In our example, we select the audio
decimation factor (audio_decimation) to be 10, so that the resulting data rate for the
sound card is 32kHz.
C.8 The big signal processing 'gut'
There is a long story behind
self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
`guts' is the central processing block of this FM receiver. blks is a package in
gnuradio. It almost does nothing but refers to another package blksimpl. All signal
processing blocks, such as deemphasizing, noncoherent demodulation are glued
together in this `gut'. wfm_rcv is a class defined in /gnuradio/blksimpl/wfm_rcv.py
[13]. Also refer [Appendix F].
/usr/local/lib/python2.4/site-packages/gnuradio/blksimpl/wfm rcv.py
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
58
wfm_rcv is a class defined in the module blksimpl. Its base class is hier_block,
defined in the module gr.hier_block. gr.hier_block can be thought as a sub-graph,
containing several signal processing blocks, which is used as a single sophisticated
block in another bigger graph. In this statement, we create an object `self.guts' as the
instantiation of the class wfm_rcv. All real signal processing is done within this big
block [13].
C.9 The signal sink
Finally, we will play the demodulated FM signal using the sound card. So the audio
device is the signal sink in this example:
# sound card as final sink
audio_sink = audio.sink (int (audio_rate),
options.audio_output,
False) # ok_to_block
sink is a global function defined in the module audio. It returns an object as the signal
sink block. audio_rate is a parameter describing the data rate of the signal entering the
sound card, which is 32kHz in our example. OK! Our FM receiver is complete! The
signal is at the door of the sound card and is ready to be played [13].
C.10 Gluing them together
The next two lines finally complete our signal flow graph
# now wire it all together
self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink)
Just now we have talked about the family of the flow graph classes, to which the new
class wfm_rx_graph belong. All those flow graph classes are derived from the `root'
class gr.basic_flow_graph. The connect method is defined in gr.basic_flow_graph.
This method is designed for the flow graph to bind all the blocks together [13].
The signal flow graph is done at this point!
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
59
To run the ‘usrp_wfm_rcv.py’ program, we use the following commands in the shell:
$ cd gnuradio/gnuradio-examples/python/usrp
$ ./usrp_wfm_rcv.py -f 96M -g 75 - o 48000
We can choose the options from the shell by using the following: “-f” to select the
frequency of interest, “-g” to select the gain and “–o” to select the sampling rate of the
audio output device.
Figure 17 shows the output of the above script.
Figure 17. Shows the received FM station at 96 MHz and its post demodulated signal
OK, here ends the explanation of our FM Receiver program. In the following few
sections, we will see the various applications of our GNU Radio and USRP, and we
shall end this paper with some future work and conclusion.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
60
IX. PROMISES OF GNU RADIO AND USRP
A. Significance of USRP
The Universal Software Radio Peripheral (USRP) enables engineers to rapidly design
and implement powerful, flexible software radio systems. A large community of
developers and users have contributed to a substantial code base and provided many
practical applications for the hardware and software. The true value of the USRP is in
what it enables engineers and designers to create on a low budget and with a
minimum of effort. The powerful combination of flexible hardware, open-source
software and a community of experienced users makes it the ideal platform for our
software radio development [12].
A.1. Benefits
• Low cost, flexible platform
• Large community of developers
• Close coupling with the GNU Radio software framework forms a flexible and
powerful platform
• Reduced parts inventory
• DSP can compensate for cheaper RF
• Multiple Input Multiple Output(MIMO) systems
A.2. Applications
The USRP product family is in use all over the world in a wide variety of
applications. While the USRP is often used for rapid prototyping and research
applications, it has been deployed in several real-world commercial and defense
Systems.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
61
Figure 18. The USRP is in use in all 38 of the countries colored red in this map.
A.2.1 Commercial Applications
There are many applications for the USRP in commercial systems. System
development and prototyping is ideally done on a software radio. And when an
application does not have the volume to justify a custom hardware design, the
flexibility of the USRP enables a cost effective, deployable system.
As an example, Path Intelligence Ltd., uses the USRP product family to track
pedestrian foot traffic in shopping malls. The phased-array capabilities of the USRP
allow Path Intelligence to determine the locations of shoppers by receiving the
control-channel transmissions of cell phones [12].
A.2.2 Defense and Homeland Security
The USRP product family is being used by all branches of the U.S. military and
intelligence services, many large defense contractors and other NATO nations. The
USRP motherboard and daughterboards enable rapid prototyping and deployment of
sophisticated wireless systems on a low budget. Some applications include [12]:
• Battlefield networks, survivable networks
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
62
• JTRS research
• Public safety communications bridges
• Emergency low-power beacons
• Mine safety and underground communications
• Passive radar
Figure 19. JTRS Seal
A.2.3 Wireless Research
Numerous researchers in wireless networks are using the USRP product family to
study such diverse topics as [12]:
• MIMO systems
• Ad-hoc and mesh networking
• MAC-layer protocols
• Spectrum occupancy, spectrum sensing
• Cognitive radio
The open and easy to use USRP product family enables rapid prototyping of
innovative new communication systems. The low cost allows deployment of
significant numbers of nodes in a test-bed for studying large-scale network effects.
B. Significance of GNU Radio
GNU Radio is a free/open-source software toolkit for building software radios. GNU
Radio has a large worldwide community of developers and users that have contributed
to a substantial code base and provided many practical applications for the hardware
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
63
and software. It provides a complete development environment to create our own
radios, handling all of the hardware interfacing, multithreading, and portability issues
for us. GNU Radio has libraries for all common software radio needs, including
various modulations (GMSK, PSK, OFDM, etc.), error-correcting codes (Reed-
Solomon, Viterbi, Turbo Codes), signal processing constructs (optimized filters,
FFTs, equalizers, timing recovery), and scheduling [12].
GNU Radio provides functions to support implementing spectrum analyser, an
oscilloscope, concurrent multi-channel receiver and an ever-growing collection of
modulators and demodulators.
B.1 GNU Radio Applications
Projects under investigation or in progress include [3]:
• Time Division Multiple Access (TDMA) waveforms.
• A passive radar system that takes advantage of broadcast TV for its signal
source. For those of us with old TVs hooked to antennas, think about the
flutter we see when airplanes fly over.
• Radio astronomy.
• TETRA transceiver.
• Digital Radio Mundial (DRM).
• Software GPS.
• Distributed sensor networks.
• Distributed measurement of spectrum utilization.
• Amateur radio transceivers.
• Ad hoc mesh networks.
• RFID detector/reader.
• Multiple input multiple outputs (MIMO) processing.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
64
X. RELATED AND FUTURE WORK
In this academic semester, we built the environment of GNU radio, got familiar with
it, and learnt how to use the existing libraries to receive a Frequency Modulated signal
using our GNU Radio Software and the USRP Hardware. Some of the future
objectives of this project include: a) Implementation of a complete VHF and UHF
receiver system based on a TV tuner module using the TVRX daughterboard and
GNU Radio; b) Implementation of recovering the original message signal, for
example voice or music, from our FM demodulated signal is another future objective.
Implementing these functions in our demo will give us more convenience to deploy
future research project and stimulate us to develop more functions based on GNU
Radio environment.
XI. SUMMARY AND CONCLUSIONS
Researchers are currently using software radio–based systems to help them work on
problems in realms that include radio astronomy, telecommunications, and medical
imaging. Already a number of commercial products rely on software radio.
While software radio is still very much a work in progress, and general-
purpose processors still lack the computing power to fulfil all the dreams of
enthusiasts, we can get a taste of the future with the USRP. The hardware works in
concert with the software developed by the GNU Radio project, an international
collaboration of programmers who donate their time and skills. Software Radio is an
exciting field and definitely a nice system.
In this paper, we first introduce the concept of software-defined radio and the capacity
of GNU Radio and USRP. Afterward, we describe the related hardware support and
development environment respectively. We have introduced the FM receiver
techniques based on our demo, and how they are implemented using GNU Radio. At
last we present some possible future work. Through this project, we build up a
systematical knowledge and experience for developing GNU Radio applications and it
is very helpful for us to deploy a research-oriented project next.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
65
XII. REFERENCES
[1] "GNU." Wikipedia, The Free Encyclopedia. This page was last modified
19:09, 2 November 2007. <http://en.wikipedia.org/wiki/GNU>.
[2] “The GNU Operating System.” GNU’s Not Unix! - Free Software, Free
Society. <http://www.gnu.org/>.
[3] Blossom, Eric. “Exploring GNU Radio.” 29 November 2004, The GNU
software radio documentation.
<http://www.gnu.org/software/gnuradio/doc/exploring-gnuradio.html#intro>.
[4] Ettus, Matt. “Ettus Research, LLC” <www.ettus.com>.
[5] Shen, Dawei “SDR Documentation” Software-Defined Radio JNL Research
Group. University of Notre Dame, May 19 2005.
<http://www.nd.edu/~jnl/sdr/docs/>.
[6] “USRP FPGA.” The GNU software radio documentation wiki.
<http://www.gnuradio.org/trac/wiki/UsrpFPGA>.
[7] “Windows Installation.” The GNU software radio documentation wiki.
<http://www.gnuradio.org/trac/wiki/WindowsInstall>.
[8] “Ubuntu Installation Options.” The GNU software radio documentation wiki.
<http://www.gnuradio.org/trac/wiki/UbuntuInstall>.
[9] Haykin, Simon. An Introduction to Analog and Digital Communication.
McMaster University, John Wiley & Sons, Inc, 1989.
[10] Proakis, John. Manolakis, Dimitris. “Digital Signal Processing Principles,
Algorithims and Applications”, 3 rd Ed.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
66
[11] Blossom, Eric. “Listening to FM Radio in Software, Step by Step.” Linux
Journal. 1 Sep. 2004. <www.linuxjournal.com/article/7505>.
[12] “USRP Brochure.” Ettus Research LLC.
<http://www.ettus.com/Download.html>.
[13] Shen, Dawei “Tutorial 5: Getting Prepared for Python in GNU Radio by
Reading the FM Receiver Code Line by Line-Part I.” Software-Defined Radio
JNL Research Group. University of Notre Dame, 27 May 2005.
<http://www.nd.edu/~jnl/sdr/docs/tutorials/5.html>.
Software Defined Radio University of Western Australia
Sameer – 20184885 Project Report
67
XIII. SOURCES OF ILLUSTRATIONS
[Figure 1] “A GLONASS Receiver.” Online Image. Wikipedia, The Free
Encyclopedia. This page was last modified 02:08, 5 October 2007.
<http://en.wikipedia.org/wiki/Image:Glonass-reciever.jpg>
[Figure 2] “A GPS Receiver.” Online Image. Wikipedia, The Free
Encyclopedia. This page was last modified 02:08, 1 November 2007.
<http://en.wikipedia.org/wiki/Image:Magellan_GPS_Blazer12.jpg>
[Figure 6] “USRP and components.” Online Image. Ettus Research LLC.
<http://www.ettus.com/images/USRP.jpg>
[Figure 8] “USRP Daughterboard: BasicRX.” Online Image. GNU Radio.
<http://www.gnuradio.org/trac/wiki/UsrpDBoardBasicRX>
[Figure 9] “USRP Daughterboard: BasicTX.” Online Image. GNU Radio.
<http://www.gnuradio.org/trac/wiki/UsrpDBoardBasicTX>
[Figure 14] “Frequency Modulation” Online Image. Wikipedia, The Free
Encyclopedia. This page was last modified 02:08, 30 October 2007.
< http://en.wikipedia.org/wiki/Image:Frequency-modulation.png>
[Figure 18] “USRP around the world.” Online Image. GNU Radio.
<http://www.gnuradio.org/trac/wiki/USRP>
[Figure 19] “Joint Tactical Radio System” Online Image. Wikipedia, The Free
Encyclopedia. This page was last modified 02:08, 2 November 2007.
APPENDICES
APPENDIX A
The FPGA and USB details:
Probably understanding what goes on the FPGA is the most important part for GNU
Radio users. As shown in Figure 5, all the ADCs and DACs are connected to the
FPGA. This piece of FPGA plays a key role in the GNU Radio system. Basically
what it does is to perform high bandwidth math, and to reduce the data rates to
something you can squirt over USB2.0. The FPGA connects to a USB2 interface chip,
the Cypress FX2. Everything (FPGA circuitry and USB Microcontroller) is
programmable over the USB2 bus.
Our standard FPGA configuration includes digital down converters (DDC)
implemented with cascaded integrator-comb (CIC) filters. CIC filters are very high-
performance filters using only adds and delays. The FPGA implements 4 digital down
converters (DDC). This allows 1, 2 or 4 separate RX channels. At the RX path, we
have 4 ADCs, and 4 DDCs. Each DDC has two inputs I and Q. Each of the 4 ADCs
can be routed to either of I or the Q input of any of the 4 DDCs. This allows for
having multiple channels selected out of the same ADC sample stream.
The digital up converters (DUCs) on the transmit side are actually contained in the
AD9862 CODEC chips, not in the FPGA. The only transmit signal processing blocks
in the FPGA are the interpolators. The interpolator outputs can be routed to any of the
4 CODEC inputs.
The multiple RX channels (1, 2, or 4) must all be the same data rate (i.e. same
decimation ratio). The same applies to the 1, 2, or TX channels, which each must be at
the same data rate (which may be different from the RX rate).
Figure 10, The FPGA schematic, shows the block diagram of the USRP's receive path
and Figure 11 shows the diagram of the digital down converter. The MUX is like a
router or a circuit switcher. It determines which ADC (or constant zero) is connected
to each DDC input. There are 4 DDCs. Each has two inputs. We can control the MUX
using usrp.set_mux() method in Python.
Mux value:
Each 4-bit I field is either 0,1,2,3
Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
All Q's must be 0xf or none of them may be 0xf
We tell each input (I0, Q0, I1 ... I3, Q3) which ADC is connected to it by using 4 bits
(0, 1, 2, 3 or 0xf). So a 32-bit integer would be enough for all 8 inputs to know which
ADC is connected. Of course an integer in hexadecimal system will be more
convenient if we want to use the set_mux() method. For most real sampling
applications, the Q input of each DDC is constant zero. So quite often we don't need
to modify the standard configuration of the FPGA. Actually it is anticipated that the
majority of USRP users will never need to use anything other than the standard FPGA
configuration.
Now let's see the digital down converter (DDC). What does it do? First, it down
converts the signal from the IF band to the base band. Second, it decimates the signal
so that the data rate can be adapted by the USB 2.0 and is reasonable for the
computers' computing capability. The second part of Figure 3 shows the block
diagram of the DDC. The complex input signal (IF) is multiplied by the constant
frequency (usually also IF) exponential signal. The resulting signal is also complex
and centered at 0. Then we decimate the signal with a factor N.
The decimator can be treated as a low pass filter followed by a downsampler. Suppose
the decimation factor is D. If we look at the digital spectrum, the low pass ¯lter selects
out the band [-¼=D, ¼=D], and then the downsampler spread the spectrum in [-¼=D,
¼=D] to [-¼, ¼]. So in fact, we have narrowed the bandwidth of the digital signal of
interest by a factor of D. Regarding the bandwidth, we can sustain 32MB/sec across
the USB. All samples sent over the USB interface are in 16-bit signed integers in IQ
format, i.e. 16-bit I and 16-bit Q data (complex), resulting in 8M complex samples/sec
across the USB. This provides a maximum e®ective total spectral bandwidth of about
8MHz by Nyquist criteria. Of course we can select much narrower ranges by
changing the decimation rate. For example, suppose we want to design an FM
receiver. The bandwidth of a FM station is generally 200kHz. So we can select the
decimation factor to be 250. Then the data rate across the USB is 64MHz / 250 =
256kHz, which is well suited for the 200kHz bandwidth without losing any spectral
information. We can set the IF frequency of the DDC using usrp.set_rx_freq() method
and set the decimation factor using usrp.set_decim_rate() method in Python. The
decimation rate must be in [1, 256].
Note that when there are multiple channels (up to 4), the channels are interleaved. For
example, with 4 channels, the sequence sent over the USB would be I0 Q0 I1 Q1 I2
Q2 I3 Q3 I0 Q0 I1 Q1, etc. The USRP can operate in full duplex mode. When in this
mode, the transmit and receive sides are completely independent of one another. The
only consideration is that the combined data rate over the bus must be 32 Megabytes
per second or less.
OK! Finally the I/Q complex signal enters the computer via the USB. That's the
software world! At the TX path, the story is pretty much the same, except that it
happens reversely. We need to send a baseband I/Q complex signal to the USRP
board. The digital up converter (DUC) will interpolate the signal, up convert it to the
IF band and finally send it through the DAC.
APPENDIX B
Windows Installation
For more information on the Windows Installation scripts and procedures, see also
Reference [7] in the References section.
Windows Porting Issues
Considerable effort has been put into making the GNU Radio code portable among
various operating systems, by the GNU Radio developers, but there are several
reasons why it cannot be "simply" compiled and run under Windows:
• The build and install procedures are based on Linux scripts and tools
• Several third-party libraries are used, each with its own, often system-
dependent, installation procedure
• Most GNU Radio applications must interface to hardware (e.g., a sound card
or USRP) which require system-dependent drivers and installation procedures
• Because GNU Radio is written as an extension to Python, there are potential
problems on Windows if different runtime libraries are used for GNU Radio
and Python
The following sections show how these issues can be addressed.
Installation Options
GNU Radio is designed to be flexible. It has a number of modules, capabilities, and
options that can be enabled or disabled to suit the needs of the user, and the user can
add custom blocks or modules to the system.
To support this flexibility, it comes with a set of files and scripts to be used
with GNU software build tools (sh, make, autoconf, automake, etc.). These tools use
Linux-like commands and filenames that are not normally available on Windows
systems.
Cygwin
Cygwin is a Linux-like environment for Windows. It provides the Linux-like shell,
file naming, and build tools we need and also makes it easy to install many of the
third-party libraries required by GNU Radio. It also provides a Linux programming
interface (API); this is not required by GNU Radio, but it lets us use the better-tested
Linux versions of some functions.
Because the Linux API uses its own C runtime library, it is best to use Cygwin
versions of Python and the third-party libraries when building GNU Radio with
Cygwin.
Installing GNU Radio with Cygwin
The easiest way to install GNU Radio on Windows is to use the Cygwin environment.
Once Cygwin and the required utilities and third-party libraries are installed,
installation of GNU Radio is as easy on Windows as it is on Linux.
To install GNU Radio with Cygwin we need to:
• Install the Cygwin environment
• Install the required utilities and third-party libraries
• Build and install GNU Radio
• Install the driver for the USRP
One way to accomplish each of these steps is described below.
Installing Utilities and Third-Party Libraries
Utilities and third-party libraries are of two types: those that are available as Cygwin
packages and those that must be downloaded and/or built separately.
Installing Cygwin packages
Before installing any of these packages, we need to see the “hints, tips, known
problems, and solutions for Windows” section regarding python.
We will need the following Cygwin packages to build GNU Radio.
• autoconf
• automake1.10 (or automake1.9)
• binutils
• boost-devel
• gcc-core (version 3.4.4-2 or later preferred)
• gcc-g++ (version 3.4.4-2 or later preferred)
• libtool1.5
• make
• Numeric
• patch
• pkg-config
• python (get version 2.4.3-1; version 2.5 doesn't work with GNU Radio yet)
• swig (Note: Building from the SVN trunk requires version 1.3.31 or higher of
swig; until this version is available as a package, we will need to build our
own from source; see the “hints, tips, known problems, and solutions for
Windows” section.)
For the USRP we will also need:
• libusb-win32 (get version 0.1.10.1-3; version 0.1.12.0-1 doesn't work with
GNU Radio yet)
• SDCC (Small Device C Compiler);
To install from SVN we will need:
• subversion
Other libraries and utilities
Some of the libraries and utilities required by GNU Radio are not available as Cygwin
packages. These packages must be installed manually:
• FFTW: the Cygwin package does not include single precision;
• CppUnit: a C++ unit test framework;
• wxPython: not required for all applications, but extremely useful;
• NumPy (Numerical Python): a package of numerical extensions for python;
• Swig: you need version 1.3.31 or higher; see the “hints, tips, known problems,
and solutions for Windows” section.
For simultaneous capture and play of audio from the sound card or have difficulties
with the basic audio support, we may want:
• PortAudio:
Building and Installing GNU Radio
GNU Radio is a large system with many options. The simplest build procedure
configures and builds all the modules that it can, but we can customize our installation
(and maybe save some time) by specifying appropriate options. The sections below
show how to download the GNU Radio source code, build a minimal GNU Radio
system (recommended for the first test), and then how to build and install everything.
Downloading the GNU Radio Source Code
The simplest way to get the GNU Radio source code is to download the tarball from
ftp://ftp.gnu.org/gnu/gnuradio/gnuradio-3.0.4.tar.gz to a convenient working directory
and unpack it with
$ tar zxf gnuradio-3.0.4.tar.gz
to produce the directory gnuradio-3.0.4. The tarball includes stable versions of the
components needed by most users. If we prefer to get the latest versions of
everything, we can check out the code from the Subversion (SVN) repository with:
$ svn co http://gnuradio.org/svn/gnuradio/trunk gnuradio
$ cd gnuradio
$./bootstrap
This checks out the current version to a tree headed by a directory named gnuradio
and prepares for configuration. The following instructions assume the code is in
gnuradio-3.0.4
We may get warning messages, but unless one of these commands stops with an error
message we should have a working installation of GNU Radio. If we do get errors be
sure to check
.
Building a Minimal GNU Radio System
For a first test, it is helpful to build a minimal GNU Radio. This is done with the
commands:
$ cd gnuradio-3.0.4
$ ./configure --with-boost-include-dir=/usr/include/boost-1_33_1 --disable-
all-components --enable-gnuradio-core --enable-graudio-oss
This disables all components except those explicity enabled, namely gnuradio-core
and gr-audio-oss. To build and install these components we use the commands:
$ cd gnuradio-3.0.4
$ make
$ make check
$ make install
hints, tips, known problems, and solutions for Windows.
To use GNU Radio we need to tell Python where to find it:
$ export PYTHONPATH=/usr/local/lib/python2.4/site-packages
We can save our self some trouble by adding this line to our ~/.bash profile
This should produce a dialtone through our speakers. If Python gives an error
message, there is a problem with the installation of GNU Radio. If we get no error
messages but no sound, we need to check to see that the speakers are turned on, the
volume is turned up, and that the "Wave" source is enabled in the audio control panel.
We use Ctrl-C to stop the dialtone. If
file.
To actually make GNU Radio do something, we can try this:
$ cd gnuradio-3.0.4/gnuradio-examples/python/audio
$ python dial_tone.py
dial_tone.py stops by itself without producing
sound or gives a Windows error pop-up, then our version of Cygwin may be out of
date (see hints, tips, known problems, and solutions for Windows).
With this minimal GNU Radio system we can capture signals from our sound card,
read signals from a file, or generate signals; process signals; and play signals on our
sound card or save them to a file.
Building a Full GNU Radio System
Building a full GNU Radio system is simpler but takes longer:
$ cd gnuradio-3.0.4
$ ./configure –with-boost-include-dir=/usr/include/boost-1_33_1
This enables all components for which the required libraries and utilities are available.
To build and install these components we use the commands:
$ cd gnuradio-3.0.4
$ make
$ make check
$ make install
Unless one of these steps fails due to an error, we should have a working GNU Radio
installation. If one of the steps fails, we may be able to disable the component that
failed. We use “./configure –help” to see how the components are named. We look
for the "--enable-..." options and add the corresponding "--disable-..." option to our
./configure
Hints, Tips, Known Problems, and Solutions for Windows
command and repeat the above steps.
Installing the Driver for the USRP
For the USRP we will need to install the driver for it;
The following topics may be useful to users of GNU Radio on Windows.
A. tar.gz or tar.tar?
Sometimes when you download a package (e.g., FFTW or CppUnit) labelled
"thing.tar.gz" it will put on your system with the filename "thing.tar.tar
". I don't know
why this happens, but if it does you will need change any commands that refer to the
downloaded file to use the actual filename on your system.
B. Python on Cygwin
Python 2.4 is required by Numeric. wxPython also has unresolved issues with python
2.5. However, python 2.4 is no longer carried by the Cygwin mirrors. Therefore
installing it is a little tricky.
• Download a copy of Python 2.4 from
http://cygwin.rtin.bz/release/python/python-2.4.3-1.tar.bz2.
• Go to your cygwin packages directory and edit the setup.ini from the mirror
you use, so that it installs the version of python you downloaded as if it was
the current version. When editing release.ini, first find the section starting "@
python". Remove everything after from [prev] to end of the section. Modify
the "source:" line, so that it points to the package you downloaded. The two
numbers that appear after the package name are the file size (in bytes) and the
md5 checksum. You'll need to correct the file size. You can remove the
checksum altogether.
• Use the cygwin setup.exe to install the python package. Be sure to select
"Install from Local Directory" (not "Install from Internet"), otherwise your
changes to setup.ini will be lost.
• If you use cygwin setup.exe again later, make sure that the action for python is
always set back to "keep", otherwise cygwin may upgrade it to version 2.5.
If you've installed version 2.5 by accident, you may have to start again from scratch.
(Uninstalling didn't work for me.) You might have version 2.5 installed if you've tried
to install boost-devel, Numeric (or any other package that depends on python) before
following this procedure. To check which version you have installed, run cygcheck -c
python.
C. CppUnit on Cygwin
CppUnit is a library that assists in automated testing of GNU Radio. Unfortunately, it
takes a little care to get a working version of CppUnit under Cygwin. This is because:
• the Cygwin cppunit package version (1.9.14-1) does not work with GNU
Radio
• CppUnit version 1.10.2 requires a patch to the build scripts to install it under
Cygwin
• CppUnit versions 1.11.0 through 1.12.0 cause ‘make check’ to fail in the pmt
D. SWIG 1.3.31 on Cygwin
Building from the latest SVN trunk requires version 1.3.31 or later of SWIG, but (as
of Dec 2006) the latest version available as a Cygwin package is 1.3.29. SWIG 1.3.31
can easily be built from source:
module of GNU Radio because of a problem in the Cygwin g++ library
1. Use Cygwin setup to uninstall any existing version of SWIG
2. Download SWIG 1.3.31 from http://www.swig.org/download.html
3. Build and install with:
tar zxf swig-1.3.31.tar.gz
cd swig-1.3.31
./configure
make
make install
APPENDIX C
USRP User’s and Developer’s GuideMatt Ettus, Ettus Research LLC <matt@ettus.com>
This guide explains both basic usage of the USRP as well as how to expand it.
Table of ContentsIntroduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
SystemRequirements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Getting all the Software. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Usingyour USRP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Standard FPGA Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Daughterboard Interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Power . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Logical Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Analog Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Digital Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8ConnectorPinouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Available Daughterboards. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8BasicRX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9BasicTX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
IntroductionThe Universal Software Radio Peripheral, or USRP (pronounced "usurp") is designed to allow general purposecomputers to function as high bandwidth software radios. In essence, it serves as a digital baseband and IF section ofa radio communication system. In addition, it has a well-defined electrical and mechanical interface to RF front-ends(daughterboards) which can translate between that IF or baseband and the RF bands of interest
The basic design philosophy behind the USRP has been to do all of the waveform-specific processing, like modu-lation and demodulation, on the host CPU. All of the high-speed general purpose operations like digital up- anddownconversion, decimation and interpolation are done on the FPGA.
It is anticipated that the majority of USRP users will never need to use anything other than the standard FPGAconfiguration. However, for those users that wish to, the FPGA design may be changed or replaced. All of theinterfaces are well defined and documented.
Figure 1. USRP with Daughterboards
1
USRPUser’s and Devel-oper’s Guide
2
USRPUser’s and Devel-oper’s Guide
3
USRPUser’s and Devel-oper’s Guide
This USRP has 2 BasicTX and 2 BasicRX boards mounted on it. Notice that the boards on the left are rotated 180degrees.
System RequirementsThe USRP requires a PC or Mac with a USB2 interface.
CapabilitiesTheUSRP has 4 high-speed analog to digital converters (ADCs), each at 12 bits per sample, 64 million samples persecond. There are also 4 high-speed digital to analog converters (DACs), each at 14 bits per sample, 128 millionsamples per second. These 4 input and 4 output channels are connected to an Altera Cyclone EP1C12 FPGA. TheFPGA, in turn, connects to a USB2 interface chip, the Cypress FX2, and on to the computer. The USRP connects tothe computer via a high speed USB2 interface only, and will not work with USB1.1.
Figure 2. Universal Software Radio Peripheral
4
USRPUser’s and Devel-oper’s Guide
Getting StartedGetting all the SoftwareThe first step in using your USRP system is to get all of GNU Radio installed. This can sometimes be a dauntingprocess, as there are several other libraries which will need to be installed first.
Library Dependencies
• SWIG
We use SWIG (Simple Wrapper Interface Generator) to tie together the C++ and Python code in the GNU Radiosystem. We require that you have version 1.3.24 or newer. You’ll probably have to compile it from source, whichyou can find here: SWIG [http://www.swig.org]
• FFTW
FFTW is the library which GNU Radio uses for FFTs. GNU Radio requires version 3.0.1 or newer, and it mustbe compiled for single precision. You can get it from the FFTW Homepage [http://www.fftw.org]
• BoostLibrary
Boostprovides several low-level structures used in our C++ code. If it is not included in your OS distribution,you can get it here: Boost [http://boost.org]
• CPPUnit
CPPUnitprovides our unit-testing framework. This creates automated tests to insure that code does not breakwhen changes are made. Get it at the CPP Unit Homepage [http://cppunit.sf.net]
Getting GNU Radio and the USRP code
Thereare several packages of software which make up GNU Radio and the USRP support software. Links to the latestversions of each can be found on the GNU Radio Wiki at Download Links [http://comsec.com/wiki?GnuRadio2.X].Gr-build can greatly simplify the installation process, and its use it highly recommended.
Following CVS Development
Development for the USRP proceeds very quickly at times, so some users may want to keep up with the latest byfollowing the CVS trees. There are three separate software repositories which contain various parts of the USRPsystem.
• USRP-HW, containing the hardware and FPGA designs.
All of the schematics in this repository were created in gEDA [http://www.geda.seul.org]. The board layoutswere created in PCB [http://pcb.sf.net]. Verilog designs are compiled in Quartus II Web Edition from Altera[http://www.altera.com].
• USRP-SW [https://sourceforge.net/cvs/?group_id=22397], USRP-SW, containing firmware and host drivers forthe USRP
Host side drivers and firmware which runs in the USB2 interface chip on the board.
5
USRPUser’s and Devel-oper’s Guide
• GNU Radio/gr-usrp [http://comsec.com/wiki?CvsAccess] which contains the GNU Radio interface to the USRP
Using your USRP
Mechanical Connection
The USRP ships with a complete set of standoffs, nuts and bolts. There are 20 standoffs, M3x10mm M-F, of which 4are intended to be used as "feet" for the USRP. Place them in the 4 corner holes on the main board, inserting the malepart from below. The remaining 16 are used to hold the daughterboards in place. Four of them should be connectedto the male portion of the 4 standoffs already inserted from below. The remaining 12 should be connected to theboard with the 12 M3x6mm screws from below. At this point there should be 16 standoffs on the board with the maleends up to serve as a guide for the daughterboards. The 16 M3 nuts are used to fasten the daughterboards down to themain board.
TheUSRP accomodates 2 TX and 2 RX daughterboards. The placement of the standoffs is designed to prevent theaccidental incorrect connection of daughterboards. The 2 sides of the USRP have their daughterboard slots rotated180 degrees. The USRP should not be operated without standoffs, and daughterboards should never be connected orremoved while power is applied.
Electrical Connections
The USRP is powered by a 6V 4A power converter included in the kit. The converter is capable of 90-260 Vac, 50/60Hz operation, and so should work in any country. If there is a need to use another power supply, the connector is astandard 2.1mm/5.5mm DC power connector. The USRP itself only needs 5V at 2A, but a 6V supply was chosen toaccomodate future daughterboards. Extra power supplies are available from Ettus Research.
The included USB cable should be connected to a USB2-capable socket on a computer. The USRP does not supportUSB 1.1 operation at this time.
Troubleshooting
When first powered up, an LED on the USRP should be flashing at about 3-4x per second. This indicates that theprocessor is running, and has put the device in a low power mode. Once firmware has been downloaded to the USRP,the LED will blink at a slower rate. If there is no blinking LED, check all power connections, and check for continuityin the power fuse (F501, near the power connector). If the fuse needs replacement, it is size 0603, 3 amps.
FPGAStandard FPGA ConfigurationIn the standard fpga configuration, usrp_std, all samples sent over the USB interface are in 16-bit signed integers inIQ format. When there are multiple channels (up to 4), the channels are interleaved. For example, with 4 channels,the sequence would be I0 Q0 I1 Q1 I2 Q2 I3 Q3 I0 Q0, etc.
The USRP can operate in full duplex mode. When in this mode, the transmit and receive sides are completelyindependent of one another. The only consideration is that the combined data rate over the bus must be 32 Megabytesper second or less. The multiple RX channels (1,2, or 4) must all be the same data rate (i.e. same decimation ratio).The same applies to the 1,2, or TX channels, which each must be at the same data rate (which may be different fromthe RX rate).
On the RX side, each of the 4 ADCs can be routed to either of I or the Q input of any of the 4 downconverters. Thisallows for having multiple channels selected out of the same ADC sample stream.
6
USRPUser’s and Devel-oper’s Guide
The digital upconverters (DUCs) on the transmit side are actually contained in the AD9862 CODEC chips, not in theFPGA. The only transmit signal processing blocks in the FPGA are the interpolators. The interpolator outputs can berouted to any of the 4 CODEC inputs.
Figure 3. Digital Down Converter Block Diagram
Daughterboar d InterfacePowerDaughterboards are provided with clean regulated 3.3V for the analog and digital sections. Additionally there is a 6Vconnection straight from the wall supply which is intended to supply a 5V LDO regulator. All daughterboards maydraw a combined total of 1.5 A.
Logical Interface7
USRPUser’s and Devel-oper’s Guide
There are slots for 2 TX daughterboards, labeled TXA and TXB, and 2 corresponding RX daughterboards, RXA andRXB. Each daughterboard slot has access to 2 of the 4 high-speed data converter analog signals (DAC outputs for TX,ADC inputs for RX). This allows each daughterboard which uses real (not IQ) sampling to have 2 independent RFsections, and 2 antennas (4 total for the system). If IQ sampling is used, each board can support a single RF section,for a total of 2 for the whole system.
No antialias or reconstruction filtering is provided on the USRP motherboard. This allows for maximum flexibilityin frequency planning for the daughterboards. The analog input bandwidth of the ADCs is over 200 MHz, so IFfrequencies up to that high may be chosen. If several decibels of loss is tolerable, and IF frequency as high as 500MHz can be used.
Every daughterboard has an I2C EEPROM (24LC024 or 24LC025) onboard which identifies the board to the system.This allows the host software to automatically set up the system properly based on the installed daughterboard. TheEEPROM may also store calibration values like DC offsets or IQ imbalances. If this EEPROM is not programmed, awarning message is printed every time USRP software is run.
Analog InterfaceEach RX daughterboard has 2 differential analog inputs (VINP_A/VINN_A and VINP_B/VINN_B) which aresampled at a rate of 64 MS/s. The input impedance is approximately 1Kohm. The motherboard has a software-controllable programmable gain amplifier on these inputs, with 0 to 20 dB of gain. With gain set to zero, full scaleinputs are 2 Volts peak-to-peak differential. When set to 20 dB, only .2 V pk-pk differential is needed to reach fullscale.
If signals are AC-coupled, there is no need to provide DC bias as long as the internal buffer is turned on. It willprovide an approximately 2V bias. If signals are DC-couple, a DC bias of Vdd/2 (1.65V) should be provided to boththe positive and negative inputs, and the internal buffer should be turned off. VREF provides a clean 1 V reference.
Each TX daughterboard has a pair of differential analog outputs which are updated at 128 MS/s. The signals(IOUTP_A/IOUTN_A and IOUTP_B/IOUTN_B) are current-output, each varying between 0 and 20 mA. Sincethey are high-impedance, they can be converted into differential voltages with a resistor.
In addition to the high-speed signals, each daughterboard has exclusive access to 2 low-speed ADC inputs (labeledAUX_ADC_A and AUX_ADC_B) which can be read from software. These are useful for sensing RSSI signal levels,temperatures, bias levels, etc. Additionally, each board has shared access to 4 low-speed DAC signals, labeledAUX_DAC_A through AUX_DAC_D. RXA and TXA share one set of these 4 lines, and RXB and TXB sharetheir own independent set. These signals are useful for controlling gain of variable-gain amplifiers, for example.AUX_ADC_REF provides a reference level for gain setting if it is necessary.
Digital Interface
Connector Pinouts
Table 1. RX DBoard ConnectorPin # Name Description1 power This is powerc1 c4d1 d4 d5
8
USRPUser’s and Devel-oper’s Guide
Available DaughterboardsBasicRX
BasicTX
9
APPENDIX D
The source code of the “dial_tone.py” program:
#!/usr/bin/env python
from gnuradio import gr
from gnuradio import audio
from gnuradio.eng_option import eng_option
from optparse import OptionParser
class my_graph(gr.flow_graph):
def __init__(self):
gr.flow_graph.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
help="pcm output device name. E.g., hw:0,0 or /dev/dsp")
parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
help="set sample rate to RATE (48000)")
(options, args) = parser.parse_args ()
if len(args) != 0:
parser.print_help()
raise SystemExit, 1
sample_rate = int(options.sample_rate)
ampl = 0.1
src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)
src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl)
dst = audio.sink (sample_rate, options.audio_output)
self.connect (src0, (dst, 0))
self.connect (src1, (dst, 1))
if __name__ == '__main__':
try:
my_graph().run()
except KeyboardInterrupt:
pass
APPENDIX E
The source code of the FM Receiver (usrp_wfm_rcv.py) program:
#!/usr/bin/env python
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
from gnuradio import blks
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
from gnuradio.wxgui import stdgui, fftsink, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
import math
import wx
def pick_subdevice(u):
"""
The user didn't specify a subdevice on the command line.
Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
@return a subdev_spec
"""
return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
usrp_dbid.TV_RX_REV_2,
usrp_dbid.TV_RX_REV_3,
usrp_dbid.BASIC_RX))
class wfm_rx_graph (stdgui.gui_flow_graph):
def __init__(self,frame,panel,vbox,argv):
stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
help="select USRP Rx side A or B (default=A)")
parser.add_option("-f", "--freq", type="eng_float", default=100.1e6, help="set
frequency to FREQ", metavar="FREQ")
parser.add_option("-g", "--gain", type="eng_float", default=40, help="set gain in dB
(default is midpoint)")
parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume
(default is midpoint)")
parser.add_option("-O", "--audio-output", type="string", default="", help="pcm
device name. E.g., hw:0,0 or surround51 or /dev/dsp")
(options, args) = parser.parse_args()
if len(args) != 0:
parser.print_help()
sys.exit(1)
self.frame = frame
self.panel = panel
self.vol = 0
self.state = "FREQ"
self.freq = 0
# build graph
self.u = usrp.source_c() # usrp is data source
adc_rate = self.u.adc_rate() # 64 MS/s
usrp_decim = 200
self.u.set_decim_rate(usrp_decim)
usrp_rate = adc_rate / usrp_decim # 320 kS/s
chanfilt_decim = 1
demod_rate = usrp_rate / chanfilt_decim
audio_decimation = 10
audio_rate = demod_rate / audio_decimation # 32 kHz
if options.rx_subdev_spec is None:
options.rx_subdev_spec = pick_subdevice(self.u)
self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
print "Using RX d'board %s" % (self.subdev.side_and_name(),)
chan_filt_coeffs = optfir.low_pass (1, # gain
usrp_rate, # sampling rate
80e3, # passband cutoff
115e3, # stopband cutoff
0.1, # passband ripple
60) # stopband attenuation
#print len(chan_filt_coeffs)
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
self.volume_control = gr.multiply_const_ff(self.vol)
# sound card as final sink
audio_sink = audio.sink (int (48000),
options.audio_output,
False) # ok_to_block
# now wire it all together
self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink)
self._build_gui(vbox, usrp_rate, demod_rate, audio_rate)
if options.gain is None:
# if no gain was specified, use the mid-point in dB
g = self.subdev.gain_range()
options.gain = float(g[0]+g[1])/2
if options.volume is None:
g = self.volume_range()
options.volume = float(g[0]+g[1])/2
if abs(options.freq) < 1e6:
options.freq *= 1e6
# set initial values
self.set_gain(options.gain)
self.set_vol(options.volume)
if not(self.set_freq(options.freq)):
self._set_status_msg("Failed to set initial frequency")
def _set_status_msg(self, msg, which=0):
self.frame.GetStatusBar().SetStatusText(msg, which)
def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate):
def _form_set_freq(kv):
return self.set_freq(kv['freq'])
if 1:
self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
fft_size=512, sample_rate=usrp_rate)
self.connect (self.u, self.src_fft)
vbox.Add (self.src_fft.win, 4, wx.EXPAND)
if 1:
post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Demod", fft_size=1024,
sample_rate=usrp_rate, y_per_div=10, ref_level=0)
self.connect (self.guts.fm_demod, post_filt_fft)
vbox.Add (post_filt_fft.win, 4, wx.EXPAND)
if 0:
post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph", fft_size=512,
sample_rate=audio_rate, y_per_div=10, ref_level=-20)
self.connect (self.guts.deemph, post_deemph_fft)
vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)
# control area form at bottom
self.myform = myform = form.form()
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add((5,0), 0)
myform['freq'] = form.float_field(
parent=self.panel, sizer=hbox, label="Freq", weight=1,
callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
hbox.Add((5,0), 0)
myform['freq_slider'] = \
form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, range=(87.9e6,
108.1e6, 0.1e6), callback=self.set_freq)
hbox.Add((5,0), 0)
vbox.Add(hbox, 0, wx.EXPAND)
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add((5,0), 0)
myform['volume'] = \
form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", weight=3,
range=self.volume_range(), callback=self.set_vol)
hbox.Add((5,0), 1)
myform['gain'] = \
form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", weight=3,
range=self.subdev.gain_range(), callback=self.set_gain)
hbox.Add((5,0), 0)
vbox.Add(hbox, 0, wx.EXPAND)
try:
self.knob = powermate.powermate(self.frame)
self.rot = 0
powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
except:
print "FYI: No Powermate or Contour Knob found"
def on_rotate (self, event):
self.rot += event.delta
if (self.state == "FREQ"):
if self.rot >= 3:
self.set_freq(self.freq + .1e6)
self.rot -= 3
elif self.rot <=-3:
self.set_freq(self.freq - .1e6)
self.rot += 3
else:
step = self.volume_range()[2]
if self.rot >= 3:
self.set_vol(self.vol + step)
self.rot -= 3
elif self.rot <=-3:
self.set_vol(self.vol - step)
self.rot += 3
def on_button (self, event):
if event.value == 0: # button up
return
self.rot = 0
if self.state == "FREQ":
self.state = "VOL"
else:
self.state = "FREQ"
self.update_status_bar ()
def set_vol (self, vol):
g = self.volume_range()
self.vol = max(g[0], min(g[1], vol))
self.volume_control.set_k(10**(self.vol/10))
self.myform['volume'].set_value(self.vol)
self.update_status_bar ()
def set_freq(self, target_freq):
"""
Set the center frequency we're interested in.
@param target_freq: frequency in Hz
@rypte: bool
Tuning is a two step process. First we ask the front-end to
tune as close to the desired frequency as it can. Then we use
the result of that operation and our target_frequency to
determine the value for the digital down converter.
"""
r = usrp.tune(self.u, 0, self.subdev, target_freq)
if r:
self.freq = target_freq
self.myform['freq'].set_value(target_freq) # update displayed value
self.myform['freq_slider'].set_value(target_freq) # update displayed value
self.update_status_bar()
self._set_status_msg("OK", 0)
return True
self._set_status_msg("Failed", 0)
return False
def set_gain(self, gain):
self.myform['gain'].set_value(gain) # update displayed value
self.subdev.set_gain(gain)
def update_status_bar (self):
msg = "Volume:%r Setting:%s" % (self.vol, self.state)
self._set_status_msg(msg, 1)
self.src_fft.set_baseband_freq(self.freq)
def volume_range(self):
return (-20.0, 0.0, 0.5)
if __name__ == '__main__':
app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX")
app.MainLoop ()
APPENDIX F
Tutorial 7: Exploring the FM receiver
Dawei Shen∗
July 12, 2005
Abstract
In tutorial 5, we skip the discussion on how the FM signal is demodulated, leaving the big‘guts’ as a black box. In this article, the real signal processing techniques for demodulating theFM signal are introduced. We will dig into this black box and see how the signal is processed inthe software world.
1 Overview
In previous tutorials, we have introduced the hardware setup of GNU Radio and some programmingtips, which form the basis of a real application in the ‘soft world’. In this article, we will investigate howthe broadcast FM signal is demodulated. The FM receiver is a typical example in GNU Radio. Youare able to hear strong stations using just a piece of wire. In tutorial 5, we skipped the introductionto the big box ‘guts’, where the real magics of the FM detection are. We will show how the signal isprocessed from the air to the sound card in this tutorial.
2 From the air to the computer, from real to complex
In tutorial 3 and 4, we have discussed the operations on the USRP, especially the role of the digitaldown converter (DDC). Basically what the USRP does is to select the part of the spectrum we areinterested in and decimate the digital sequence by some factor N. The resulting signal is complex(gr_complex) with I/Q two channels. So after we finish writing these lines
src = usrp.source_c (0, decim) # decim = 250, so data rate (quad_rate) is 256kHzsrc.set_rx_freq (0, IF_freq) # IF_freq = our input - 128MHzsrc.set_pga(0,20)
we’ve got a ‘complex’ signal, with a data rate 256k samples per second. We name it ‘quadraturerate’ - quad_rate because the complex signal has I/Q quadrature components.
The IF frequency we choose is an interesting and useful point here. IF_freq is equal to the user’sinput minus 128MHz, as the line in function parseargs() indicates:
∗The author is affiliated with Networking Communications and Information Processing (NCIP) Laboratory,Department of Electrical Engineering, University of Notre Dame. Welcome to send me your comments orinquiries. Email: dshen@nd.edu
1
2 Tutorial 7 - Exploring the FM receiver
return freq1 - 128e6
wfm_rcv_gui was written assuming that there was no RF front end doing any down conversion. TheA/D sample rate is 64M. The Nyquist zones are therefore:
[0, 32M] normal[32M, 64M] inverted[64M, 96M] normal[96M, 128M] inverted
etc.
The problem is that 96M, one of the folding points, occurs right in the middle of the broadcastband. This means that 95.0 and 97.0 both alias down to the same frequency and can’t be distinguishedfrom each other. freq1 - 128M will give a valid frequency if freq1 is >= 96M. Bottom line: it’s akludge that sort of works.
3 Getting the instantaneous frequency, from complex to real
It’s time to dig into the heart of the ‘guts’ now, which we left as a big black box in tutorial 5.
guts = blks.wfm_rcv (self, quad_rate, audio_decimation)
blks is a package in gnuradio. It almost does nothing but refers to another package blksimpl.wfm_rcv is a class defined in /gnuradio/blksimpl/wfm_rcv.py, which is real ‘processor’ of the FMreceiver. The source code is appended at the end.
wfm_rcv is derived from gr.hier_block. gr.hier_block describes a series of blocks in tandemin a flow graph. It assumes that there is at most a single block at the head of the chain and a singleblock at the end of the chain. Either head or tail may be None indicating a sink or source respectively.hier_block could be recognized a sub-graph consisting of several blocks connected one after another.To construct a hier_block, we need to specify the flow graph that contains this hierarchical block,the first and the last block in the signal processing chain. A hierarchical block could be treated as acommon block, which could be placed and connected in a flow graph, like these lines demonstrate:
self.connect (src, guts)self.connect (guts, (audio_sink, 0))
The ‘head’ block in the chain is fm_demod, the instance of gr.quadrature_demod_cf. To under-stand the real work within it, we should know a bit about how FM signals are generated. With FM,the instantaneous frequency of the transmitted waveform is varied as a function of the input signal.The instantaneous frequency at any time is given by the following formula:
f(t) = k * m(t) + fc
m(t) is the input signal, k is a constant that controls the frequency sensitivity and fc is thefrequency of the carrier (for example, 100.1MHz). So to recover m(t), two steps are needed. Firstwe need to remove the carrier fc, then we’re left with a baseband signal that has an instantaneousfrequency proportional to the original message m(t). The second step is obviously to compute theinstantaneous frequency of the baseband signal. Thus, our challenge is to find a way to remove thecarrier and compute the instantaneous frequency. Removing the carrier has been done on the FPGA,via the digital down converter (DDC), as introduced in tutorial 3 and 4. We have explained why we
D. Shen 3
tune to (fc - 128MHz) in the preceding section. The resulting signal coming into the ‘guts’ has alreadybecome a baseband signal and the remaining task is to calculate its instantaneous frequency. If weintegrate frequency, we get phase, or angle. Conversely, differentiating phase with respect to timegives frequency. These are the key insights we use to build the receiver.
We use the gr.quadrature_demod_cf block for computing the instantaneous frequency of thebaseband signal. We approximate differentiating the phase by determining the angle between adjacentsamples. Recall that the digital down converter produces complex numbers on its output. Using abit more trigonometry, we can determine the angle between two subsequent samples by multiplyingone by the complex conjugate of the other and then taking the arc tangent of the product. Once youknow what you want, it doesn’t take much code. gr_quadrature_demod_cf.cc contains the C++implementation of this block. We will talk about how to write a signal processing block using C++in detail in tutorial 10 and 11. But it’s useful to give a shot at the code now. The bulk of the signalprocessing is the three-line loop in sync_work() function.
Part of gr_quadrature_demod_cf.cc...
intgr_quadrature_demod_cf::sync_work (
int noutput_items,gr_vector_const_void_star &input_items,gr_vector_void_star &output_items)
gr_complex *in = (gr_complex *) input_items[0];float *out = (float *) output_items[0];in++; // ensure that in[-1] is validfor (int i = 0; i < noutput_items; i++)gr_complex product = in[i] * conj (in[i-1]);out[i] = d_gain * arg (product);
return noutput_items;
A helpful diagram for the FM receiver can be found here.
fm_demod_gain = quad_rate/(2*math.pi*max_dev)
Note that fm_demod_gain can be treated as a constant controlling the volume. Its real valuedoesn’t matter. Here arg (product) is the phase difference between adjacent samples, if we divideit by the sample interval, i.e. multiply the data rate quad_rate, we get the radian frequency ω,which gives us the instantaneous frequency f if we further divide ω by 2π. Finally we normalize thefrequency by max_dev.
4 Deemphasizer
The second block in the chain is a deemphasizer deemph, an instance of the class fm_deemph. fm_deemphis defined in fm_emph.py, also located in the package blksimpl.
What is deemphasis? Let’s introduce it briefly. It has been theoretically proved that, in FMdetector, the power of the output noise increases with the frequency quadratically. However, formost practical signals, such as human voice and music, the power of the signal decreases significantlyas frequency increases. As a result, the signal noise ratio (SNR) at the high frequency end usuallybecomes unbearable. To circumvent this effect, people introduce ‘preemphasis’ and ‘deemphasis’ into
4 Tutorial 7 - Exploring the FM receiver
the FM system. At the transmitter, we use proper preemphasis circuits to manually amplify the highfrequency components, and do the converse operations at the receiver to recover the original powerdistribution of the signal. As a result, we improve the SNR effectively.
In the analog world, a simple first order RLC circuit usually suffices for preemphasis and deem-phasis. Here is a nice plot of their transfer functions. In our digital signal processing, a first order IIRfilter could be the right choice.
Part of fm_emph.py...
# 1# H(s) = -------# 1 + s## tau is the RC time constant.# critical frequency: w_p = 1/tau## We prewarp and use the bilinear z-transform to get our IIR coefficients.# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis#class fm_deemph(gr.hier_block):
"""FM Deemphasis IIR filter."""def __init__(self, fg, fs, tau=75e-6):
"""@type fs: float@param tau: Time constant in seconds (75us in US, 50us in EUR)@type tau: float"""w_p = 1/tauw_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq
a1 = (w_pp - 1)/(w_pp + 1)b0 = w_pp/(1 + w_pp)b1 = b0
btaps = [b0, b1]ataps = [1, a1]
deemph = gr.iir_filter_ffd(btaps, ataps)gr.hier_block.__init__(self, fg, deemph, deemph)
We start from the transfer function of the analog filter as prototype, and use bilinear transformationto get the digital IIR filter. Note that gr.iir_filter_ffd is the IIR filter block with float input,float output and double taps.
5 Audio FIR decimation filter
After passing the deemphasizer, how does the signal look like now? First, it’s a real signal with adata rate of 256kHz. Second, it’s a baseband signal, with effective frequency range from 0 to about100kHz, containing all the frequency components of a FM station.
As a side note, the bandwidth of a FM station is usually around 2 * 100kHz. This also explains
D. Shen 5
why we choose 256kHz as the quadrature rate (the decimation rate on the USRP is chosen to be 250).A sample rate of 256kHz is just suitable for the 200kHz bandwidth, without losing any spectruminformation. Maybe you have noticed, in the FM receiver, we never use any low-pass filtering operationto ‘pick out’ the FM station we are interested in. Actually this is done implicitly in the digital downconverter (DDC) on the USRP. Recall that digital down converter can be regarded as a low-pass FIRfilter followed by a downsampler. As a result, the target station is picked out then spread out tothe entire digital spectrum after decimation. Because we choose the right decimation rate, we haveeventually done a lot! The bottom line is, we are operating on a single FM station after the signalgoes through the USRP.
Now we need to resolve two issues. First, the signal rate is 256kHz now, much higher than what thesound card can adopt. The PC sound cards usually sample up to 96,000 Hz maximum. Second, the100kHz spectrum contains several channels, L + R, L - R, pilot tones, etc. To keep our life simpler, wejust want to design a mono receiver low-passing only the L + R signal. So clearly, an FIR decimationfilter is exactly what we want.
To make things clearer, here is a brief introduction to the FM signal band. From 0 to about 16kHzis the left plus right (L + R) audio. The peak at 19kHz is the stereo pilot tone. The left minus right(L - R) stereo information is centered at 2x the pilot (38kHz) and is AM-modulated on top of the FM.Additional subcarriers are sometimes found in the region of 57kHz - 96kHz. We can use the GNURadio built-in fft block with GUI supports to view the spectrum of the demodulated signal (detailswill be introduced in tutorial 8). Here is a nice real plot given by Eric. Here is a good illustration ofthe FM band.
OK, now let’s design the FIR decimation filter. The GNU Radio block gr.fir_filter_fff givesus an FIR filter with float input, float output, and float taps. Its constructor takes two arguments:the first one is the decimation factor, the second one is the filter coefficients (taps) vector.
self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
If we need an FIR filter without changing the data rate, then we just simply set the decimationrate to be 1. If we need an interpolation filter rather than a decimation filter, then the GNU Radioblock gr.interp_fir_filter_xxx is what we should choose.
The filter coefficients audio_coeffs are obtained using the FIR filter design block gr.firdes.low_pass() is a static public function defined in the class gr_firdes. Similarly, it also has high_pass(),band_pass(), band_reject() functions. We use these functions to design the FIR filter taps, pro-vided the filter parameters and specifications. For example, the syntax for design a low-pass filter is:
vector< float > gr_firdes::low_pass ( double gain,double sampling_freq,double cutoff_freq,double transition_width,win_type window = WIN_HAMMING,double beta = 6.76) [static]
The meaning of each argument is quite obvious. Note that beta is a parameter for Kaiser window.In our example, we select the audio decimation factor (audio_decimation) to be 8, so that theresulting data rate for the sound card is 32kHz. We are only interested in the L + R audio from 0 to16kHz, so we low pass the output of the quadrature demodulator with a cutoff frequency of 16kHz.This gives us a monaural output that we connect to the sound card outputs. In our example, wechoose the cutoff frequency as 15kHz and transition band as 1kHz, which is reasonable.
width_of_transition_band = audio_rate / 32audio_coeffs = gr.firdes.low_pass (volume, # gain (20)
6 Tutorial 7 - Exploring the FM receiver
quad_rate, # sampling rate (32kHz)audio_rate/2 - width_of_transition_band, (15kHz)width_of_transition_band, (16kHz)gr.firdes.WIN_HAMMING)
OK! Our FM receiver is complete! The signal is at the door of the sound card and is ready to beplayed. Note that the usage of FIR filters, as well as multirate processing is very important in thedigital signal processing.
Finally, we connect these blocks and call the __init__() method of gr.hier_block to completethe __init__() method of the wfm_rcv class. Here we need to specify the head and the tail of thepipeline.
fg.connect (self.fm_demod, self.deemph, self.audio_filter)gr.hier_block.__init__(self,
fg,self.fm_demod, # head of the pipelineself.audio_filter) # tail of the pipeline
6 Conclusion
In this article, we have introduced the FM detection techniques and how they are implemented usingGNU Radio. Now we can see GNU Radio is really a nice system, providing us so many powerful toolsand flexible ways to construct a real application. In next tutorial, we will wrap up the explanation ofwfm_rcv_gui.py, with an emphasis on the GNU Radio GUI tools.
APPENDIX A: The source code
from gnuradio import grfrom gnuradio.blksimpl.fm_emph import fm_deemphimport math
class wfm_rcv(gr.hier_block):def __init__ (self, fg, quad_rate, audio_decimation):
"""Hierarchical block for demodulating a broadcast FM signal.
The input is the downconverted complex baseband signal (gr_complex).The output is the demodulated audio (float).
@param fg: flow graph.@type fg: flow graph@param quad_rate: input sample rate of complex baseband input.@type quad_rate: float@param audio_decimation: how much to decimate quad_rate to get to audio.@type audio_decimation: integer"""volume = 20.
max_dev = 75e3fm_demod_gain = quad_rate/(2*math.pi*max_dev)audio_rate = quad_rate / audio_decimation
D. Shen 7
# We assign to self so that outsiders can grab the demodulator# if they need to. E.g., to plot its output.## input: complex; output: floatself.fm_demod = gr.quadrature_demod_cf (fm_demod_gain)
# input: float; output: floatself.deemph = fm_deemph (fg, quad_rate)
# compute FIR filter taps for audio filterwidth_of_transition_band = audio_rate / 32audio_coeffs = gr.firdes.low_pass (volume, # gain
quad_rate, # sampling rateaudio_rate/2 - width_of_transition_band,width_of_transition_band,gr.firdes.WIN_HAMMING)
# input: float; output: floatself.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
fg.connect (self.fm_demod, self.deemph, self.audio_filter)
gr.hier_block.__init__(self,fg,self.fm_demod, # head of the pipelineself.audio_filter) # tail of the pipeline
References
[1] Eric Blossom, Listening to FM Radio in Software, Step by Step,http://www.linuxjournal.com/article/7505
APPENDIX G
Tutorial 8: Getting Prepared for Python in GNU Radio by
Reading the FM Receiver Code Line by Line – Part II
Dawei Shen∗
July 13, 2005
Abstract
Let’s continue our discussion on the FM example wfm_rcv_gui.py. The usage of the GUItools in GNU Radio, which are built upon wxPython, will be shown. We will also introduce someuseful programming tips on argument parsing. If you are interested in using or even developingthe GUI tools, this article would be helpful.
1 Overview
In this article, we will complete our discussion on the FM receiver code wfm_rcv_gui.py. One excitingfeature of GNU Radio, is it incorporates powerful GUI tools for displaying and analyzing the signal,emulating the real spectrum analyzer and the oscillograph. We will introduce the usage of the GUItools, which are built upon wxPython. Next we will talk about how to handle the command linearguments in Python.
2 GUI tools in GNU Radio
The most intuitive and straightforward way to analyze a signal is to display it graphically, both intime domain and frequency domain. For the applications in the real world, we have the spectrumanalyzer and the oscillograph to facilitate us. Fortunately, in the software radio world, we also havesuch nice tools, thanks to wxPython, which provides a flexible way to construct GUI tools.
2.1 The ‘Spectrum Analyzer’ - fft sink
Let’s continue to read the code:
if 1:pre_demod, fft_win1 = \
fftsink.make_fft_sink_c (self, panel, "Pre-Demodulation",
∗The author is affiliated with Networking Communications and Information Processing (NCIP) Laboratory,Department of Electrical Engineering, University of Notre Dame. Welcome to send me your comments orinquiries. Email: dshen@nd.edu
1
2
512, quad_rate)self.connect (src, pre_demod)vbox.Add (fft_win1, 1, wx.EXPAND)
This is the ‘soft spectrum analyzer’, based on fast Fourier transformation (FFT) of the digitalsequence. This ‘soft spectrum analyzer’ is used as the signal sink. That’s why it is named as ‘fftsink’.It’s defined in the module wxgui.fftsink.py. The function make_fft_sink_c() serves as the publicinterface to create an instance of the fft sink:
/site-packages/gnuradio/wxgui/fftsink.py...def make_fft_sink_c(fg, parent, title, fft_size, input_rate, ymin=0, ymax=100):
block = fft_sink_c(fg, parent, title=title, fft_size=fft_size,sample_rate=input_rate, y_per_div=(ymax - ymin)/8, ref_level=ymax)
return (block, block.win)
First, we should point out that in Python, a function could return multiple values. make_fft_sink_c()returns two values: block is an instance of the class fft_sink_c, defined in the same modulewxgui.fftsink.py. Another special feature of Python needs to be emphasized: Python supportsmultiple inheritance. fft_sink_c is derived from two classes: gr.hier_block and fft_sink_base.Being a ‘son’ class of gr.hier_block implies that fft_sink_c can be treated as a normal block,which can be placed and connected in a flow graph, as the next line shows:
self.connect (src, pre_demod)
block.win is obviously an attribute of block. In the definition of the class fft_sink_c, wecan find its data type is the class fft_window, a subclass of wx.Window, also defined in the modulewxgui.fftsink.py. We can think of it as a window that is going to be hang up on your screen. Thiswindow block.win will be used as the argument of the method vbox.Add.
2.2 How wxPython plays its role
To understand the other parts thoroughly, we need to know a little bit about wxPython, a GUI toolkitfor Python. Interested readers may visit wxPython’s website or tutorials’ page for more information.It might be time consuming to explore all the technical details about wxPython. The good news is inGNU Radio, we can use the spectrum analyzer and oscillograph pretty much as it is. Just copythose lines anywhere you want with only a few changes.
Let’s invest some time in wxPython’s organism. The first thing to do is certainly to import allwxPython’s components into current workspace, like the line ‘import wx’ does. Every wxPythonapplication needs to derive a class from wx.App and provide an OnInit() method for it. The systemcalls this method as part of its startup/initialization sequence, in wx.App.__init()__. The primarypurpose of OnInit() is to create the frames, windows, etc. necessary for the program to beginoperation. After defining such a class, we need to instantiate an object of this class and start theapplication by calling its MainLoop() method, whose role is to handle the events. In our FM receiverexample, where is such a class defined? Let’s look at the last three lines:
if __name__ == ’__main__’:app = stdgui.stdapp (wfm_rx_graph, "WFM RX")app.MainLoop ()
In fact, such a class, called stdapp has been created when we import the stdgui module.
from gnuradio.wxgui import stdgui, fftsink
3
The final two lines again will probably be the same for all your wxPython applications. We simplycreate an instance of our application class, and then call its MainLoop() method. MainLoop() is theheart of the application and is where events are processed and dispatched to the various windows inthe application. There are some tricks behind the scene. Don’t worry about that.
Let’s look at the definition of stdapp in /gnuradio/wxgui/stugui.py:
class stdapp (wx.App):def __init__ (self, flow_graph_maker, title="GNU Radio"):
self.flow_graph_maker = flow_graph_makerself.title = title# All our initialization must come before calling wx.App.__init__.# OnInit is called from somewhere in the guts of __init__.wx.App.__init__ (self)
def OnInit (self):frame = stdframe (self.flow_graph_maker, self.title)frame.Show (True)self.SetTopWindow (frame)return True
stdapp is right the class derived from wx.App. Its initialization method __init__() takes twoarguments: flow_graph_maker, a class belonging to the flow graph family (remember the biggest classwfm_rx_graph we created is derived from gr.flow_graph?); title, the title of the whole application(WFM RX in our example). In OnInit() method, these two arguments are further used to create theobject of stdframe.
class stdframe (wx.Frame):def __init__ (self, flow_graph_maker, title="GNU Radio"):
# print "stdframe.__init__"wx.Frame.__init__(self, None, -1, title)
self.CreateStatusBar (2)mainmenu = wx.MenuBar ()
menu = wx.Menu ()item = menu.Append (200, ’E&xit’, ’Exit’)self.Bind (wx.EVT_MENU, self.OnCloseWindow, item)mainmenu.Append (menu, "&File")self.SetMenuBar (mainmenu)
self.Bind (wx.EVT_CLOSE, self.OnCloseWindow)self.panel = stdpanel (self, self, flow_graph_maker)vbox = wx.BoxSizer(wx.VERTICAL)vbox.Add(self.panel, 1, wx.EXPAND)self.SetSizer(vbox)self.SetAutoLayout(True)vbox.Fit(self)
def OnCloseWindow (self, event):self.flow_graph().stop()self.Destroy ()
def flow_graph (self):return self.panel.fg
4
It’s worth taking a while to understand the layout of a wxPython GUI. In wxPython, a wx.Windowis anything which can take up visual space on the computer screen. Thus, the wx.Window class isthe base class from which all visual elements are derived – including input fields, pull-down menus,buttons, etc. The wx.Window class defines all the behavior common to all visual GUI elements,including positioning, sizing, showing, giving focus, etc. If we’re looking for an object to representa window on the computer screen, don’t look at wx.Window, look at wx.Frame instead. wx.Frame isderived from wx.Window. It implements all behavior specific to windows on the computer’s screen. A‘Frame’ is a window whose size and position can (usually) be changed by the user. It usually has thickborders and a title bar, and can optionally contain a menu bar, toolbar and status bar. A ‘Frame’ cancontain any window that is not a frame or dialog. So to create a ‘window’ on the computer screen,you create a wx.Frame (or one of its sub-classes, such as wx.Dialog), rather than a wx.Window.
Within a frame, you’ll use a number of wx.Window sub-classes to flesh out the frame’s con-tents, such as wx.MenuBar, wx.StatusBar, wx.ToolBar, sub-classes of wx.Control (eg. wx.Button,wx.StaticText, wx.TextCtrl, wx.ComboBox, etc.), or wx.Panel, which is a container to hold yourvarious wx.Control objects. All visual elements (wx.Window objects and their subclasses) can holdsub-elements. A wx.Frame might hold a number of wx.Panel objects, which in turn hold a numberof wx.Button, wx.StaticText and wx.TextCtrl objects.
In our example, stdframe, the subclass of wx.Frame, is used to create the ‘frame’. We make thisframe appear by ‘showing’ it using frame.Show (True). The SetTopWindow() method simply tellsthat this frame is one of the main frames (in this case the only one) for the application. Notice theshape of the constructor of wx.Frame:
wx.Frame(Parent, Id, "title")
Most of the constructors in wxPython have this shape: A parent object as a first parameter and anId in a second parameter. As shown in the example, it’s possible to use respectively None and -1 asdefault parameters, meaning the object has no parent and respectively a system-defined Id.
In stdframe.__init__(), we create a panel and place inside the frame.
self.panel = stdpanel (self, self, flow_graph_maker)
The class stdpanel is derived from wx.Panel:
class stdpanel (wx.Panel):def __init__ (self, parent, frame, flow_graph_maker):
wx.Panel.__init__ (self, parent, -1)self.frame = frame
vbox = wx.BoxSizer (wx.VERTICAL)self.fg = flow_graph_maker (frame, self, vbox, sys.argv)self.SetSizer (vbox)self.SetAutoLayout (True)vbox.Fit (self)
self.fg.start ()
Note that panel’s parent is the frame object we create just now, meaning this panel is a subcom-ponent of the frame. The frame places the panel inside itself using a wx.BoxSizer, vbox. The basicidea behind a box sizer is that windows will most often be laid out in rather simple basic geometry,typically in a row or a column or nested hierarchies of either. A wx.BoxSizer will lay out its itemsin a simple row or column, depending on the orientation parameter passed to the constructor. Inour example, vbox = wx.BoxSizer(wx.VERTICAL) tells the constructor all the items will be placedvertically. The SetSizer() call tells the frame which sizer to use. The call to SetAutoLayout() tells
5
the frame to use the sizer to position and size your components. And finally, the call to sizer.Fit()tells the sizer to calculate the initial size and position for all its elements. If you are using sizers, thisis the normal process you would go through to set up your window or frame’s contents before it isdisplayed for the first time. The most important and useful method for a sizer is add(), it appendsan item to the sizer. Its syntax looks like:
Add(self, item, proportion=0, flag=0)
‘item’ is what you wish to append to the sizer, usually a wx.Window object. It can also be a childsizer. proportion is related to whether a child of a sizer can change its size in the main orientation ofthe wx.BoxSizer. There are several flags defined in wx, and they are used to determine how the sizeritems behave and the border of the window. wx.EXPAND used in our example means the item will beexpanded to fill the space allotted to the item. Refer to this page for a complete description.
Have you ever had this confusion: we define a ‘big’ class wfm_rcv_graph, but where do we use it?why do we never create an instance of this class? The secret is revealed in stdpanel.__init__().The instance of wfm_rcv_graph is created here and the flow graph is started.
class stdpanel (wx.Panel):def __init__ (self, parent, frame, flow_graph_maker):
......vbox = wx.BoxSizer (wx.VERTICAL)self.fg = flow_graph_maker (frame, self, vbox, sys.argv)self.SetSizer (vbox)self.SetAutoLayout (True)vbox.Fit (self)self.fg.start ()
We put a panel in the frame, but what do we put in the panel? We first create a new sizervbox for the panel. Note that this vbox is different from the one defined in stdframe. Then wecreate an instance of flow_graph_maker (wfm_rcv_graph) with vbox as an argument passed to it(also with frame and the panel itself). In wfm_rcv_graph.__init__(), this vbox will append severalspectrum analyzers or oscillograph (wx.Window objects) to the sizer by using vbox.Add(). Then thepanel uses the sizer vbox position and size all these child-windows. Finally, we start the flow graph:self.fg.start(), the corresponding data would be displayed on the screen dynamically.
Let’s go back to the code of our FM receiver example.
if 1:pre_demod, fft_win1 = \
fftsink.make_fft_sink_c (self, panel, "Pre-Demodulation",512, quad_rate)
self.connect (src, pre_demod)vbox.Add (fft_win1, 1, wx.EXPAND)
and the definition of the make_fft_sink_c() method:
/site-packages/gnuradio/wxgui/fftsink.py...def make_fft_sink_c(fg, parent, title, fft_size, input_rate, ymin=0, ymax=100):
block = fft_sink_c(fg, parent, title=title, fft_size=fft_size,sample_rate=input_rate, y_per_div=(ymax - ymin)/8, ref_level=ymax)
return (block, block.win)
Everything is much clearer now, right? panel is passed to make_fft_sink_c() as the ‘parent’ ofthis fft sink (block.win, a wx.Window object). The return value of block.win is saved in fft_win1and then appended to vbox.
6
make_fft_sink_c() takes seven parameters. fft_size is the number of samples used to performFFT. input_rate is the sample frequency. ymin and ymax give the vertical range of the plot you wishto display on the screen.
Note that there is a complicated story behind the class fft_sink_c. We didn’t talk about how fastFourier transform is performed and how it is used as a block, but focusing on its interface to Pythonand wxPython. In fact, another Python package called ‘Numeric’ helps a lot here. However, we don’tneed to know all the details. Understanding how it interacts with wxPython and other blocks at thePython level would be sufficient.
2.3 The ‘Oscillograph’- scope sink
Another important GUI tool in GNU Radio is the ‘soft oscillograph’ - scope_sink. It’s not used inour example, but it would be very helpful if you wish to see the waveforms in the time domain. Itsusage is quite similar to the fft_sink:
if 1:scope_input, scope_win1 = \
scopesink.make_scope_sink_f (self, panel, "Title", self.fs)self.connect (signal, scope_input)vbox.Add (scope_win1, 1, wx.EXPAND)
Note that here signal should be a real float signal. If you wish to display a complex signal withI/Q channels, make_scope_sink_c() is the right choice. Copy these lines wherever you think a scopeshould appear, then connect it to the signal as a block. Refer to /site-packages/gnuradio/wxgui/scopesink.pyfor more details.
3 Handling command line arguments
Python fully supports creating programs that can be run on the command line, complete withcommand-line arguments and either short- or long- style flags to specify various options. Remem-ber when we create an instance of wfm_rcv_graph in stdpanel.__init__(), we use:
self.fg = flow_graph_maker (frame, self, vbox, sys.argv)
Each command line argument passed to the program will be saved in sys.argv, which is just a ‘list’. Inthis list, sys.argv[0] is just the command itself (wfm_rcv_gui.py in our example). So actually all thearguments are saved in sys.argv[1:]. That explains why we use IF_freq = parseargs(argv[1:])to process the arguments.
You may want to use short- or long- style flags to add various options like ‘-v’, or ‘--help’. Thenthe optparse module is exactly what you would like to use. optparse is a powerful and flexiblecommand line interpreter. You may see this page to study it. Another example, located at
gnuradio-examples/python/usrp/fsk_r(t)x.py
gives a very good demonstration on how to use this parser.
4 conclusion
This tutorial completes our discussion on the FM receiver example. We mainly talk about howwxPython plays its role in GNU Radio. It might be a little bit involved to understand how those
7
classes are organized together, but it won’t be that difficult if we are patient enough. Besides, thegood news is we can simple use those codes as templates, without worrying too much about theimplementation details.
References
[1] Python on-line tutorials, http://www.python.org/doc/current/tut/
[2] Python Library Reference - optparse,http://www.python.org/doc/2.3/lib/module-optparse.html
[3] wxPython on-line tutorials, http://wxpython.org/tutorial.php
[4] wxPython wiki, Getting started, http://wiki.wxpython.org/index.cgi/Getting 20Started
APPENDIX H
Libraries and Modules in GNU radio package:
Inside the site-packages:
gnuradio
blks:
__init__.py This file is required to make Python treat the
directories as packages
blksimpl:
am_demod.py AM demodulation block
dbpsk.py Differential BPSK modulation and demodulation
dqpsk.py Differential QPSK modulation and demodulation
filterbank.py Include both synthesis and analysis
fm_demod.py Generalized FM demodulation block
fm_emph.py FM deemphasis and preemphasis IIR filter
gmsk.py GMSK modulator and demodulator
__init__.py nothing
nbfm_rx.py Narrow band FM receiver
nbfm_tx.py Narrow band FM transmitter
pkt.py mod/demod with packets as i/o (sending packets
and demodulating/deframing packets)
psk.py define different kinds of PSK (BPSK, QPSK,
8PSK)
rational_resampler.py Rational resampling polyphase FIR filter
standard_squelch.py Implement the squelch function
wfm_rev.py Demodulating a broadcast FM signal
wfm_rcv_pll.py Demodulating a broadcast FM signal with stereo
wfm_tx.py Wide band FM Transmitter
gr
Basic_flow_graph.py Constructs the basic graph and provides basic
operations on the graph
(base class of “flow_graph”)
exceptions.py Exception handling (not finished yet)
flow_graph.py Define the type of flow graph and play an key role
in scheduling the signal control
gnuradio_swig_python.py Automatically created by SWIG
gr_threading.py Choose load gr_threading_23.py or
gr_threading_24.py
gr_threading_23.py Threading module for version 2.3
gr_threading_24.py Threading module for version 2.4
hier_block.py Construct hierarchical blocks for graph (many
non-implemented modules)
__init__.py
Prefs.py
scheduler.py Schedule the threads
gru:
__init__.py
gruimpl:
crc.py CRC generator
Freqz.py Compute frequency response of a digital filter
given the numerator (b) and denominator (a)
gnuplot_freqz.py Plot the frequency response by using gnuplot
hexint.py Convert unsigned masks into signed ints
__init__.py
listmisc.py Return a copy of input ‘x’ that is reverse order
lmx2306.py Control National IMX2306 (specific hardware)
based frequency synthesizer
mathmisc.py Some math functions (Gcd, Lcm, Log2)
os_read_exactly.py Replace os.read that blocks until it reads exactly
nbytes.
sdr__1000.py Control the DDS(direct digital synthesizer) on the
SDR-1000 (specific hardware)
seq_with_cursor.py
socket_stuff.py Set up socket for TCP/UDP connections
pager:
aypabtu.py Mostly same as usrp_flex.py
flex_demod.py FLEX pager protocol demodulation block
__init__.py
pager_swig.py Automatically created by SWIG
Usrp_flex.py This is an example to demonstrates receiving and
demodulating the FLEX pager protocol
vocoder:
gsm_full_rate.py Automatically created by SWIG
__init__.py Not implemented yet
wxgui:
ftsink.py FFT sink test application
form.py wxgui form demo (Editbox, Int/Float check)
__init__.py
plot.py Demonstrate the drawing function
powermate.py Handler for Griffin PowerMate, Contour
ShuttlePro & ShuttleXpress USB knobs
ra_fftsink.py FFT sink test application
ra_stripchartsink.py
ra_waterfallsink.py
scopesink.py O’Scope Test Application
slider.py Demonstrate how to control slider
stdgui.py A simple wx gui for GNU Radio application
waterfallsink.py Waterfall sink test application
atsc.py: Automatically created by SWIG
audio.py: Generic audio or soundcard interface
audio_alsa.py: Automatically created by SWIG
audio_oss.py: Automatically created by SWIG
db_base.py: Abstract base class for all daughterboards. This defines
the required operations and interfaces for all d'boards.
db_ = daughterboard
db_basic.py: Handler for basic Tx daughterboards, Basic Rx
daughterboards, Low Freq Rx daughterboards, Low Freq Tx
daughterboards.
db_dbs_rx.py: Control DBS receiver based USRP daughterboard.
db_flexrf: Functions for all flexrf boards.
db_flexrf_mimo.py: Mimo classes for all flexrf boards.
db_instantiator.py: Instantiate for accessing daughterboard
db_tv_rx.py: Control Microtune 4937 based USRP daughterboard
ecc.py: Automatically created by SWIG
eng_notation.py: Change engineering notation (E.g., 5e-9 -> 5n)
eng_option.py: Add support for engineering notation
flexrf_debug_gui.py: Debug GUI for ‘Flexrf’
gr_unittest.py: Add support for unittest
__init__.py:
local_calibrator.py: NO LONGER USED
modulation_utils.py: Miscellaneous utilities for managing modulations
and demodulations
optfir.py: Routines for designing optimal FIR filters
packet_utils.py: Utilities for packet handling
ra.py: Automatically created by SWIG
trellis.py: Automatically created by SWIG
tx_debug_gui.py: Debug tool for ‘Tx’
usrp.py: Basic configuration for USRP
usrpl.py: Automatically created by SWIG
usrp_multi.py: Multiple-source handling for USRP
video_sdl.py: Automatically created by SWIG
window.py: Routines for designing window functions
__init__.py:
usrp_dbid.py: Defines USRP daughterboard ID
usrp_fpga_regs.py: Copy everything that starts with FR_ or bmFR_ from
the usrp_prims name space into our name space
usrp_prims.py: Automatically created by SWIG
top related