ECE 598HH: Special Topics in Wireless Networks and Mobile Systems Lecture 17: Software Defined Radio Tutorial Haitham Hassanieh
Software Defined Radios Idea: Flexibility, Portability, Multifunction Programmable Radio Frontend: Change Center Frequency, Bandwidth, Sampling Rate, Gain,. Baseband Processing in Software: Implement baseband functions on host in software (C++, Python, ) Implement some function on FPGA.
Many Open Source SDR Platforms USRP: Universal Software Radio Peripheral (Ettus) SORA: SOftware-defined Radio (Microsoft) Warp: Wireless Open Access Research Platform (Rice) RTL-SDR
GNU-Radio USRP Platform USRP: Universal Software Radio Peripheral (Ettus)
What is GNU Radio? Basic Concepts Software Radio Developing Applications UHD 2
What is GNU Radio? What is GNU Radio? Basic Concepts Basic Concepts Developing Applications Developing Applications UHD UHD 3 3
BASEBAND PROCESSING DIGITAL & RF FRONTEND ANTENNA BASEBAND PROCESSING DIGITAL & RF FRONTEND ANTENNA
What is GNU Radio? Software toolkit for signal processing What is GNU Radio? Providing a fast, low-cost way to test algorithms and waveform Software toolkit design for signal processing Providing a fast, low-cost way to test algorithms and waveform design USRP (Universal Software Radio Peripheral) USRP (Universal Software Radio Peripheral) Hardware TX/RX frontend Hardware TX/RX frontend
GNU Radio Components Host Computer GNU Radio Components Hardware Frontend GNU Radio Software Host Computer GNU Radio Software ADC/DAC and Digital Frontend Hardware Frontend ADC/DAC and Digital (USRP) Frontend (USRP) RF Frontend (Daughterboard) RF Frontend (Daughterboard)
USRP1 Features: Frequency Range: DC-6 GHz Connectivity for Two, Complete Tx/Rx chains Two Dual 64 MS/s 12-bit ADCs Two Dual 128 MS/s, 14-bit DACs Up to 16 MS/s USB Streaming Altera Cyclone FPGA
USRP2/N200/N210 Features: Frequency Range: DC-6 GHz 100 MS/s 14-bit ADC 400 MS/s, 16-bit DAC Up to 25 MS/s through Gigabit Ethernet Streaming (50 MS/s at 8 bits per sample) Xilinx Spartan XC3SD3400A FPGA: 2368K Memory, 53K logic cells MIMO Extension/ External Clock Synchronization
USRP X300/310 Features: Frequency Range: DC-6 GHz Two 200 MS/s 14-bit ADC Two 800 MS/s, 16-bit DAC Up to 200 MS/s through 10 Gigabit Ethernet or PCI Express Xilinx Kintex-7 FPGA: 28620K memory, 406K logic cells MIMO Extension External Clock Synchronization
USRP Daughter Boards Define Bandwidth, Frequency Range, Gain SBX: 400MHz-4.4GHz (40MHz/120MHz) WBX: 40MHz-2.2GHz (40MHz/120MHz) CBX: 1.2GHz-6GHz (40MHz/120MHz) UBX: 10MHz-6GHz (40MHz/160MHz) Basic TX/RX 1MHz-250MHz LFTX/LFRX 0MHz-30MHz
GNU Radio Software Open source (GPL) GNU Radio Software Existing examples: 802.11b, Zigbee, OFDM, DBPSK, Open source (GPL) DQPSK Existing examples: 802.11b, Zigbee, OFDM, DBPSK, DQPSK Extensive library of signal processing blocks (C++) Extensive library of signal processing blocks (C++) Modular design (flow graph) Modular design (flow graph) GNU Radio + UHD GNU Radio + UHD
What is GNU Radio? What is GNU Radio? Basic Concepts Basic Concepts Developing Applications Developing Applications UHD UHD 11 11
Blocks Signal Processing Block Blocks Accepts input streams Signal Processing Block Produces output streams Source: No input Accepts input streams Produces output streams Source: No input noise_source, signal_source, usrp_source noise_source, signal_source, usrp_source Sink: No outputs Sink: No outputs audio_alsa_sink, usrp_sink audio_alsa_sink, usrp_sink
Data Types Blocks operate on certain data types Data Types float, complex, int, char Vectors IO Signature: Blocks operate on certain data types 1 or 2 streams float, complex, int, char of float Vectors IO Signature: Number of input ports Number of input ports Number of output ports Number of output ports Item size of each port Item size of each port 1 or 2 streams of float 1 stream of complex 1 stream of complex
Flow Graph Blocks composed as a flow graph Data Flow stream Graph flowing from sources to sinks Blocks composed as a flow graph Signal Data Source stream flowing from sources to sinks Sample Rate: 32k Waveform: Signal Sine Source Sample Rate: 32k Frequency: Waveform: 350Hz Sine Frequency: 350Hz Amplitude: 0.1 Amplitude: 0.1 Audio Audio Sink Sink Signal Source Sample Rate: 32k Signal Source Sample Rate: 32k Sample Rate: 32k Sample Rate: Waveform: 32k Sine Frequency: 440Hz Waveform: Sine Amplitude: 0.1 Frequency: 440Hz Amplitude: 0.1
Example Code Example Code
QPSK Demodulator Example QPSK Demodulator Example
What is GNU Radio? What is GNU Radio? Basic Concepts Basic Concepts Developing Applications Developing Applications UHD UHD 18 18
Development Architecture Python C++ Development Architecture Flow graph construction Python Flow graph construction C++ Signal processing blocks Signal processing blocks Python Flow graph construction C++ Python Flow graph construction C++ Signal processing blocks Signal processing blocks
Python Example Python Example Signal Source Sample Rate: option Waveform: Sine Signal Source Sample Rate: option Waveform: Sine Frequency: 350Hz Amplitude: 0.1 Frequency: 350Hz Amplitude: 0.1 Signal Source Sample Rate: option Waveform: Sine Frequency: 440Hz Amplitude: 0.1 Signal Source Sample Rate: option Waveform: Sine Frequency: 440Hz Amplitude: 0.1 Audio Sink Sample Rate: option Audio Sink Sample Rate: option
#!/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_top_block(gr.top_block): def init (self): #!/usr/bin/env python gr.top_block. init (self) from gnuradio import gr from gnuradio import audio from gnuradio.eng_option import eng_option from optparse import OptionParser parser = OptionParser(option_class=eng_option) parser.add_option("-o", "--audio-output", type="string", default="", class my_top_block(gr.top_block): help="pcm output device name. E.g., hw:0,0") def init (self): parser.add_option("-r", gr.top_block. init (self) "--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 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") 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 sample_rate = int(options.sample_rate) ampl = 0.1 src0 = gr.sig_source_f src0 = gr.sig_source_f (sample_rate, gr.gr_sin_wave, 350, ampl) 350, ampl) src1 = gr.sig_source_f (sample_rate, gr.gr_sin_wave, 440, ampl) src1 = gr.sig_source_f dst = audio.sink (sample_rate, options.audio_output) gr.gr_sin_wave, 440, ampl) dst = audio.sink self.connect (sample_rate, (src0, (dst, 0)) options.audio_output) self.connect (src1, (dst, 1)) self.connect (src0, (dst, 0)) self.connect (src1, (dst, 1)) if name == ' main ': try: my_top_block().run() except KeyboardInterrupt: pass if name == ' main ': try: my_top_block().run() except KeyboardInterrupt: pass
from gnuradio import gr from gnuradio import audio from gnuradio.eng_option import eng_option from optparse import OptionParser Import modules from GNU Radio library from gnuradio import gr from gnuradio import audio from gnuradio.eng_option import eng_option from optparse import OptionParser Import modules from GNU Radio library
class my_top_block(gr.top_block): def init (self): gr.top_block. init (self) Define container for Flow Graph gr.top_block class maintains the graph class my_top_block(gr.top_block): def init (self): gr.top_block. init (self) Define container for Flow Graph gr.top_block class maintains the graph
Define and parse command-line options parser = OptionParser(option_class=eng_option) Define and parse command-line options parser.add_option("-o", "--audio-output", type="string", default="", help="pcm output device name. E.g., hw:0,0") 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") help="set sample rate to RATE (48000)") 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 parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, (options, args) = parser.parse_args () if len(args)!= 0: parser.print_help() raise SystemExit, 1
sample_rate = int(options.sample_rate) Create and connect signal processing blocks ampl = 0.1 sample_rate = int(options.sample_rate) ampl = 0.1 Create and connect signal processing blocks src0 = gr.sig_source_f src0 = (sample_rate, gr.gr_sin_wave, 350, ampl) 350, ampl) src1 = gr.sig_source_f (sample_rate, gr.gr_sin_wave, 440, ampl) src1 = gr.sig_source_f dst = audio.sink (sample_rate, options.audio_output) gr.gr_sin_wave, 440, ampl) dst = audio.sink self.connect (sample_rate, (src0, (dst, 0)) options.audio_output) self.connect (src1, (dst, 1)) self.connect (src0, (dst, 0)) self.connect (src1, (dst, 1))
if name == ' main ': try: my_top_block().run() except KeyboardInterrupt: pass if name == ' main ': try: my_top_block().run() except KeyboardInterrupt: pass Run the flow graph when the program is executed Run the flow graph when the program is executed
Creating Your Own Block Basics Creating Your Own Block A block is a C++ class Typically derived from gr_block class Basics A block is a C++ class Three components Typically derived from gr_block class my_block_xx.h: Three components Block definition my_block_xx.h: definition my_block_xx.cc: Block implementation my_block_xx.cc: Block implementation my_block_xx.i: Python bindings (SWIG (SWIG interface) interface)
Block Definition #include <gr_sync_block.h> class my_block_cc; Block Definition typedef boost::shared_ptr<6829_my_block_cc> 6829_my_block_cc_sptr; #include <gr_sync_block.h> class my_block_cc; 6829_my_block_cc_sptr 6829_make_my_block_cc(); typedef boost::shared_ptr<6829_my_block_cc> 6829_my_block_cc_sptr; class my_block_cc : public gr_sync_block { private: unsigned int d_count; 6829_my_block_cc_sptr 6829_make_my_block_cc(); class my_block_cc : public gr_sync_block { private: unsigned int d_count; friend 6829_my_block_cc_sptr friend 6829_make_my_block_cc(); 6829_my_block_cc(); public: 6829_my_block_cc(); public: int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); int work(int noutput_items, }; }; gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); Create instances of block Create instances of block Method for processing input streams and producing output streams Method for processing input streams and producing output streams
Block Implementation #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <my_block_cc.h> #include <gr_io_signature.h> Block Implementation #ifdef HAVE_CONFIG_H #include "config.h" #endif 6829_my_block_cc_sptr #include <my_block_cc.h> 6829_make_my_block_cc() #include <gr_io_signature.h> { return 6829_my_block_cc_sptr(new 6829_my_block_cc()); } 6829_my_block_cc_sptr 6829_make_my_block_cc() { return 6829_my_block_cc_sptr(new 6829_my_block_cc()); } 6829_hw_sample_block_cc::6829_hw_sample_block_cc() : gr_sync_block("my_block_cc", : gr_make_io_signature(1, 1, sizeof(gr_complex)), gr_make_io_signature(1, 1, 1, sizeof(gr_complex))), sizeof(gr_complex)), d_count(0) gr_make_io_signature(1, 1, sizeof(gr_complex))), { d_count(0) Define input and } output signatures { } Define input and output signatures
Block Implementation int 6829_my_block_cc::work(int noutput_items, gr_vector_const_void_star &input_items, Block Implementation gr_vector_void_star &output_items) { const gr_complex* in = (const gr_complex*)input_items[0]; gr_complex* out = (gr_complex*)output_items[0]; int 6829_my_block_cc::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { const gr_complex* in = (const gr_complex*)input_items[0]; gr_complex* out = (gr_complex*)output_items[0]; memcpy(out, in, sizeof(*out) * noutput_items); return noutput_items; } Copy input stream to output stream for (int i = 0; memcpy(out, i < noutput_items; in, sizeof(*out) * noutput_items); ++i) fprintf(stderr, for (int i = 0; i "%u\t<%.6f, < noutput_items; %.6f>\n", ++i) d_count++, fprintf(stderr, in[i].real(), "%u\t<%.6f, %.6f>\n", in[i].imag()); Echo samples d_count++, in[i].real(), in[i].imag()); stderr return noutput_items; } Return number of items processed of items processed Copy input stream to output stream Echo samples stderr
What is GNU Radio? What is GNU Radio? Basic Concepts Basic Concepts Developing Applications Developing Applications UHD UHD 32 32
UHD (USRP Hardware Driver) Why UHD? UHD (USRP Hardware Driver) Why UHD? Having N drivers isn t going to scale Having N drivers isn t going to scale
UHD (USRP Hardware Driver) Single API for all USRP devices C++ based UHD (USRP API Hardware Driver) All daughterboards Single API for all USRP devices C++ based API Inherent multi-channel support All daughterboards Inherent multi-channel support - Synchronization - Synchronization - Channel alignment - Channel alignment Gnuradio UHD Blocks Source Block, Sink Block Python, C++ Source Block, Sink Block Python, C++
UHD (USRP Hardware Driver) USRP Hardware UHD (USRP Hardware Driver) USRP Hardware Send/Recv Samples Send/Recv Samples Set/Get Properties Set/Get Properties Send/receive samples Send/receive samples device->send(...) and device->recv(...) Set/get properties Set/get properties C++ API Multi-USRP C++ API Multi-USRP
Device Properties Set/get gain Device Properties Set center frequency Set/get gain Set/get device time Set center frequency Set/get sample rate Set/get device time Set/get sample rate Antenna selection Antenna selection Frontend selection Frontend selection
Example: MIMO TX sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" Example: MIMO TX --file_prefix="tx" --rate=1000000 sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" --file_prefix="tx" --freq=922000000 --rate=1000000 --ant="tx/rx" --gain=10 --freq=922000000 --ant="tx/rx" --gain=10 --ref="external" --ref="external" --num_transmits=10 --num_transmits=10 --scale=0.5 --scale=0.5
Example: MIMO TX sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" Example: MIMO TX sudo./tx_samples_multi_from_file_repeat tx_samples_multi_from_file_repeat.cpp --args="addr0=192.168.10.2,addr1=192.168.20.2" uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); tx_samples_multi_from_file_repeat.cpp uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
Example: MIMO TX sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" Example: MIMO TX --file_prefix="tx" --rate=1000000 sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" --file_prefix="tx" --freq=922000000 --rate=1000000 --ant="tx/rx" --gain=10 --freq=922000000 --ant="tx/rx" --gain=10 tx_samples_multi_from_file_repeat.cpp tx_samples_multi_from_file_repeat.cpp usrp->set_tx_rate(rate, i); usrp->set_tx_rate(rate, usrp->set_tx_freq(freq, i); usrp->set_tx_antenna(ant, i); usrp->set_tx_freq(freq, i); usrp->set_tx_gain(gain, i); usrp->set_tx_antenna(ant, i); usrp->set_tx_gain(gain, i);
Example: MIMO TX sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" Example: MIMO TX --file_prefix="tx" --rate=1000000 sudo./tx_samples_multi_from_file_repeat --args="addr0=192.168.10.2,addr1=192.168.20.2" --file_prefix="tx" --freq=922000000 --rate=1000000 --ant="tx/rx" --gain=10 --freq=922000000 --ant="tx/rx" --gain=10 --ref="external" --ref="external" tx_samples_multi_from_file_repeat.cpp tx_samples_multi_from_file_repeat.cpp usrp->set_clock_config(uhd::clock_config_t::external()); usrp->set_clock_config(uhd::clock_config_t::external());
USRP http://www.ettus.com/resource GNU Radio http://gnuradio.org/redmine/projects/gnuradio/wiki USRP http://www.ettus.com/resource Available Signal Processing Blocks GNU Radio http://gnuradio.org/redmine/projects/gnuradio/wiki http://gnuradio.org/doc/doxygen/hierarchy.html Available Signal Processing Blocks GNU Radio Mailing List Archives http://gnuradio.org/doc/doxygen/hierarchy.html http://www.gnu.org/software/gnuradio/mailinglists.html GNU Radio Mailing List Archives http://www.gnu.org/software/gnuradio/mailinglists.html USRP Mailing List USRP Mailing List http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/ http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/ UHD UHD http://ettus-apps.sourcerepo.com/redmine/ettus/projects/uhd/wiki http://ettus-apps.sourcerepo.com/redmine/ettus/projects/uhd/wiki