diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | README | 150 | ||||
-rw-r--r-- | README.md | 23 | ||||
-rw-r--r-- | gr-dtv/include/gnuradio/dtv/CMakeLists.txt | 9 | ||||
-rw-r--r-- | gr-fec/lib/async_decoder_impl.cc | 2 | ||||
-rw-r--r-- | gr-uhd/apps/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-uhd/apps/uhd_app.py | 292 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_siggen | 34 | ||||
-rw-r--r-- | gr-uhd/apps/uhd_siggen_base.py | 351 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_siggen_gui | 689 | ||||
-rw-r--r-- | gr-uhd/examples/grc/uhd_siggen_gui.grc | 2154 |
11 files changed, 3137 insertions, 571 deletions
diff --git a/.gitignore b/.gitignore index 5140c03b1c..a18599872b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,3 @@ *.pyc *.pyo build/ -.idea/ -*.npy -*.lprof @@ -1,23 +1,139 @@ -ESA Summer of Code in Space 2015 POLAR Code implementation for GNU Radio -================ +# +# Copyright 2001-2007,2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# -This is a GNU Radio clone which contains all the files for my POLAR code project for ESA Summer of Code in Space 2015. My name is Johannes Demel and I am a Master degree student at *Karlsruhe Institute of Technology (KIT)*. +Welcome to GNU Radio! -Basics ----------- -The project is based on Erdal Arikan's 2009 paper *Channel Polarization: A Method for Constructing Capacity-Achieving Codes for Symmetric Binary-Input Memoryless Channels*. An in-depth explanation of my project is given in my project proposal <https://github.com/jdemel/socis-proposal>. -Structure ----------- -The aim of the project is to add POLAR code encoder, decoder, channel construction capabilities to GNU Radio. POLAR codes are used for channel coding, thus all files shall reside within the *gr-fec* submodule. Also encoder and decoder shall use the FECAPI. The decision to do all development in-tree is driven by previous experience that out-of-tree modules are often terribly hard to merge later on and it may take years to do so. +Please see http://gnuradio.org for the wiki, bug tracking, +and source code viewer. -Project -------- -A quick overview of my project timeline goes as follows. +If you've got questions about GNU Radio, please subscribe to the +discuss-gnuradio mailing list and post your questions there. +http://gnuradio.org/redmine/projects/gnuradio/wiki/MailingLists -1. create Python testcode -2. implement encoder and decoder in C++ for FECAPI. -3. optimize blocks and create VOLK kernels. -4. implement channel construction algorithms. +There is also a "Build Guide" in the wiki that contains OS specific +recommendations: +http://gnuradio.org/redmine/projects/gnuradio/wiki/BuildGuide + + +The bleeding edge code can be found in our git repository at +http://gnuradio.org/git/gnuradio.git/. To checkout the latest, use +this command: + + $ git clone git://git.gnuradio.org/gnuradio + +For information about using Git, please see: +http://gnuradio.org/redmine/projects/gnuradio/wiki/DevelopingWithGit + + +How to Build GNU Radio: + +For more complete instructions, see the "Building GNU Radio" page in +the GNU Radio manual (can be built or found online at +http://gnuradio.org/doc/doxygen/build_guide.html). + +See these steps for a quick build guide. + + (1) Ensure that you've satisfied the external dependencies. These + dependencies are listed in the manual's build page and are not + presented here to reduce duplication errors. + + See the wiki at http://gnuradio.org for details. + + + (2) Building from cmake: + + $ mkdir $(builddir) + $ cd $(builddir) + $ cmake [OPTIONS] $(srcdir) + $ make + $ make test + $ sudo make install + + +That's it! + +Options: +Useful options include setting the install prefix and the build type: + + -DCMAKE_INSTALL_PREFIX=<directory to install to> + -DCMAKE_BUILD_TYPE="<type>" + +Currently, GNU Radio has a "Debug" type that builds with '-g -O2' +useful for debugging the software and a "Release" type that builds +with '-O3', which is the default. + + +------------------------------------------------------------------------------- + + KNOWN INCOMPATIBILITIES + + + GNU Radio triggers bugs in g++ 3.3 for X86. DO NOT USE GCC 3.3 on + the X86 platform. g++ 3.2, 3.4, and the 4.* series are known to work well. + +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- + + NOTES + +------------------------------------------------------------------------------- + +To run the examples you may need to set PYTHONPATH. Note that the +prefix and python version number in the path needs to match your +installed version of python. + + $ export PYTHONPATH=/usr/local/lib/python2.7/dist-packages + +You may want to add this to your shell init file (~/.bash_profile if +you use bash). + + +Another handy trick if for example your fftw includes and libs are +installed in, say ~/local/include and ~/local/lib, instead of +/usr/local is this: + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/local/lib + $ make CPPFLAGS="-I$HOME/local/include" + + +Sometimes the prerequisites are installed in a location which is not +included in the default compiler and linker search paths. This +happens with pkgsrc and NetBSD. To build, tell configure to use these +locations: + + LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" CPPFLAGS="-I/usr/pkg/include" ./configure --prefix=/usr/gnuradio + + +------------------------------------------------------------------------------- + + Legal Matters + +------------------------------------------------------------------------------- + +Some files have been changed many times throughout the +years. Copyright notices at the tops of these files list which years +changes have been made. For some files, changes have occurred in many +consecutive years. These files may often have the format of a year +range (e.g., "2006 - 2011"), which indicates that these files have had +copyrightable changes made during each year in the range, inclusive. -This may get continuously updated and I will add more details during project development.
\ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 8d6fc4b760..0000000000 --- a/README.md +++ /dev/null @@ -1,23 +0,0 @@ -ESA Summer of Code in Space 2015 POLAR Code implementation for GNU Radio -================ - -This is a GNU Radio clone which contains all the files for my POLAR code project for ESA Summer of Code in Space 2015. My name is Johannes Demel and I am a Master degree student at *Karlsruhe Institute of Technology (KIT)*. - -Basics ----------- -The project is based on Erdal Arikan's 2009 paper *Channel Polarization: A Method for Constructing Capacity-Achieving Codes for Symmetric Binary-Input Memoryless Channels*. An in-depth explanation of my project is given in my project proposal <https://github.com/jdemel/socis-proposal>. - -Structure ----------- -The aim of the project is to add POLAR code encoder, decoder, channel construction capabilities to GNU Radio. POLAR codes are used for channel coding, thus all files shall reside within the *gr-fec* submodule. Also encoder and decoder shall use the FECAPI. The decision to do all development in-tree is driven by previous experience that out-of-tree modules are often terribly hard to merge later on and it may take years to do so. - -Project -------- -A quick overview of my project timeline goes as follows. - -1. create Python testcode -2. implement encoder and decoder in C++ for FECAPI. -3. optimize blocks and create VOLK kernels. -4. implement channel construction algorithms. - -This may get continuously updated and I will add more details during project development.
\ No newline at end of file diff --git a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt index d1eff3f891..4232ff7065 100644 --- a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt +++ b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt @@ -66,6 +66,15 @@ install(FILES dvbt_symbol_inner_interleaver.h dvbt_map.h dvbt_reference_signals.h + dvbt_ofdm_sym_acquisition.h + dvbt_demod_reference_signals.h + dvbt_demap.h + dvbt_bit_inner_deinterleaver.h + dvbt_viterbi_decoder.h + dvbt_convolutional_deinterleaver.h + dvbt_reed_solomon_dec.h + dvbt_energy_descramble.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/dtv COMPONENT "dtv_devel" ) diff --git a/gr-fec/lib/async_decoder_impl.cc b/gr-fec/lib/async_decoder_impl.cc index 33aaacb2f4..8d20a43142 100644 --- a/gr-fec/lib/async_decoder_impl.cc +++ b/gr-fec/lib/async_decoder_impl.cc @@ -119,7 +119,7 @@ namespace gr { size_t nbits_in = pmt::length(bits); size_t nbits_out = 0; size_t nblocks = 1; - bool variable_frame_size = d_decoder->set_frame_size(nbits_out); + bool variable_frame_size = d_decoder->set_frame_size(nbits_in*d_decoder->rate()); // Check here if the frame size is larger than what we've // allocated for in the constructor. diff --git a/gr-uhd/apps/CMakeLists.txt b/gr-uhd/apps/CMakeLists.txt index 1d68c00ac7..ebcaf6e9f8 100644 --- a/gr-uhd/apps/CMakeLists.txt +++ b/gr-uhd/apps/CMakeLists.txt @@ -25,6 +25,7 @@ include(GrPython) GR_PYTHON_INSTALL( FILES uhd_siggen_base.py + uhd_app.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/uhd COMPONENT "uhd_python" ) diff --git a/gr-uhd/apps/uhd_app.py b/gr-uhd/apps/uhd_app.py new file mode 100644 index 0000000000..5af01adaaa --- /dev/null +++ b/gr-uhd/apps/uhd_app.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python +# +# Copyright 2015 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +""" +USRP Helper Module: Common tasks for uhd-based apps. +""" + +from __future__ import print_function +import sys +import time +import argparse +from gnuradio import eng_arg +from gnuradio import uhd +from gnuradio import gr +from gnuradio import gru + +COMMAND_DELAY = .2 # Seconds + +COMPACT_TPL = "{mb_id} ({mb_serial}), {db_subdev} ({subdev}, {ant}{db_serial})" +LONG_TPL = """{prefix} Motherboard: {mb_id} ({mb_serial}) +{prefix} Daughterboard: {db_subdev}{db_serial} +{prefix} Subdev: {subdev} +{prefix} Antenna: {ant} +""" + +class UHDApp(object): + def __init__(self, prefix=None, args=None): + self.prefix = prefix + self.args = args + self.verbose = args.verbose or 0 + if self.args.sync == 'auto' and len(self.args.channels) > 1: + self.args.sync = 'pps' + + def vprint(self, *args): + """ + Print 'string' with 'prefix' prepended if self.verbose is True + """ + if self.verbose: + print("[{prefix}]".format(prefix=self.prefix), *args) + + def get_usrp_info_string(self, + compact=False, + tx_or_rx='rx', + chan=0, + mboard=0, + ): + """ + Return a nice textual description of the USRP we're using. + """ + assert tx_or_rx == 'rx' or tx_or_rx == 'tx' + try: + info_pp = {} + if self.prefix is None: + info_pp['prefix'] = "" + else: + info_pp['prefix'] = "[{prefix}] ".format(prefix=self.prefix) + usrp_info = self.usrp.get_usrp_info(chan) + info_pp['mb_id'] = usrp_info['mboard_id'] + info_pp['mb_serial'] = usrp_info['mboard_serial'] + if info_pp['mb_serial'] == "": + info_pp['mb_serial'] = "no serial" + info_pp['db_subdev'] = usrp_info["{xx}_subdev_name".format(xx=tx_or_rx)] + info_pp['db_serial'] = ", " + usrp_info["{xx}_serial".format(xx=tx_or_rx)] + if info_pp['db_serial'] == "": + info_pp['db_serial'] = "no serial" + info_pp['subdev'] = self.usrp.get_subdev_spec(mboard) + info_pp['ant'] = self.usrp.get_antenna(chan) + if info_pp['mb_id'] in ("B200", "B210", "E310"): + # In this case, this is meaningless + info_pp['db_serial'] = "" + tpl = LONG_TPL + if compact: + tpl = COMPACT_TPL + return tpl.format(**info_pp) + except: + return "Can't establish USRP info." + + def normalize_antenna_sel(self, args): + """ + Make sure the --antenna option matches the --channels option. + """ + if args.antenna is None: + return None + antennas = [x.strip() for x in args.antenna.split(",")] + if len(antennas) != 1 and len(antennas) != len(args.channels): + raise ValueError("Invalid antenna setting for {n} channels: {a}".format( + n=len(self.channels), a=args.antenna, + )) + if len(antennas) == 1: + antennas = [antennas[0],] * len(args.channels) + return antennas + + def async_callback(self, msg): + """ + Call this when USRP async metadata needs printing. + """ + md = self.async_src.msg_to_async_metadata_t(msg) + print("[{prefix}] Channel: {chan} Time: {t} Event: {e}".format( + prefix=self.prefix, + chan=md.channel, + t=md.time_spec.get_real_secs(), + e=md.event_code, + )) + + def setup_usrp(self, ctor, args, cpu_format='fc32'): + """ + Instantiate a USRP object; takes care of all kinds of corner cases and settings. + Pop it and some args onto the class that calls this. + """ + self.channels = args.channels + self.cpu_format = cpu_format + # Create a UHD device object: + self.usrp = ctor( + device_addr=args.args, + stream_args=uhd.stream_args( + cpu_format, + args.otw_format, + args=args.stream_args, + channels=self.channels, + ) + ) + # Set the subdevice spec: + if args.spec: + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.set_subdev_spec(args.spec, mb_idx) + # Sampling rate: + self.usrp.set_samp_rate(args.samp_rate) + self.samp_rate = self.usrp.get_samp_rate() + self.vprint("Using sampling rate: {rate}".format(rate=self.samp_rate)) + # Set the antenna: + self.antenna = self.normalize_antenna_sel(args) + if self.antenna is not None: + for i, chan in enumerate(self.channels): + self.usrp.set_antenna(self.antenna[i], chan) + self.vprint("[{prefix}] Channel {chan}: Using antenna {ant}.".format( + prefix=self.prefix, chan=chan, ant=self.usrp.get_antenna(chan) + )) + self.antenna = self.usrp.get_antenna(self.channels[0]) + # Set receive daughterboard gain: + self.set_gain(args.gain) + # Set frequency (tune request takes lo_offset): + if hasattr(args, 'lo_offset') and args.lo_offset is not None: + treq = uhd.tune_request(args.freq, args.lo_offset) + else: + treq = uhd.tune_request(args.freq) + # Make sure tuning is synched: + if len(self.channels) > 1: + if args.sync == 'pps': + self.usrp.set_time_unknown_pps(uhd.time_spec()) + cmd_time = self.usrp.get_time_now() + uhd.time_spec(COMMAND_DELAY) + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.set_command_time(cmd_time, mb_idx) + for chan in self.channels: + self.tr = self.usrp.set_center_freq(treq, chan) + if self.tr == None: + sys.stderr.write('[{prefix}] [ERROR] Failed to set center frequency on channel {chan}\n'.format( + prefix=self.prefix, chan=chan + )) + exit(1) + if len(self.channels) > 1: + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.clear_command_time(mb_idx) + print("[{prefix}] Syncing channels...".format(prefix=self.prefix)) + time.sleep(COMMAND_DELAY) + self.freq = self.usrp.get_center_freq(self.channels[0]) + if args.show_async_msg: + self.async_msgq = gr.msg_queue(0) + self.async_src = uhd.amsg_source("", self.async_msgq) + self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback) + + def set_gain(self, gain): + """ + Safe gain-setter. Catches some special cases: + - If gain is None, set to mid-point in dB. + - If the USRP is multi-channel, set it on all channels. + """ + if gain is None: + if self.args.verbose: + self.vprint("Defaulting to mid-point gains:".format(prefix=self.prefix)) + for chan in self.channels: + self.usrp.set_normalized_gain(.5, chan) + if self.args.verbose: + self.vprint("Channel {chan} gain: {g} dB".format( + prefix=self.prefix, chan=chan, g=self.usrp.get_gain(chan) + )) + else: + self.vprint("Setting gain to {g} dB.".format(g=gain)) + for chan in self.channels: + self.usrp.set_gain(gain, chan) + self.gain = self.usrp.get_gain(self.channels[0]) + + def set_freq(self, freq, skip_sync=False): + """ + Safely tune all channels to freq. + """ + self.vprint("Tuning all channels to {freq} MHz.".format(freq=freq/1e6)) + # Set frequency (tune request takes lo_offset): + if hasattr(self.args, 'lo_offset') and self.args.lo_offset is not None: + treq = uhd.tune_request(self.args.freq, self.args.lo_offset) + else: + treq = uhd.tune_request(self.args.freq) + # Make sure tuning is synched: + if len(self.channels) > 1 and not skip_sync: + cmd_time = self.usrp.get_time_now() + uhd.time_spec(COMMAND_DELAY) + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.set_command_time(cmd_time, mb_idx) + for chan in self.channels: + self.tr = self.usrp.set_center_freq(treq, chan) + if self.tr == None: + sys.stderr.write('[{prefix}] [ERROR] Failed to set center frequency on channel {chan}\n'.format( + prefix=self.prefix, chan=chan + )) + exit(1) + if len(self.channels) > 1 and not skip_sync: + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.clear_command_time(mb_idx) + self.vprint("Syncing channels...".format(prefix=self.prefix)) + time.sleep(COMMAND_DELAY) + + @staticmethod + def setup_argparser( + parser=None, + description='USRP App', + allow_mimo=True, + tx_or_rx="", + skip_freq=False, + ): + """ + Create or amend an argument parser with typical USRP options. + """ + def cslist(string): + """ + For ArgParser: Turn a comma separated list into an actual list. + """ + try: + return [int(x.strip()) for x in string.split(",")] + except: + raise argparse.ArgumentTypeError("Not a comma-separated list: {string}".format(string=string)) + if parser is None: + parser = argparse.ArgumentParser( + description=description, + ) + tx_or_rx = tx_or_rx.strip() + " " + group = parser.add_argument_group('USRP Arguments') + group.add_argument("-a", "--args", default="", help="UHD device address args") + group.add_argument("--spec", help="Subdevice of UHD device where appropriate") + group.add_argument("-A", "--antenna", help="Select {xx}Antenna(s) where appropriate".format(xx=tx_or_rx)) + group.add_argument("-s", "--samp-rate", type=eng_arg.eng_float, default=1e6, + help="Sample rate") + group.add_argument("-g", "--gain", type=eng_arg.eng_float, default=None, + help="Gain (default is midpoint)") + group.add_argument("--gain-type", choices=('db', 'normalized'), default='db', + help="Gain Type (applies to -g)") + if not skip_freq: + group.add_argument("-f", "--freq", type=eng_arg.eng_float, default=None, required=True, + help="Set carrier frequency to FREQ", + metavar="FREQ") + group.add_argument("--lo-offset", type=eng_arg.eng_float, default=0.0, + help="Set daughterboard LO offset to OFFSET [default=hw default]") + if allow_mimo: + group.add_argument("-c", "--channels", default=[0,], type=cslist, + help="Select {xx} Channels".format(xx=tx_or_rx)) + group.add_argument("--otw-format", choices=['sc16', 'sc12', 'sc8'], default='sc16', + help="Choose over-the-wire data format") + group.add_argument("--stream-args", default="", help="Set additional stream arguments") + group.add_argument("-m", "--amplitude", type=eng_arg.eng_float, default=0.15, + help="Set output amplitude to AMPL (0.0-1.0)", metavar="AMPL") + group.add_argument("-v", "--verbose", action="count", help="Use verbose console output") + group.add_argument("--show-async-msg", action="store_true", + help="Show asynchronous message notifications from UHD") + group.add_argument("--sync", choices=('default', 'pps', 'auto'), + default='auto', help="Set to 'pps' to sync devices to PPS") + return parser + diff --git a/gr-uhd/apps/uhd_siggen b/gr-uhd/apps/uhd_siggen index 52fc24922f..6e5d46506f 100755 --- a/gr-uhd/apps/uhd_siggen +++ b/gr-uhd/apps/uhd_siggen @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. +# Copyright 2008,2009,2011,2012,2015 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,32 +20,10 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr -from gnuradio.uhd import uhd_siggen_base as uhd_siggen -import sys +try: + import uhd_siggen_base as uhd_siggen +except ImportError: + from gnuradio.uhd import uhd_siggen_base as uhd_siggen -def main(): - if gr.enable_realtime_scheduling() != gr.RT_OK: - print "Note: failed to enable realtime scheduling, continuing" - - # Grab command line options and create top block - try: - (options, args) = uhd_siggen.get_options() - tb = uhd_siggen.top_block(options, args) - - except RuntimeError, e: - print e - sys.exit(1) - - tb.start() - raw_input('Press Enter to quit: ') - tb.stop() - tb.wait() - -# Make sure to create the top block (tb) within a function: -# That code in main will allow tb to go out of scope on return, -# which will call the decontructor on usrp and stop transmit. -# Whats odd is that grc works fine with tb in the __main__, -# perhaps its because the try/except clauses around tb. if __name__ == "__main__": - main() + uhd_siggen.main() diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index 503f49b481..31415dac41 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # -# Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. +# Copyright 2008,2009,2011,2012,2015 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -19,6 +19,9 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # +""" +Provide a base flow graph for USRP signal generators. +""" DESC_KEY = 'desc' SAMP_RATE_KEY = 'samp_rate' @@ -36,44 +39,69 @@ FREQ_RANGE_KEY = 'freq_range' GAIN_RANGE_KEY = 'gain_range' TYPE_KEY = 'type' -def setter(ps, key, val): ps[key] = val +# FIXME figure out if this can be deleted +#def setter(ps, key, val): ps[key] = val -from gnuradio import gr, gru, uhd, eng_notation +import sys +import math +import argparse +try: + from uhd_app import UHDApp +except ImportError: + from gnuradio.uhd.uhd_app import UHDApp +from gnuradio import gr, gru, uhd, eng_notation, eng_arg from gnuradio import analog from gnuradio import blocks from gnuradio.gr.pubsub import pubsub from gnuradio.eng_option import eng_option from optparse import OptionParser -import sys -import math n2s = eng_notation.num_to_str -waveforms = { analog.GR_SIN_WAVE : "Complex Sinusoid", - analog.GR_CONST_WAVE : "Constant", - analog.GR_GAUSSIAN : "Gaussian Noise", - analog.GR_UNIFORM : "Uniform Noise", - "2tone" : "Two Tone", - "sweep" : "Sweep" } - -# -# GUI-unaware GNU Radio flowgraph. This may be used either with command -# line applications or GUI applications. -# -class top_block(gr.top_block, pubsub): - def __init__(self, options, args): +waveforms = { + analog.GR_CONST_WAVE : "Constant", + analog.GR_SIN_WAVE : "Complex Sinusoid", + analog.GR_GAUSSIAN : "Gaussian Noise", + analog.GR_UNIFORM : "Uniform Noise", + "2tone" : "Two Tone", + "sweep" : "Sweep", +} + +class USRPSiggen(gr.top_block, pubsub, UHDApp): + """ + GUI-unaware GNU Radio flowgraph. This may be used either with command + line applications or GUI applications. + """ + def __init__(self, args): gr.top_block.__init__(self) pubsub.__init__(self) - self._verbose = options.verbose - - #initialize values from options - self._setup_usrpx(options) - self[SAMP_RATE_KEY] = options.samp_rate - self[TX_FREQ_KEY] = options.tx_freq - self[AMPLITUDE_KEY] = options.amplitude - self[WAVEFORM_FREQ_KEY] = options.waveform_freq - self[WAVEFORM_OFFSET_KEY] = options.offset - self[WAVEFORM2_FREQ_KEY] = options.waveform2_freq + UHDApp.__init__(self, args=args, prefix="UHD-SIGGEN") + self.extra_sink = None + + # Initialize device: + self.setup_usrp( + ctor=uhd.usrp_sink, + args=args, + ) + print("[UHD-SIGGEN] UHD Signal Generator") + print("[UHD-SIGGEN] UHD Version: {ver}".format(ver=uhd.get_version_string())) + print("[UHD-SIGGEN] Using USRP configuration:") + print(self.get_usrp_info_string(tx_or_rx="tx")) + self.usrp_description = self.get_usrp_info_string(tx_or_rx="tx", compact=True) + + ### Set subscribers and publishers: + self.publish(SAMP_RATE_KEY, lambda: self.usrp.get_samp_rate()) + self.publish(DESC_KEY, lambda: self.usrp_description) + self.publish(FREQ_RANGE_KEY, lambda: self.usrp.get_freq_range(self.channels[0])) + self.publish(GAIN_RANGE_KEY, lambda: self.usrp.get_gain_range(self.channels[0])) + self.publish(GAIN_KEY, lambda: self.usrp.get_gain(self.channels[0])) + + self[SAMP_RATE_KEY] = args.samp_rate + self[TX_FREQ_KEY] = args.freq + self[AMPLITUDE_KEY] = args.amplitude + self[WAVEFORM_FREQ_KEY] = args.waveform_freq + self[WAVEFORM_OFFSET_KEY] = args.offset + self[WAVEFORM2_FREQ_KEY] = args.waveform2_freq self[DSP_FREQ_KEY] = 0 self[RF_FREQ_KEY] = 0 @@ -91,84 +119,15 @@ class top_block(gr.top_block, pubsub): AMPLITUDE_KEY, WAVEFORM_FREQ_KEY, WAVEFORM_OFFSET_KEY, WAVEFORM2_FREQ_KEY): self[key] = self[key] - self[TYPE_KEY] = options.type #set type last - - def _setup_usrpx(self, options): - self._u = uhd.usrp_sink(device_addr=options.args, stream_args=uhd.stream_args('fc32')) - self._u.set_samp_rate(options.samp_rate) - - # Set the subdevice spec - if(options.spec): - self._u.set_subdev_spec(options.spec, 0) - - # Set the gain on the usrp from options - if(options.gain): - self._u.set_gain(options.gain) - - # Set the antenna - if(options.antenna): - self._u.set_antenna(options.antenna, 0) + self[TYPE_KEY] = args.type #set type last - # Setup USRP Configuration value - try: - usrp_info = self._u.get_usrp_info() - mboard_id = usrp_info["mboard_id"] - mboard_serial = usrp_info["mboard_serial"] - if mboard_serial == "": - mboard_serial = "no serial" - dboard_subdev_name = usrp_info["tx_subdev_name"] - dboard_serial = usrp_info["tx_serial"] - if dboard_serial == "": - dboard_serial = "no serial" - subdev = self._u.get_subdev_spec() - antenna = self._u.get_antenna() - - desc_key_str = "Motherboard: %s [%s]\n" % (mboard_id, mboard_serial) - if "B200" in mboard_id or "B210" in mboard_id: - desc_key_str += "Daughterboard: %s\n" % dboard_subdev_name - else: - desc_key_str += "Daughterboard: %s [%s]\n" % (dboard_subdev_name, dboard_serial) - desc_key_str += "Subdev: %s\n" % subdev - desc_key_str += "Antenna: %s" % antenna - except: - desc_key_str = "USRP configuration output not implemented in this version" - - self.publish(DESC_KEY, lambda: desc_key_str) - self.publish(FREQ_RANGE_KEY, self._u.get_freq_range) - self.publish(GAIN_RANGE_KEY, self._u.get_gain_range) - self.publish(GAIN_KEY, self._u.get_gain) - - print "UHD Signal Generator" - print "Version: %s" % uhd.get_version_string() - print "\nUsing USRP configuration:" - print desc_key_str + "\n" - - # Direct asynchronous notifications to callback function - if options.show_async_msg: - self.async_msgq = gr.msg_queue(0) - self.async_src = uhd.amsg_source("", self.async_msgq) - self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback) - - def async_callback(self, msg): - md = self.async_src.msg_to_async_metadata_t(msg) - print "Channel: %i Time: %f Event: %i" % (md.channel, md.time_spec.get_real_secs(), md.event_code) - - def _set_tx_amplitude(self, ampl): + def set_samp_rate(self, sr): """ - Sets the transmit amplitude sent to the USRP - - Args: - ampl: the amplitude or None for automatic + When sampling rate is updated, also update the signal sources. """ - ampl_range = self[AMPL_RANGE_KEY] - if ampl is None: - ampl = (ampl_range[1] - ampl_range[0])*0.15 + ampl_range[0] - self[AMPLITUDE_KEY] = max(ampl_range[0], min(ampl, ampl_range[1])) - - def set_samp_rate(self, sr): - self._u.set_samp_rate(sr) - sr = self._u.get_samp_rate() - + self.vprint("Setting sampling rate to: {rate} Msps".format(rate=sr/1e6)) + self.usrp.set_samp_rate(sr) + sr = self.usrp.get_samp_rate() if self[TYPE_KEY] in (analog.GR_SIN_WAVE, analog.GR_CONST_WAVE): self._src.set_sampling_freq(self[SAMP_RATE_KEY]) elif self[TYPE_KEY] == "2tone": @@ -179,48 +138,9 @@ class top_block(gr.top_block, pubsub): self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) else: return True # Waveform not yet set - - if self._verbose: - print "Set sample rate to:", sr - + self.vprint("Set sample rate to: {rate} Msps".format(rate=sr/1e6)) return True - def set_gain(self, gain): - if gain is None: - g = self[GAIN_RANGE_KEY] - gain = float(g.start()+g.stop())/2 - if self._verbose: - print "Using auto-calculated mid-point TX gain" - self[GAIN_KEY] = gain - return - self._u.set_gain(gain) - if self._verbose: - print "Set TX gain to:", gain - - def set_freq(self, target_freq): - - if target_freq is None: - f = self[FREQ_RANGE_KEY] - target_freq = float(f.start()+f.stop())/2.0 - if self._verbose: - print "Using auto-calculated mid-point frequency" - self[TX_FREQ_KEY] = target_freq - return - - tr = self._u.set_center_freq(target_freq) - fs = "%sHz" % (n2s(target_freq),) - if tr is not None: - self._freq = target_freq - self[DSP_FREQ_KEY] = tr.actual_dsp_freq - self[RF_FREQ_KEY] = tr.actual_rf_freq - if self._verbose: - print "Set center frequency to", self._u.get_center_freq() - print "Tx RF frequency: %sHz" % (n2s(tr.actual_rf_freq),) - print "Tx DSP frequency: %sHz" % (n2s(tr.actual_dsp_freq),) - elif self._verbose: - print "Failed to set freq." - return tr - def set_waveform_freq(self, freq): if self[TYPE_KEY] == analog.GR_SIN_WAVE: self._src.set_frequency(freq) @@ -242,6 +162,7 @@ class top_block(gr.top_block, pubsub): return True def set_waveform(self, type): + self.vprint("Selecting waveform...") self.lock() self.disconnect_all() if type == analog.GR_SIN_WAVE or type == analog.GR_CONST_WAVE: @@ -258,9 +179,8 @@ class top_block(gr.top_block, pubsub): self[WAVEFORM_FREQ_KEY], self[AMPLITUDE_KEY]/2.0, 0) - if(self[WAVEFORM2_FREQ_KEY] is None): + if self[WAVEFORM2_FREQ_KEY] is None: self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY] - self._src2 = analog.sig_source_c(self[SAMP_RATE_KEY], analog.GR_SIN_WAVE, self[WAVEFORM2_FREQ_KEY], @@ -276,7 +196,6 @@ class top_block(gr.top_block, pubsub): # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2) if self[WAVEFORM2_FREQ_KEY] is None: self[WAVEFORM2_FREQ_KEY] = 0.1 - self._src1 = analog.sig_source_f(self[SAMP_RATE_KEY], analog.GR_TRI_WAVE, self[WAVEFORM2_FREQ_KEY], @@ -284,33 +203,33 @@ class top_block(gr.top_block, pubsub): -0.5) self._src2 = analog.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) self._src = blocks.multiply_const_cc(self[AMPLITUDE_KEY]) - self.connect(self._src1,self._src2,self._src) + self.connect(self._src1, self._src2, self._src) else: - raise RuntimeError("Unknown waveform type") - - self.connect(self._src, self._u) + raise RuntimeError("[UHD-SIGGEN] Unknown waveform type") + for c in xrange(len(self.channels)): + self.connect(self._src, (self.usrp, c)) + if self.extra_sink is not None: + self.connect(self._src, self.extra_sink) self.unlock() - - if self._verbose: - print "Set baseband modulation to:", waveforms[type] - if type == analog.GR_SIN_WAVE: - print "Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),) - print "Initial phase:", self[WAVEFORM_OFFSET_KEY] - elif type == "2tone": - print "Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),) - print "Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),) - elif type == "sweep": - print "Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0)) - print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),) - print "TX amplitude:", self[AMPLITUDE_KEY] - + self.vprint("Set baseband modulation to:", waveforms[type]) + if type == analog.GR_SIN_WAVE: + self.vprint("Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) + self.vprint("Initial phase:", self[WAVEFORM_OFFSET_KEY]) + elif type == "2tone": + self.vprint("Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) + self.vprint("Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) + elif type == "sweep": + self.vprint("Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0))) + self.vprint("Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) + self.vprint("TX amplitude:", self[AMPLITUDE_KEY]) def set_amplitude(self, amplitude): + """ + amplitude subscriber + """ if amplitude < 0.0 or amplitude > 1.0: - if self._verbose: - print "Amplitude out of range:", amplitude + self.vprint("Amplitude out of range:", amplitude) return False - if self[TYPE_KEY] in (analog.GR_SIN_WAVE, analog.GR_CONST_WAVE, analog.GR_GAUSSIAN, analog.GR_UNIFORM): self._src.set_amplitude(amplitude) elif self[TYPE_KEY] == "2tone": @@ -320,83 +239,55 @@ class top_block(gr.top_block, pubsub): self._src.set_k(amplitude) else: return True # Waveform not yet set - - if self._verbose: - print "Set amplitude to:", amplitude + self.vprint("Set amplitude to:", amplitude) return True -def get_options(): - usage="%prog: [options]" - parser = OptionParser(option_class=eng_option, usage=usage) - parser.add_option("-a", "--args", type="string", default="", - help="UHD device address args , [default=%default]") - parser.add_option("", "--spec", type="string", default=None, - help="Subdevice of UHD device where appropriate") - parser.add_option("-A", "--antenna", type="string", default=None, - help="select Rx Antenna where appropriate") - parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, - help="set sample rate (bandwidth) [default=%default]") - parser.add_option("-g", "--gain", type="eng_float", default=None, - help="set gain in dB (default is midpoint)") - parser.add_option("-f", "--tx-freq", type="eng_float", default=None, - help="Set carrier frequency to FREQ [default=mid-point]", - metavar="FREQ") - parser.add_option("-x", "--waveform-freq", type="eng_float", default=0, - help="Set baseband waveform frequency to FREQ [default=%default]") - parser.add_option("-y", "--waveform2-freq", type="eng_float", default=None, - help="Set 2nd waveform frequency to FREQ [default=%default]") - parser.add_option("--sine", dest="type", action="store_const", const=analog.GR_SIN_WAVE, +def setup_argparser(): + """ + Create argument parser for signal generator. + """ + parser = UHDApp.setup_argparser( + description="USRP Signal Generator.", + tx_or_rx="Tx", + ) + group = parser.add_argument_group('Siggen Arguments') + group.add_argument("-x", "--waveform-freq", type=eng_arg.eng_float, default=0.0, + help="Set baseband waveform frequency to FREQ") + group.add_argument("-y", "--waveform2-freq", type=eng_arg.eng_float, default=0.0, + help="Set 2nd waveform frequency to FREQ") + group.add_argument("--sine", dest="type", action="store_const", const=analog.GR_SIN_WAVE, help="Generate a carrier modulated by a complex sine wave", default=analog.GR_SIN_WAVE) - parser.add_option("--const", dest="type", action="store_const", const=analog.GR_CONST_WAVE, + group.add_argument("--const", dest="type", action="store_const", const=analog.GR_CONST_WAVE, help="Generate a constant carrier") - parser.add_option("--offset", type="eng_float", default=0, - help="Set waveform phase offset to OFFSET [default=%default]") - parser.add_option("--gaussian", dest="type", action="store_const", const=analog.GR_GAUSSIAN, + group.add_argument("--offset", type=eng_arg.eng_float, default=0, + help="Set waveform phase offset to OFFSET", metavar="OFFSET") + group.add_argument("--gaussian", dest="type", action="store_const", const=analog.GR_GAUSSIAN, help="Generate Gaussian random output") - parser.add_option("--uniform", dest="type", action="store_const", const=analog.GR_UNIFORM, + group.add_argument("--uniform", dest="type", action="store_const", const=analog.GR_UNIFORM, help="Generate Uniform random output") - parser.add_option("--2tone", dest="type", action="store_const", const="2tone", + group.add_argument("--2tone", dest="type", action="store_const", const="2tone", help="Generate Two Tone signal for IMD testing") - parser.add_option("--sweep", dest="type", action="store_const", const="sweep", + group.add_argument("--sweep", dest="type", action="store_const", const="sweep", help="Generate a swept sine wave") - parser.add_option("", "--amplitude", type="eng_float", default=0.15, - help="Set output amplitude to AMPL (0.0-1.0) [default=%default]", - metavar="AMPL") - parser.add_option("-v", "--verbose", action="store_true", default=False, - help="Use verbose console output [default=%default]") - parser.add_option("", "--show-async-msg", action="store_true", default=False, - help="Show asynchronous message notifications from UHD [default=%default]") - - (options, args) = parser.parse_args() - - return (options, args) + return parser -# If this script is executed, the following runs. If it is imported, -# the below does not run. -def test_main(): +def main(): if gr.enable_realtime_scheduling() != gr.RT_OK: - print "Note: failed to enable realtime scheduling, continuing" - - # Grab command line options and create top block + print("Note: failed to enable realtime scheduling, continuing") + # Grab command line args and create top block try: - (options, args) = get_options() - tb = top_block(options, args) - - except RuntimeError, e: - print e - sys.exit(1) - + parser = setup_argparser() + args = parser.parse_args() + tb = USRPSiggen(args) + except RuntimeError as e: + print(e) + exit(1) tb.start() - raw_input('Press Enter to quit: ') + raw_input('[UHD-SIGGEN] Press Enter to quit:\n') tb.stop() tb.wait() -# Make sure to create the top block (tb) within a function: -# That code in main will allow tb to go out of scope on return, -# which will call the decontructor on usrp and stop transmit. -# Whats odd is that grc works fine with tb in the __main__, -# perhaps its because the try/except clauses around tb. if __name__ == "__main__": - test_main() + main() diff --git a/gr-uhd/apps/uhd_siggen_gui b/gr-uhd/apps/uhd_siggen_gui index 80fcf8e673..ab04ccc8e2 100755 --- a/gr-uhd/apps/uhd_siggen_gui +++ b/gr-uhd/apps/uhd_siggen_gui @@ -1,6 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # -# Copyright 2009,2011,2012 Free Software Foundation, Inc. +# Copyright 2015 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -19,301 +19,452 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # +""" +Signal Generator App +""" -import wx -from gnuradio import gr, uhd +# Started off with this flow graph: +################################################## +# GNU Radio Python Flow Graph +# Title: UHD Signal Generator +# Author: Ettus Research +# Description: Signal Generator for use with USRP Devices +# Generated: Sun Jun 28 17:21:28 2015 +################################################## + +import sip +import sys +import threading +import time +from distutils.version import StrictVersion +from PyQt4 import Qt +from PyQt4.QtCore import QObject, pyqtSlot from gnuradio import analog -from gnuradio.gr.pubsub import pubsub -from gnuradio.wxgui import gui, forms -from gnuradio.uhd import uhd_siggen_base as uhd_siggen -import sys, math +from gnuradio import eng_notation +from gnuradio import gr +from gnuradio import qtgui +from gnuradio import uhd +from gnuradio.filter import firdes +from gnuradio.qtgui import Range, RangeWidget +try: + import uhd_siggen_base as uhd_siggen +except ImportError: + from gnuradio.uhd import uhd_siggen_base as uhd_siggen + -class app_gui(pubsub): - def __init__(self, frame, panel, vbox, top_block, options, args): - pubsub.__init__(self) - self.frame = frame # Use for top-level application window frame - self.panel = panel # Use as parent class for created windows - self.vbox = vbox # Use as sizer for created windows - self.tb = top_block # GUI-unaware flowgraph class - self.options = options # Supplied command-line options - self.args = args # Supplied command-line arguments - self.build_gui() +class uhd_siggen_gui(Qt.QWidget): + """ + Signal Generator Flowgraph + """ + def __init__(self, args): + ################################################## + # Set up the siggen app + ################################################## + self._sg = uhd_siggen.USRPSiggen(args) + self.usrp = self._sg.usrp - # Event response handlers - def evt_set_status_msg(self, msg): - self.frame.SetStatusText(msg, 0) + ################################################## + # GUI Setup + ################################################## + Qt.QWidget.__init__(self) + self.setWindowTitle("UHD Signal Generator") + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + self.settings = Qt.QSettings("GNU Radio", "uhd_siggen_gui") + self.restoreGeometry(self.settings.value("geometry").toByteArray()) - # GUI construction - def build_gui(self): - self.vbox.AddSpacer(5) - self.vbox.AddStretchSpacer() ################################################## - # Baseband controls + # Widgets + Controls ################################################## - bb_vbox = forms.static_box_sizer(parent=self.panel, label="Baseband Modulation", orient=wx.VERTICAL, bold=True) - self.vbox.Add(bb_vbox, 0, wx.EXPAND) - sine_bb_hbox = wx.BoxSizer(wx.HORIZONTAL) - sweep_bb_hbox = wx.BoxSizer(wx.HORIZONTAL) - tone_bb_hbox = wx.BoxSizer(wx.HORIZONTAL) - self.vbox.AddSpacer(10) - self.vbox.AddStretchSpacer() - #callback to show/hide forms - def set_type(type): - sine_bb_hbox.ShowItems(type == analog.GR_SIN_WAVE) - sweep_bb_hbox.ShowItems(type == 'sweep') - tone_bb_hbox.ShowItems(type == '2tone') - self.vbox.Layout() - self.tb.subscribe(uhd_siggen.TYPE_KEY, set_type) - #create sine forms - sine_bb_hbox.AddSpacer(10) - forms.text_box( - parent=self.panel, sizer=sine_bb_hbox, - label='Frequency (Hz)', - ps=self.tb, - key=uhd_siggen.WAVEFORM_FREQ_KEY, - converter=forms.float_converter(), + ### Waveform Selector + self._waveform_options = uhd_siggen.waveforms.keys() + self._waveform_labels = uhd_siggen.waveforms.values() + self._waveform_group_box = Qt.QGroupBox("Waveform") + self._waveform_box = Qt.QHBoxLayout() + class variable_chooser_button_group(Qt.QButtonGroup): + def __init__(self, parent=None): + Qt.QButtonGroup.__init__(self, parent) + @pyqtSlot(int) + def updateButtonChecked(self, button_id): + self.button(button_id).setChecked(True) + self._waveform_button_group = variable_chooser_button_group() + self._waveform_group_box.setLayout(self._waveform_box) + for i, label in enumerate(self._waveform_labels): + radio_button = Qt.QRadioButton(label) + self._waveform_box.addWidget(radio_button) + self._waveform_button_group.addButton(radio_button, i) + self._waveform_callback = lambda i: Qt.QMetaObject.invokeMethod( + self._waveform_button_group, + "updateButtonChecked", + Qt.Q_ARG("int", self._waveform_options.index(i)) ) - sine_bb_hbox.AddStretchSpacer() - #create sweep forms - sweep_bb_hbox.AddSpacer(10) - forms.text_box( - parent=self.panel, sizer=sweep_bb_hbox, - label='Sweep Width (Hz)', - ps=self.tb, - key=uhd_siggen.WAVEFORM_FREQ_KEY, - converter=forms.float_converter(), + self._waveform_callback(self._sg[uhd_siggen.TYPE_KEY]) + self._waveform_button_group.buttonClicked[int].connect( + lambda i: self.set_waveform(self._waveform_options[i]) ) - sweep_bb_hbox.AddStretchSpacer() - forms.text_box( - parent=self.panel, sizer=sweep_bb_hbox, - label='Sweep Rate (Hz)', - ps=self.tb, - key=uhd_siggen.WAVEFORM2_FREQ_KEY, - converter=forms.float_converter(), + self.top_grid_layout.addWidget(self._waveform_group_box, 0,0,1,5) + ### Center Frequency Sliders + self.freq_coarse = self._sg.usrp.get_center_freq(self._sg.channels[0]) + self._freq_coarse_range = Range( + self.usrp.get_freq_range(self._sg.channels[0]).start(), + self.usrp.get_freq_range(self._sg.channels[0]).stop(), + 1e3, # Step + self.freq_coarse, + 200, # Min Width ) - sweep_bb_hbox.AddStretchSpacer() - #create 2tone forms - tone_bb_hbox.AddSpacer(10) - forms.text_box( - parent=self.panel, sizer=tone_bb_hbox, - label='Tone 1 (Hz)', - ps=self.tb, - key=uhd_siggen.WAVEFORM_FREQ_KEY, - converter=forms.float_converter(), + self._freq_coarse_win = RangeWidget( + self._freq_coarse_range, + self.set_freq_coarse, + "Center Frequency", + "counter_slider", + float ) - tone_bb_hbox.AddStretchSpacer() - forms.text_box( - parent=self.panel, sizer=tone_bb_hbox, - label='Tone 2 (Hz)', - ps=self.tb, - key=uhd_siggen.WAVEFORM2_FREQ_KEY, - converter=forms.float_converter(), + self.top_grid_layout.addWidget(self._freq_coarse_win, 1,0,1,5) + self.freq_fine = 0.0 + self._freq_fine_range = Range( + -1e6, 1e6, 1e3, + self.freq_fine, + 200 ) - tone_bb_hbox.AddStretchSpacer() - forms.radio_buttons( - parent=self.panel, sizer=bb_vbox, - choices=uhd_siggen.waveforms.keys(), - labels=uhd_siggen.waveforms.values(), - ps=self.tb, - key=uhd_siggen.TYPE_KEY, - style=wx.NO_BORDER | wx.RA_HORIZONTAL, + self._freq_fine_win = RangeWidget( + self._freq_fine_range, + self.set_freq_fine, + "Fine Tuning", + "counter_slider", + float ) - bb_vbox.AddSpacer(10) - bb_vbox.Add(sine_bb_hbox, 0, wx.EXPAND) - bb_vbox.Add(sweep_bb_hbox, 0, wx.EXPAND) - bb_vbox.Add(tone_bb_hbox, 0, wx.EXPAND) - set_type(self.tb[uhd_siggen.TYPE_KEY]) - - ################################################## - # Frequency controls - ################################################## - fc_vbox = forms.static_box_sizer(parent=self.panel, - label="Center Frequency", - orient=wx.VERTICAL, - bold=True) - fc_vbox.AddSpacer(5) - # First row of frequency controls (center frequency) - freq_hbox = wx.BoxSizer(wx.HORIZONTAL) - fc_vbox.Add(freq_hbox, 0, wx.EXPAND) - fc_vbox.AddSpacer(10) - # Second row of frequency controls (results) - tr_hbox = wx.BoxSizer(wx.HORIZONTAL) - fc_vbox.Add(tr_hbox, 0, wx.EXPAND) - fc_vbox.AddSpacer(5) - # Add frequency controls to top window sizer - self.vbox.Add(fc_vbox, 0, wx.EXPAND) - self.vbox.AddSpacer(10) - self.vbox.AddStretchSpacer() - freq_hbox.AddSpacer(5) - forms.text_box( - parent=self.panel, sizer=freq_hbox, - proportion=1, - converter=forms.float_converter(), - ps=self.tb, - key=uhd_siggen.TX_FREQ_KEY, + self.top_grid_layout.addWidget(self._freq_fine_win, 2,0,1,5) + self.lo_offset = self._sg.args.lo_offset + self._lo_offset_range = Range( + -self._sg[uhd_siggen.SAMP_RATE_KEY]/2, + self._sg[uhd_siggen.SAMP_RATE_KEY]/2, + 1e3, + self.lo_offset, + 200 ) - freq_hbox.AddSpacer(10) - - forms.slider( - parent=self.panel, sizer=freq_hbox, - proportion=2, - ps=self.tb, - key=uhd_siggen.TX_FREQ_KEY, - minimum=self.tb[uhd_siggen.FREQ_RANGE_KEY].start(), - maximum=self.tb[uhd_siggen.FREQ_RANGE_KEY].stop(), - num_steps=100, + self._lo_offset_win = RangeWidget( + self._lo_offset_range, + self.set_lo_offset, + "LO Offset", + "counter_slider", + float ) - freq_hbox.AddSpacer(5) - tr_hbox.AddSpacer(5) - forms.static_text( - parent=self.panel, sizer=tr_hbox, - label='RF Frequency', - ps=self.tb, - key=uhd_siggen.RF_FREQ_KEY, - converter=forms.float_converter(), - proportion=1, + self.top_grid_layout.addWidget(self._lo_offset_win, 3,0,1,5) + ### Signal frequencies + self._freq1_enable_on = (analog.GR_SIN_WAVE, "2tone", "sweep") + self._freq1_offset_range = Range( + -self._sg[uhd_siggen.SAMP_RATE_KEY]/4, + self._sg[uhd_siggen.SAMP_RATE_KEY]/4, + 100, + self._sg.args.waveform_freq, + 200 ) - tr_hbox.AddSpacer(10) - forms.static_text( - parent=self.panel, sizer=tr_hbox, - label='DSP Frequency', - ps=self.tb, - key=uhd_siggen.DSP_FREQ_KEY, - converter=forms.float_converter(), - proportion=1, + self._freq1_offset_win = RangeWidget( + self._freq1_offset_range, + self.set_freq1_offset, + "Frequency Offset: Signal 1", + "counter_slider", + float ) - tr_hbox.AddSpacer(5) - - ################################################## - # Amplitude controls - ################################################## - amp_hbox = forms.static_box_sizer(parent=self.panel, - label="Amplitude", - orient=wx.VERTICAL, - bold=True) - amp_hbox.AddSpacer(5) - # First row of amp controls (ampl) - lvl_hbox = wx.BoxSizer(wx.HORIZONTAL) - amp_hbox.Add(lvl_hbox, 0, wx.EXPAND) - amp_hbox.AddSpacer(10) - # Second row of amp controls (tx gain) - gain_hbox = wx.BoxSizer(wx.HORIZONTAL) - amp_hbox.Add(gain_hbox, 0, wx.EXPAND) - amp_hbox.AddSpacer(5) - self.vbox.Add(amp_hbox, 0, wx.EXPAND) - self.vbox.AddSpacer(10) - self.vbox.AddStretchSpacer() - lvl_hbox.AddSpacer(5) - forms.text_box( - parent=self.panel, sizer=lvl_hbox, - proportion=1, - converter=forms.float_converter(), - ps=self.tb, - key=uhd_siggen.AMPLITUDE_KEY, - label="Level (0.0-1.0)", + self._freq1_offset_win.setEnabled(self._sg[uhd_siggen.TYPE_KEY] in self._freq1_enable_on) + self.top_grid_layout.addWidget(self._freq1_offset_win, 4,0,1,3) + self._freq2_enable_on = ("2tone", "sweep") + self._freq2_offset_range = Range( + -self._sg[uhd_siggen.SAMP_RATE_KEY]/4, + self._sg[uhd_siggen.SAMP_RATE_KEY]/4, + 100, + self._sg.args.waveform2_freq, + 200 ) - lvl_hbox.AddSpacer(10) - forms.log_slider( - parent=self.panel, sizer=lvl_hbox, - proportion=2, - ps=self.tb, - key=uhd_siggen.AMPLITUDE_KEY, - min_exp=-6, - max_exp=0, - base=10, - num_steps=100, + self._freq2_offset_win = RangeWidget( + self._freq2_offset_range, + self.set_freq2_offset, + "Signal 2 ", + "counter_slider", + float ) - lvl_hbox.AddSpacer(5) - if self.tb[uhd_siggen.GAIN_RANGE_KEY].start() < self.tb[uhd_siggen.GAIN_RANGE_KEY].stop(): - gain_hbox.AddSpacer(5) - forms.text_box( - parent=self.panel, sizer=gain_hbox, - proportion=1, - converter=forms.float_converter(), - ps=self.tb, - key=uhd_siggen.GAIN_KEY, - label="TX Gain (dB)", - ) - gain_hbox.AddSpacer(10) - forms.slider( - parent=self.panel, sizer=gain_hbox, - proportion=2, - ps=self.tb, - key=uhd_siggen.GAIN_KEY, - minimum=self.tb[uhd_siggen.GAIN_RANGE_KEY].start(), - maximum=self.tb[uhd_siggen.GAIN_RANGE_KEY].stop(), - step_size=self.tb[uhd_siggen.GAIN_RANGE_KEY].step(), + self._freq2_offset_win.setEnabled(self._sg[uhd_siggen.TYPE_KEY] in self._freq2_enable_on) + self.top_grid_layout.addWidget(self._freq2_offset_win, 4,3,1,2) + ### Amplitude + self._amplitude_range = Range(0, 1, .001, .7, 200) + self._amplitude_win = RangeWidget( + self._amplitude_range, + self.set_amplitude, + "Signal Amplitude", + "counter_slider", + float + ) + self.top_grid_layout.addWidget(self._amplitude_win, 5,0,1,5) + ### Gain + self._gain_range = Range( + self.usrp.get_gain_range(self._sg.channels[0]).start(), + self.usrp.get_gain_range(self._sg.channels[0]).stop(), + .5, + self.usrp.get_gain(self._sg.channels[0]), + 200., + ) + self._gain_win = RangeWidget( + self._gain_range, + self._sg.set_gain, + "TX Gain", "counter_slider", float + ) + self.top_grid_layout.addWidget(self._gain_win, 6,0,1,5) + ### Samp rate, LO sync, Antenna Select + self.samp_rate = self._sg[uhd_siggen.SAMP_RATE_KEY] + self._samp_rate_tool_bar = Qt.QToolBar(self) + self._samp_rate_tool_bar.addWidget(Qt.QLabel("Sampling Rate: ")) + self._samp_rate_line_edit = Qt.QLineEdit(eng_notation.num_to_str(self._sg[uhd_siggen.SAMP_RATE_KEY])) + self._samp_rate_tool_bar.addWidget(self._samp_rate_line_edit) + self._samp_rate_line_edit.returnPressed.connect( + lambda: self.set_samp_rate(eng_notation.str_to_num(str(self._samp_rate_line_edit.text().toAscii()))) + ) + self.top_grid_layout.addWidget(self._samp_rate_tool_bar, 7,0,1,2) + _sync_phases_push_button = Qt.QPushButton("Sync LOs") + _sync_phases_push_button.pressed.connect(lambda: self.set_sync_phases(True)) + _sync_phases_push_button.setEnabled(bool(len(self._sg.channels) > 1)) + self.top_grid_layout.addWidget(_sync_phases_push_button, 7,2,1,1) + # Antenna Select + self._ant_tool_bar = Qt.QToolBar(self) + self._ant_tool_bar.addWidget(Qt.QLabel("Antenna: ")) + self._ant_combo_box = Qt.QComboBox() + self._ant_tool_bar.addWidget(self._ant_combo_box) + self._ant_options = self.usrp.get_antennas(self._sg.channels[0]) + for label in self._ant_options: + self._ant_combo_box.addItem(label) + self._ant_callback = lambda i: Qt.QMetaObject.invokeMethod( + self._ant_combo_box, "setCurrentIndex", + Qt.Q_ARG("int", self._ant_options.index(i)) + ) + self._ant_callback(self.usrp.get_antenna(self._sg.channels[0])) + self._ant_combo_box.currentIndexChanged.connect(lambda i: self.set_ant(self._ant_options[i])) + self.top_grid_layout.addWidget(self._ant_tool_bar, 7,4,1,1) + # Labels + Lock Sensors + self._lo_locked_probe_0_tool_bar = Qt.QToolBar(self) + self._lo_locked_probe_0_formatter = lambda x: x + self._lo_locked_probe_0_tool_bar.addWidget(Qt.QLabel("LO locked: ")) + self._lo_locked_probe_0_label = Qt.QLabel(str(False)) + self._lo_locked_probe_0_tool_bar.addWidget(self._lo_locked_probe_0_label) + self.top_grid_layout.addWidget(self._lo_locked_probe_0_tool_bar, 8,0,1,1) + def _chan0_lo_locked_probe(): + while True: + val = all([self.usrp.get_sensor('lo_locked', c).to_bool() for c in range(len(self._sg.channels))]) + try: + self.set_chan0_lo_locked(val) + except AttributeError: + pass + time.sleep(.1) + _chan0_lo_locked_thread = threading.Thread(target=_chan0_lo_locked_probe) + _chan0_lo_locked_thread.daemon = True + _chan0_lo_locked_thread.start() + self.label_rf_freq = self._sg.tr.actual_rf_freq + self._label_rf_freq_tool_bar = Qt.QToolBar(self) + self._label_rf_freq_formatter = lambda x: x + self._label_rf_freq_tool_bar.addWidget(Qt.QLabel("LO freq: ")) + self._label_rf_freq_label = Qt.QLabel(str(self._label_rf_freq_formatter(self.label_rf_freq))) + self._label_rf_freq_tool_bar.addWidget(self._label_rf_freq_label) + self.top_grid_layout.addWidget(self._label_rf_freq_tool_bar, 8,1,1,1) + self.label_dsp_freq = self._sg.tr.actual_dsp_freq + self._label_dsp_freq_tool_bar = Qt.QToolBar(self) + self._label_dsp_freq_formatter = lambda x: x + self._label_dsp_freq_tool_bar.addWidget(Qt.QLabel("DSP Freq: ")) + self._label_dsp_freq_label = Qt.QLabel(str(self._label_dsp_freq_formatter(self.label_dsp_freq))) + self._label_dsp_freq_tool_bar.addWidget(self._label_dsp_freq_label) + self.top_grid_layout.addWidget(self._label_dsp_freq_tool_bar, 8,2,1,1) + ################################################## + # Freq Sink + ################################################## + if self._sg.args.show_freq_sink: + self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( + 1024, #size + firdes.WIN_BLACKMAN_hARRIS, #wintype + self.freq_coarse + self.freq_fine, #fc + self.samp_rate, #bw + "", #name + 1 #number of inputs ) - gain_hbox.AddSpacer(5) - + self.qtgui_freq_sink_x_0.set_update_time(0.10) + self.qtgui_freq_sink_x_0.set_y_axis(-100, 10) + self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") + self.qtgui_freq_sink_x_0.enable_autoscale(False) + self.qtgui_freq_sink_x_0.enable_grid(False) + self.qtgui_freq_sink_x_0.set_fft_average(1.0) + self.qtgui_freq_sink_x_0.enable_control_panel(False) + self.qtgui_freq_sink_x_0.set_line_label(0, "Siggen Spectrum") + self.qtgui_freq_sink_x_0.set_line_width(0, 1) + self.qtgui_freq_sink_x_0.set_line_color(0, "blue") + self.qtgui_freq_sink_x_0.set_line_alpha(0, 1.0) + self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) + self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win, 9,0,2,5) + # Reconnect: + self._sg.extra_sink = self.qtgui_freq_sink_x_0 + self._sg[uhd_siggen.TYPE_KEY] = self._sg[uhd_siggen.TYPE_KEY] ################################################## - # Sample Rate controls + # Start transmitting ################################################## - sam_hbox = forms.static_box_sizer(parent=self.panel, - label="Sample Rate", - orient=wx.HORIZONTAL, - bold=True) - self.vbox.Add(sam_hbox, 0, wx.EXPAND) - self.vbox.AddSpacer(10) - self.vbox.AddStretchSpacer() - sam_hbox.AddStretchSpacer(20) - forms.static_text( - parent=self.panel, sizer=sam_hbox, - label='Sample Rate (sps)', - ps=self.tb, - key=uhd_siggen.SAMP_RATE_KEY, - converter=forms.float_converter(), + self._sg.start() + + ################################################## + # QT + Flowgraph stuff + ################################################## + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "uhd_siggen_gui") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() + + def stop(self): + """ + Stop flow graph, tear down blocks + """ + self._sg.stop() + self._sg.wait() + self._sg = None + + ################################################## + # Setters + ################################################## + def set_waveform(self, waveform): + self._freq1_offset_win.setEnabled(waveform in self._freq1_enable_on) + self._freq2_offset_win.setEnabled(waveform in self._freq2_enable_on) + self._sg[uhd_siggen.TYPE_KEY] = waveform + self._waveform_callback(waveform) + + def set_freq_coarse(self, freq_coarse): + self.freq_coarse = freq_coarse + self.update_center_freq() + + def set_freq_fine(self, freq_fine): + self.freq_fine = freq_fine + self.update_center_freq() + + def set_lo_offset(self, lo_offset): + self.lo_offset = lo_offset + self.update_center_freq() + + def update_center_freq(self): + if hasattr(self, "qtgui_freq_sink_x_0"): + self.qtgui_freq_sink_x_0.set_frequency_range(self.freq_coarse + self.freq_fine, self.samp_rate) + self.tune() + + def tune(self): + """ + Multi-channel tune + """ + tune_req = uhd.tune_request( + self.freq_fine + self.freq_coarse, + self.lo_offset ) - sam_hbox.AddStretchSpacer(20) + for idx, c in enumerate(self._sg.channels): + tune_res = self.usrp.set_center_freq(tune_req, c) + if idx == 0: + self.set_label_dsp_freq(tune_res.actual_dsp_freq) + self.set_label_rf_freq(tune_res.actual_rf_freq) - ################################################## - # UHD status - ################################################## - u2_hbox = forms.static_box_sizer(parent=self.panel, - label="UHD (%s)" % (uhd.get_version_string()), - orient=wx.HORIZONTAL, - bold=True) - self.vbox.Add(u2_hbox, 0, wx.EXPAND) - self.vbox.AddSpacer(10) - self.vbox.AddStretchSpacer() - u2_hbox.AddSpacer(10) - forms.static_text( - parent=self.panel, sizer=u2_hbox, - ps=self.tb, - key=uhd_siggen.DESC_KEY, - converter=forms.str_converter(), + def set_freq1_offset(self, freq1_offset): + self._sg[uhd_siggen.WAVEFORM_FREQ_KEY] = freq1_offset + + def set_freq2_offset(self, freq2_offset): + self._sg[uhd_siggen.WAVEFORM2_FREQ_KEY] = freq2_offset + + def set_amplitude(self, amplitude): + self.amplitude = amplitude + self._sg[uhd_siggen.AMPLITUDE_KEY] = amplitude + + def set_sync_phases(self, sync): + if sync: + self._sg.vprint("Attempting to sync LO phases. This does not work with all boards.") + self._sg.set_freq(self.freq_coarse + self.freq_fine, False) + + def set_ant(self, ant): + self.ant = ant + self._ant_callback(self.ant) + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + Qt.QMetaObject.invokeMethod( + self._samp_rate_line_edit, "setText", + Qt.Q_ARG("QString", eng_notation.num_to_str(self.samp_rate)) ) - self.vbox.AddSpacer(5) - self.vbox.AddStretchSpacer() + self._sg[uhd_siggen.SAMP_RATE_KEY] = samp_rate + self.update_center_freq() -def main(): - try: - # Get command line parameters - (options, args) = uhd_siggen.get_options() + def set_label_rf_freq(self, label_rf_freq): + self.label_rf_freq = label_rf_freq + Qt.QMetaObject.invokeMethod( + self._label_rf_freq_label, "setText", + Qt.Q_ARG( + "QString", + eng_notation.num_to_str(self.label_rf_freq) + ) + ) - # Create the top block using these - tb = uhd_siggen.top_block(options, args) + def set_label_dsp_freq(self, label_dsp_freq): + self.label_dsp_freq = label_dsp_freq + Qt.QMetaObject.invokeMethod( + self._label_dsp_freq_label, "setText", + Qt.Q_ARG( + "QString", + eng_notation.num_to_str(self.label_dsp_freq) + ) + ) - # Create the GUI application - app = gui.app(top_block=tb, # Constructed top block - gui=app_gui, # User interface class - options=options, # Command line options - args=args, # Command line args - title="UHD Signal Generator", # Top window title - nstatus=1, # Number of status lines - start=True, # Whether to start flowgraph - realtime=True) # Whether to set realtime priority + def set_chan0_lo_locked(self, chan0_lo_locked): + self.set_lo_locked_probe_0(chan0_lo_locked) - # And run it - app.MainLoop() + def set_lo_locked_probe_0(self, lo_locked_probe_0): + Qt.QMetaObject.invokeMethod( + self._lo_locked_probe_0_label, "setText", + Qt.Q_ARG("QString", str(self.lo_locked_probe_0)) + ) + + +def setup_parser(): + """ + Argument parser for siggen_gui + """ + parser = uhd_siggen.setup_argparser() + group = parser.add_argument_group('GUI Arguments') + group.add_argument( + "-q", "--show-freq-sink", action="store_true", + help="Show QT Frequency Widget" + ) + return parser + +def main(): + """ Go, go, go! """ + parser = setup_parser() + args = parser.parse_args() + if(StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0")): + Qt.QApplication.setGraphicsSystem(gr.prefs().get_string('qtgui', 'style', 'raster')) + qapp = Qt.QApplication(sys.argv) + siggen_gui = uhd_siggen_gui(args) + siggen_gui.show() + def quitting(): + siggen_gui.stop() + qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting) + qapp.exec_() + siggen_gui = None #to clean up Qt widgets - except RuntimeError, e: - print e - sys.exit(1) +if __name__ == '__main__': + import ctypes + import sys + if sys.platform.startswith('linux'): + try: + x11 = ctypes.cdll.LoadLibrary('libX11.so') + x11.XInitThreads() + except: + print("Warning: failed to XInitThreads()") + main() -# Make sure to create the top block (tb) within a function: That code -# in main will allow tb to go out of scope on return, which will call -# the decontructor on uhd device and stop transmit. Whats odd is that -# grc works fine with tb in the __main__, perhaps its because the -# try/except clauses around tb. -if __name__ == "__main__": main() diff --git a/gr-uhd/examples/grc/uhd_siggen_gui.grc b/gr-uhd/examples/grc/uhd_siggen_gui.grc new file mode 100644 index 0000000000..27eda7c4c7 --- /dev/null +++ b/gr-uhd/examples/grc/uhd_siggen_gui.grc @@ -0,0 +1,2154 @@ +<?xml version='1.0' encoding='utf-8'?> +<?grc format='1' created='3.7.9'?> +<flow_graph> + <timestamp>Sat Jun 27 12:02:49 2015</timestamp> + <block> + <key>options</key> + <param> + <key>author</key> + <value>Ettus Research</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>description</key> + <value>Signal Generator for use with USRP Devices</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(-8, -11)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>generate_options</key> + <value>qt_gui</value> + </param> + <param> + <key>id</key> + <value>uhd_siggen_gui</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>thread_safe_setters</key> + <value></value> + </param> + <param> + <key>title</key> + <value>UHD Signal Generator</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>.7</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(984, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>5,0,1,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>amplitude</value> + </param> + <param> + <key>label</key> + <value>Signal Amplitude</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>0</value> + </param> + <param> + <key>step</key> + <value>.001</value> + </param> + <param> + <key>stop</key> + <value>1</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_chooser</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>RX2</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(304, 175)</value> + </param> + <param> + <key>gui_hint</key> + <value>7,4,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>ant</value> + </param> + <param> + <key>label0</key> + <value>RX2</value> + </param> + <param> + <key>label1</key> + <value>TX/RX</value> + </param> + <param> + <key>label2</key> + <value>J1</value> + </param> + <param> + <key>label3</key> + <value>J2</value> + </param> + <param> + <key>label4</key> + <value></value> + </param> + <param> + <key>label</key> + <value>Antenna</value> + </param> + <param> + <key>labels</key> + <value>[]</value> + </param> + <param> + <key>num_opts</key> + <value>2</value> + </param> + <param> + <key>option0</key> + <value>RX2</value> + </param> + <param> + <key>option1</key> + <value>TX/RX</value> + </param> + <param> + <key>option2</key> + <value>J1</value> + </param> + <param> + <key>option3</key> + <value>J2</value> + </param> + <param> + <key>option4</key> + <value>4</value> + </param> + <param> + <key>options</key> + <value>[0, 1, 2]</value> + </param> + <param> + <key>orient</key> + <value>Qt.QVBoxLayout</value> + </param> + <param> + <key>type</key> + <value>string</value> + </param> + <param> + <key>widget</key> + <value>combo_box</value> + </param> + </block> + <block> + <key>variable_function_probe</key> + <param> + <key>block_id</key> + <value>uhd_usrp_source_0</value> + </param> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>function_args</key> + <value>"'lo_locked'"</value> + </param> + <param> + <key>function_name</key> + <value>get_sensor</value> + </param> + <param> + <key>_coordinate</key> + <value>(0, 110)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>chan0_lo_locked</value> + </param> + <param> + <key>poll_rate</key> + <value>10</value> + </param> + <param> + <key>value</key> + <value>uhd.sensor_value("", False, "")</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(656, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>4,0,1,3</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>freq1_offset</value> + </param> + <param> + <key>label</key> + <value>Frequency Offset: Signal 1</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>-1e6</value> + </param> + <param> + <key>step</key> + <value>100</value> + </param> + <param> + <key>stop</key> + <value>1e6</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(816, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>4,3,1,2</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>freq2_offset</value> + </param> + <param> + <key>label</key> + <value>Signal 2 </value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>-1e6</value> + </param> + <param> + <key>step</key> + <value>100</value> + </param> + <param> + <key>stop</key> + <value>1e6</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>1e9</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(296, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>1,0,1,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>freq_coarse</value> + </param> + <param> + <key>label</key> + <value>Center Frequency</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>100e6</value> + </param> + <param> + <key>step</key> + <value>1e3</value> + </param> + <param> + <key>stop</key> + <value>2e9</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(440, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>2,0,1,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>freq_fine</value> + </param> + <param> + <key>label</key> + <value>Fine Tuning</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>-1e6</value> + </param> + <param> + <key>step</key> + <value>1e3</value> + </param> + <param> + <key>stop</key> + <value>1e6</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>20</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(1128, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>6,0,1,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>gain</value> + </param> + <param> + <key>label</key> + <value>TX Gain</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>0</value> + </param> + <param> + <key>step</key> + <value>.5</value> + </param> + <param> + <key>stop</key> + <value>50</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_label</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>1e3</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>_coordinate</key> + <value>(688, 236)</value> + </param> + <param> + <key>gui_hint</key> + <value>8,2,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>label_dsp_freq</value> + </param> + <param> + <key>label</key> + <value>DSP Freq</value> + </param> + <param> + <key>type</key> + <value>real</value> + </param> + </block> + <block> + <key>variable_qtgui_label</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>1e9</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>_coordinate</key> + <value>(576, 236)</value> + </param> + <param> + <key>gui_hint</key> + <value>8,1,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>label_lo_freq</value> + </param> + <param> + <key>label</key> + <value>LO freq</value> + </param> + <param> + <key>type</key> + <value>real</value> + </param> + </block> + <block> + <key>variable_qtgui_label</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>chan0_lo_locked.to_bool()</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>_coordinate</key> + <value>(448, 236)</value> + </param> + <param> + <key>gui_hint</key> + <value>8,0,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>lo_locked_probe_0</value> + </param> + <param> + <key>label</key> + <value>LO locked</value> + </param> + <param> + <key>type</key> + <value>bool</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(552, -2)</value> + </param> + <param> + <key>gui_hint</key> + <value>3,0,1,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>lo_offset</value> + </param> + <param> + <key>label</key> + <value>LO Offset</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>-samp_rate/2</value> + </param> + <param> + <key>step</key> + <value>samp_rate/2</value> + </param> + <param> + <key>stop</key> + <value>1e3</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_entry</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>1e6</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(160, 259)</value> + </param> + <param> + <key>gui_hint</key> + <value>7,0,1,2</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>label</key> + <value>Sampling Rate</value> + </param> + <param> + <key>type</key> + <value>real</value> + </param> + </block> + <block> + <key>variable_qtgui_push_button</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>False</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(896, 315)</value> + </param> + <param> + <key>gui_hint</key> + <value>7,2,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>sync_phases</value> + </param> + <param> + <key>label</key> + <value>Sync LOs</value> + </param> + <param> + <key>pressed</key> + <value>True</value> + </param> + <param> + <key>released</key> + <value>False</value> + </param> + <param> + <key>type</key> + <value>bool</value> + </param> + </block> + <block> + <key>variable_qtgui_chooser</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(160, -6)</value> + </param> + <param> + <key>gui_hint</key> + <value>0,0,1,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>waveform</value> + </param> + <param> + <key>label0</key> + <value>Tone</value> + </param> + <param> + <key>label1</key> + <value>Two-Tone</value> + </param> + <param> + <key>label2</key> + <value>Uniform Noise</value> + </param> + <param> + <key>label3</key> + <value>Two Tone</value> + </param> + <param> + <key>label4</key> + <value>Sweep</value> + </param> + <param> + <key>label</key> + <value>Waveform</value> + </param> + <param> + <key>labels</key> + <value>[]</value> + </param> + <param> + <key>num_opts</key> + <value>5</value> + </param> + <param> + <key>option0</key> + <value>0</value> + </param> + <param> + <key>option1</key> + <value>1</value> + </param> + <param> + <key>option2</key> + <value>2</value> + </param> + <param> + <key>option3</key> + <value>3</value> + </param> + <param> + <key>option4</key> + <value>4</value> + </param> + <param> + <key>options</key> + <value>[0, 1, 2]</value> + </param> + <param> + <key>orient</key> + <value>Qt.QHBoxLayout</value> + </param> + <param> + <key>type</key> + <value>int</value> + </param> + <param> + <key>widget</key> + <value>radio_buttons</value> + </param> + </block> + <block> + <key>analog_sig_source_x</key> + <param> + <key>amp</key> + <value>amplitude if not sync_phases else 0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>freq</key> + <value>freq1_offset</value> + </param> + <param> + <key>_coordinate</key> + <value>(720, 125)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>analog_sig_source_x_0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>offset</key> + <value>0</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>waveform</key> + <value>analog.GR_TRI_WAVE</value> + </param> + </block> + <block> + <key>qtgui_freq_sink_x</key> + <param> + <key>autoscale</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>1.0</value> + </param> + <param> + <key>bw</key> + <value>samp_rate</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>fc</key> + <value>freq_coarse + freq_fine</value> + </param> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>ctrlpanel</key> + <value>False</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>fftsize</key> + <value>1024</value> + </param> + <param> + <key>_coordinate</key> + <value>(920, 220)</value> + </param> + <param> + <key>gui_hint</key> + <value>9,0,2,5</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>grid</key> + <value>False</value> + </param> + <param> + <key>id</key> + <value>qtgui_freq_sink_x_0</value> + </param> + <param> + <key>legend</key> + <value>True</value> + </param> + <param> + <key>alpha1</key> + <value>1.0</value> + </param> + <param> + <key>color1</key> + <value>"blue"</value> + </param> + <param> + <key>label1</key> + <value></value> + </param> + <param> + <key>width1</key> + <value>1</value> + </param> + <param> + <key>alpha10</key> + <value>1.0</value> + </param> + <param> + <key>color10</key> + <value>"dark blue"</value> + </param> + <param> + <key>label10</key> + <value></value> + </param> + <param> + <key>width10</key> + <value>1</value> + </param> + <param> + <key>alpha2</key> + <value>1.0</value> + </param> + <param> + <key>color2</key> + <value>"red"</value> + </param> + <param> + <key>label2</key> + <value></value> + </param> + <param> + <key>width2</key> + <value>1</value> + </param> + <param> + <key>alpha3</key> + <value>1.0</value> + </param> + <param> + <key>color3</key> + <value>"green"</value> + </param> + <param> + <key>label3</key> + <value></value> + </param> + <param> + <key>width3</key> + <value>1</value> + </param> + <param> + <key>alpha4</key> + <value>1.0</value> + </param> + <param> + <key>color4</key> + <value>"black"</value> + </param> + <param> + <key>label4</key> + <value></value> + </param> + <param> + <key>width4</key> + <value>1</value> + </param> + <param> + <key>alpha5</key> + <value>1.0</value> + </param> + <param> + <key>color5</key> + <value>"cyan"</value> + </param> + <param> + <key>label5</key> + <value></value> + </param> + <param> + <key>width5</key> + <value>1</value> + </param> + <param> + <key>alpha6</key> + <value>1.0</value> + </param> + <param> + <key>color6</key> + <value>"magenta"</value> + </param> + <param> + <key>label6</key> + <value></value> + </param> + <param> + <key>width6</key> + <value>1</value> + </param> + <param> + <key>alpha7</key> + <value>1.0</value> + </param> + <param> + <key>color7</key> + <value>"yellow"</value> + </param> + <param> + <key>label7</key> + <value></value> + </param> + <param> + <key>width7</key> + <value>1</value> + </param> + <param> + <key>alpha8</key> + <value>1.0</value> + </param> + <param> + <key>color8</key> + <value>"dark red"</value> + </param> + <param> + <key>label8</key> + <value></value> + </param> + <param> + <key>width8</key> + <value>1</value> + </param> + <param> + <key>alpha9</key> + <value>1.0</value> + </param> + <param> + <key>color9</key> + <value>"dark green"</value> + </param> + <param> + <key>label9</key> + <value></value> + </param> + <param> + <key>width9</key> + <value>1</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>name</key> + <value>""</value> + </param> + <param> + <key>nconnections</key> + <value>1</value> + </param> + <param> + <key>showports</key> + <value>True</value> + </param> + <param> + <key>freqhalf</key> + <value>True</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> + <key>tr_level</key> + <value>0.0</value> + </param> + <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_FREE</value> + </param> + <param> + <key>tr_tag</key> + <value>""</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>wintype</key> + <value>firdes.WIN_BLACKMAN_hARRIS</value> + </param> + <param> + <key>ymax</key> + <value>10</value> + </param> + <param> + <key>ymin</key> + <value>-140</value> + </param> + </block> + <block> + <key>uhd_usrp_sink</key> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>ant0</key> + <value></value> + </param> + <param> + <key>bw0</key> + <value>0</value> + </param> + <param> + <key>center_freq0</key> + <value>0</value> + </param> + <param> + <key>norm_gain0</key> + <value>False</value> + </param> + <param> + <key>gain0</key> + <value>0</value> + </param> + <param> + <key>ant10</key> + <value></value> + </param> + <param> + <key>bw10</key> + <value>0</value> + </param> + <param> + <key>center_freq10</key> + <value>0</value> + </param> + <param> + <key>norm_gain10</key> + <value>False</value> + </param> + <param> + <key>gain10</key> + <value>0</value> + </param> + <param> + <key>ant11</key> + <value></value> + </param> + <param> + <key>bw11</key> + <value>0</value> + </param> + <param> + <key>center_freq11</key> + <value>0</value> + </param> + <param> + <key>norm_gain11</key> + <value>False</value> + </param> + <param> + <key>gain11</key> + <value>0</value> + </param> + <param> + <key>ant12</key> + <value></value> + </param> + <param> + <key>bw12</key> + <value>0</value> + </param> + <param> + <key>center_freq12</key> + <value>0</value> + </param> + <param> + <key>norm_gain12</key> + <value>False</value> + </param> + <param> + <key>gain12</key> + <value>0</value> + </param> + <param> + <key>ant13</key> + <value></value> + </param> + <param> + <key>bw13</key> + <value>0</value> + </param> + <param> + <key>center_freq13</key> + <value>0</value> + </param> + <param> + <key>norm_gain13</key> + <value>False</value> + </param> + <param> + <key>gain13</key> + <value>0</value> + </param> + <param> + <key>ant14</key> + <value></value> + </param> + <param> + <key>bw14</key> + <value>0</value> + </param> + <param> + <key>center_freq14</key> + <value>0</value> + </param> + <param> + <key>norm_gain14</key> + <value>False</value> + </param> + <param> + <key>gain14</key> + <value>0</value> + </param> + <param> + <key>ant15</key> + <value></value> + </param> + <param> + <key>bw15</key> + <value>0</value> + </param> + <param> + <key>center_freq15</key> + <value>0</value> + </param> + <param> + <key>norm_gain15</key> + <value>False</value> + </param> + <param> + <key>gain15</key> + <value>0</value> + </param> + <param> + <key>ant16</key> + <value></value> + </param> + <param> + <key>bw16</key> + <value>0</value> + </param> + <param> + <key>center_freq16</key> + <value>0</value> + </param> + <param> + <key>norm_gain16</key> + <value>False</value> + </param> + <param> + <key>gain16</key> + <value>0</value> + </param> + <param> + <key>ant17</key> + <value></value> + </param> + <param> + <key>bw17</key> + <value>0</value> + </param> + <param> + <key>center_freq17</key> + <value>0</value> + </param> + <param> + <key>norm_gain17</key> + <value>False</value> + </param> + <param> + <key>gain17</key> + <value>0</value> + </param> + <param> + <key>ant18</key> + <value></value> + </param> + <param> + <key>bw18</key> + <value>0</value> + </param> + <param> + <key>center_freq18</key> + <value>0</value> + </param> + <param> + <key>norm_gain18</key> + <value>False</value> + </param> + <param> + <key>gain18</key> + <value>0</value> + </param> + <param> + <key>ant19</key> + <value></value> + </param> + <param> + <key>bw19</key> + <value>0</value> + </param> + <param> + <key>center_freq19</key> + <value>0</value> + </param> + <param> + <key>norm_gain19</key> + <value>False</value> + </param> + <param> + <key>gain19</key> + <value>0</value> + </param> + <param> + <key>ant1</key> + <value></value> + </param> + <param> + <key>bw1</key> + <value>0</value> + </param> + <param> + <key>center_freq1</key> + <value>0</value> + </param> + <param> + <key>norm_gain1</key> + <value>False</value> + </param> + <param> + <key>gain1</key> + <value>0</value> + </param> + <param> + <key>ant20</key> + <value></value> + </param> + <param> + <key>bw20</key> + <value>0</value> + </param> + <param> + <key>center_freq20</key> + <value>0</value> + </param> + <param> + <key>norm_gain20</key> + <value>False</value> + </param> + <param> + <key>gain20</key> + <value>0</value> + </param> + <param> + <key>ant21</key> + <value></value> + </param> + <param> + <key>bw21</key> + <value>0</value> + </param> + <param> + <key>center_freq21</key> + <value>0</value> + </param> + <param> + <key>norm_gain21</key> + <value>False</value> + </param> + <param> + <key>gain21</key> + <value>0</value> + </param> + <param> + <key>ant22</key> + <value></value> + </param> + <param> + <key>bw22</key> + <value>0</value> + </param> + <param> + <key>center_freq22</key> + <value>0</value> + </param> + <param> + <key>norm_gain22</key> + <value>False</value> + </param> + <param> + <key>gain22</key> + <value>0</value> + </param> + <param> + <key>ant23</key> + <value></value> + </param> + <param> + <key>bw23</key> + <value>0</value> + </param> + <param> + <key>center_freq23</key> + <value>0</value> + </param> + <param> + <key>norm_gain23</key> + <value>False</value> + </param> + <param> + <key>gain23</key> + <value>0</value> + </param> + <param> + <key>ant24</key> + <value></value> + </param> + <param> + <key>bw24</key> + <value>0</value> + </param> + <param> + <key>center_freq24</key> + <value>0</value> + </param> + <param> + <key>norm_gain24</key> + <value>False</value> + </param> + <param> + <key>gain24</key> + <value>0</value> + </param> + <param> + <key>ant25</key> + <value></value> + </param> + <param> + <key>bw25</key> + <value>0</value> + </param> + <param> + <key>center_freq25</key> + <value>0</value> + </param> + <param> + <key>norm_gain25</key> + <value>False</value> + </param> + <param> + <key>gain25</key> + <value>0</value> + </param> + <param> + <key>ant26</key> + <value></value> + </param> + <param> + <key>bw26</key> + <value>0</value> + </param> + <param> + <key>center_freq26</key> + <value>0</value> + </param> + <param> + <key>norm_gain26</key> + <value>False</value> + </param> + <param> + <key>gain26</key> + <value>0</value> + </param> + <param> + <key>ant27</key> + <value></value> + </param> + <param> + <key>bw27</key> + <value>0</value> + </param> + <param> + <key>center_freq27</key> + <value>0</value> + </param> + <param> + <key>norm_gain27</key> + <value>False</value> + </param> + <param> + <key>gain27</key> + <value>0</value> + </param> + <param> + <key>ant28</key> + <value></value> + </param> + <param> + <key>bw28</key> + <value>0</value> + </param> + <param> + <key>center_freq28</key> + <value>0</value> + </param> + <param> + <key>norm_gain28</key> + <value>False</value> + </param> + <param> + <key>gain28</key> + <value>0</value> + </param> + <param> + <key>ant29</key> + <value></value> + </param> + <param> + <key>bw29</key> + <value>0</value> + </param> + <param> + <key>center_freq29</key> + <value>0</value> + </param> + <param> + <key>norm_gain29</key> + <value>False</value> + </param> + <param> + <key>gain29</key> + <value>0</value> + </param> + <param> + <key>ant2</key> + <value></value> + </param> + <param> + <key>bw2</key> + <value>0</value> + </param> + <param> + <key>center_freq2</key> + <value>0</value> + </param> + <param> + <key>norm_gain2</key> + <value>False</value> + </param> + <param> + <key>gain2</key> + <value>0</value> + </param> + <param> + <key>ant30</key> + <value></value> + </param> + <param> + <key>bw30</key> + <value>0</value> + </param> + <param> + <key>center_freq30</key> + <value>0</value> + </param> + <param> + <key>norm_gain30</key> + <value>False</value> + </param> + <param> + <key>gain30</key> + <value>0</value> + </param> + <param> + <key>ant31</key> + <value></value> + </param> + <param> + <key>bw31</key> + <value>0</value> + </param> + <param> + <key>center_freq31</key> + <value>0</value> + </param> + <param> + <key>norm_gain31</key> + <value>False</value> + </param> + <param> + <key>gain31</key> + <value>0</value> + </param> + <param> + <key>ant3</key> + <value></value> + </param> + <param> + <key>bw3</key> + <value>0</value> + </param> + <param> + <key>center_freq3</key> + <value>0</value> + </param> + <param> + <key>norm_gain3</key> + <value>False</value> + </param> + <param> + <key>gain3</key> + <value>0</value> + </param> + <param> + <key>ant4</key> + <value></value> + </param> + <param> + <key>bw4</key> + <value>0</value> + </param> + <param> + <key>center_freq4</key> + <value>0</value> + </param> + <param> + <key>norm_gain4</key> + <value>False</value> + </param> + <param> + <key>gain4</key> + <value>0</value> + </param> + <param> + <key>ant5</key> + <value></value> + </param> + <param> + <key>bw5</key> + <value>0</value> + </param> + <param> + <key>center_freq5</key> + <value>0</value> + </param> + <param> + <key>norm_gain5</key> + <value>False</value> + </param> + <param> + <key>gain5</key> + <value>0</value> + </param> + <param> + <key>ant6</key> + <value></value> + </param> + <param> + <key>bw6</key> + <value>0</value> + </param> + <param> + <key>center_freq6</key> + <value>0</value> + </param> + <param> + <key>norm_gain6</key> + <value>False</value> + </param> + <param> + <key>gain6</key> + <value>0</value> + </param> + <param> + <key>ant7</key> + <value></value> + </param> + <param> + <key>bw7</key> + <value>0</value> + </param> + <param> + <key>center_freq7</key> + <value>0</value> + </param> + <param> + <key>norm_gain7</key> + <value>False</value> + </param> + <param> + <key>gain7</key> + <value>0</value> + </param> + <param> + <key>ant8</key> + <value></value> + </param> + <param> + <key>bw8</key> + <value>0</value> + </param> + <param> + <key>center_freq8</key> + <value>0</value> + </param> + <param> + <key>norm_gain8</key> + <value>False</value> + </param> + <param> + <key>gain8</key> + <value>0</value> + </param> + <param> + <key>ant9</key> + <value></value> + </param> + <param> + <key>bw9</key> + <value>0</value> + </param> + <param> + <key>center_freq9</key> + <value>0</value> + </param> + <param> + <key>norm_gain9</key> + <value>False</value> + </param> + <param> + <key>gain9</key> + <value>0</value> + </param> + <param> + <key>clock_rate</key> + <value>0.0</value> + </param> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>dev_addr</key> + <value>""</value> + </param> + <param> + <key>dev_args</key> + <value>""</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(960, 125)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>uhd_usrp_sink_0</value> + </param> + <param> + <key>type</key> + <value>fc32</value> + </param> + <param> + <key>clock_source0</key> + <value></value> + </param> + <param> + <key>sd_spec0</key> + <value></value> + </param> + <param> + <key>time_source0</key> + <value></value> + </param> + <param> + <key>clock_source1</key> + <value></value> + </param> + <param> + <key>sd_spec1</key> + <value></value> + </param> + <param> + <key>time_source1</key> + <value></value> + </param> + <param> + <key>clock_source2</key> + <value></value> + </param> + <param> + <key>sd_spec2</key> + <value></value> + </param> + <param> + <key>time_source2</key> + <value></value> + </param> + <param> + <key>clock_source3</key> + <value></value> + </param> + <param> + <key>sd_spec3</key> + <value></value> + </param> + <param> + <key>time_source3</key> + <value></value> + </param> + <param> + <key>clock_source4</key> + <value></value> + </param> + <param> + <key>sd_spec4</key> + <value></value> + </param> + <param> + <key>time_source4</key> + <value></value> + </param> + <param> + <key>clock_source5</key> + <value></value> + </param> + <param> + <key>sd_spec5</key> + <value></value> + </param> + <param> + <key>time_source5</key> + <value></value> + </param> + <param> + <key>clock_source6</key> + <value></value> + </param> + <param> + <key>sd_spec6</key> + <value></value> + </param> + <param> + <key>time_source6</key> + <value></value> + </param> + <param> + <key>clock_source7</key> + <value></value> + </param> + <param> + <key>sd_spec7</key> + <value></value> + </param> + <param> + <key>time_source7</key> + <value></value> + </param> + <param> + <key>nchan</key> + <value>1</value> + </param> + <param> + <key>num_mboards</key> + <value>1</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>hide_cmd_port</key> + <value>False</value> + </param> + <param> + <key>stream_args</key> + <value></value> + </param> + <param> + <key>stream_chans</key> + <value>[]</value> + </param> + <param> + <key>sync</key> + <value></value> + </param> + <param> + <key>len_tag_name</key> + <value></value> + </param> + <param> + <key>otw</key> + <value></value> + </param> + </block> + <connection> + <source_block_id>analog_sig_source_x_0</source_block_id> + <sink_block_id>qtgui_freq_sink_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>analog_sig_source_x_0</source_block_id> + <sink_block_id>uhd_usrp_sink_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> |