commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 02/03: uhd: Updated uhd_siggen_gui (uses QT


From: git
Subject: [Commit-gnuradio] [gnuradio] 02/03: uhd: Updated uhd_siggen_gui (uses QT), added GRC siggen example
Date: Thu, 24 Sep 2015 23:53:51 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 5fe360c6ad5e6b50b00380962a1fbe0b5eaeca34
Author: Martin Braun <address@hidden>
Date:   Sun Jun 28 00:23:16 2015 -0700

    uhd: Updated uhd_siggen_gui (uses QT), added GRC siggen example
    
    - Added uhd_app.py base class for example apps
    - uhd_siggen and uhd_siggen_gui now both use uhd_app
    - siggen now also multi-channel capabilities
    - siggen_gui fully QT, no more WX
---
 gr-uhd/apps/CMakeLists.txt             |    1 +
 gr-uhd/apps/uhd_app.py                 |  292 +++++
 gr-uhd/apps/uhd_siggen                 |   34 +-
 gr-uhd/apps/uhd_siggen_base.py         |  351 ++----
 gr-uhd/apps/uhd_siggen_gui             |  689 ++++++----
 gr-uhd/examples/grc/uhd_siggen_gui.grc | 2154 ++++++++++++++++++++++++++++++++
 6 files changed, 2994 insertions(+), 527 deletions(-)

diff --git a/gr-uhd/apps/CMakeLists.txt b/gr-uhd/apps/CMakeLists.txt
index 1d68c00..ebcaf6e 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 0000000..5af01ad
--- /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 52fc249..6e5d465 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 503f49b..31415da 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 80fcf8e..ab04ccc 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 0000000..27eda7c
--- /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>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]