From f0bf96fad3e02e494fa8ae3edde548844342569b Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Wed, 9 Sep 2009 12:33:10 -0700
Subject: copied usrp_siggen stuff from experimental gui into gnuradio tree

---
 gr-utils/src/python/Makefile.am         |   5 +-
 gr-utils/src/python/usrp2_siggen.py     | 389 --------------------------
 gr-utils/src/python/usrp2_siggen_gui.py | 275 -------------------
 gr-utils/src/python/usrp_siggen.py      | 471 ++++++++++++++++++++------------
 gr-utils/src/python/usrp_siggen_gui.py  | 310 +++++++++++++++++++++
 5 files changed, 601 insertions(+), 849 deletions(-)
 delete mode 100755 gr-utils/src/python/usrp2_siggen.py
 delete mode 100755 gr-utils/src/python/usrp2_siggen_gui.py
 create mode 100755 gr-utils/src/python/usrp_siggen_gui.py

(limited to 'gr-utils/src')

diff --git a/gr-utils/src/python/Makefile.am b/gr-utils/src/python/Makefile.am
index 0c8240fe47..fb21e4f449 100644
--- a/gr-utils/src/python/Makefile.am
+++ b/gr-utils/src/python/Makefile.am
@@ -56,10 +56,9 @@ bin_SCRIPTS = \
     usrp_rx_cfile.py \
     usrp_rx_nogui.py \
     usrp_siggen.py \
+    usrp_siggen_gui.py \
     usrp_test_counting.py \
     usrp_test_loopback.py \
     usrp2_fft.py \
-    usrp2_rx_cfile.py \
-    usrp2_siggen.py \
-    usrp2_siggen_gui.py
+    usrp2_rx_cfile.py
 
diff --git a/gr-utils/src/python/usrp2_siggen.py b/gr-utils/src/python/usrp2_siggen.py
deleted file mode 100755
index 9ade933c7c..0000000000
--- a/gr-utils/src/python/usrp2_siggen.py
+++ /dev/null
@@ -1,389 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008,2009 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.
-# 
-
-from gnuradio import gr, eng_notation, usrp2
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-import sys
-import math
-
-n2s = eng_notation.num_to_str
-
-waveforms = { gr.GR_SIN_WAVE   : "Complex Sinusoid",
-              gr.GR_CONST_WAVE : "Constant",
-              gr.GR_GAUSSIAN   : "Gaussian Noise",
-              gr.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):
-    def __init__(self, options, args):
-        gr.top_block.__init__(self)
-        self._verbose = options.verbose
-
-        self._interp = 0 
-        self._gain = 0
-        self._freq = None       # Indicates frequency hasn't been successfully set yet
-        self._bb_freq = 0
-        self._ddc_freq = 0
-        self._amplitude = 0
-        self._type = None       # Indicates waveform flowgraph not created yet
-        self._offset = options.offset
-
-        self.set_usrp2(options.interface, options.mac_addr)
-        self.set_interp(options.interp)
-        self.set_gain(options.gain)
-        self.set_freq(options.tx_freq, options.lo_offset)
-        self.set_amplitude(options.amplitude)
-
-        self.set_waveform_freq(options.waveform_freq)
-        self.set_waveform2_freq(options.waveform2_freq)
-        self.set_waveform(options.type)
-
-    def set_usrp2(self, interface, mac_addr):
-        self._u = usrp2.sink_32fc(interface, mac_addr)
-        self._dac_rate = self._u.dac_rate()
-        if self._verbose:
-            print "Network interface:", interface
-            print "Network address:", self._u.mac_addr()
-            print "Daughterboard ID:", hex(self._u.daughterboard_id())
-
-    def set_interp(self, interp):
-        if interp < 4 or interp > 512: # FIXME get from flowgraph
-            if self._verbose: print "Interpolation rate out of range:", interp
-            return False
-
-        if not self._u.set_interp(interp):
-            raise RuntimeError("Failed to set interpolation rate %i" % (interp,))
-
-        self._interp = interp
-        self._eth_rate = self._dac_rate/self._interp
-        if self._verbose:
-            print "USRP2 interpolation rate:", self._interp
-            print "USRP2 IF bandwidth: %sHz" % (n2s(self._eth_rate),)
-
-        if (self._type == gr.GR_SIN_WAVE or 
-            self._type == gr.GR_CONST_WAVE):
-            self._src.set_sampling_freq(self._eth_rate)
-        elif self._type == "2tone":
-            self._src1.set_sampling_freq(self._eth_rate)
-            self._src1.set_sampling_freq(self._eth_rate)
-        elif self._type == "sweep":
-            self._src1.set_sampling_freq(self._eth_rate)
-            self._src1.set_sampling_freq(self._waveform_freq*2*math.pi/self._eth_rate)
-        else:
-            return True # Waveform not yet set
-        
-        if self._verbose: print "Set interpolation rate to:", interp
-        return True
-
-    def set_gain(self, gain):
-        if gain is None:
-            g = self._u.gain_range()
-            gain = float(g[0]+g[1])/2
-            if self._verbose:
-                print "Using auto-calculated mid-point TX gain"
-        self._u.set_gain(gain)
-        self._gain = gain
-        if self._verbose:
-            print "Set TX gain to:", self._gain
-
-    def set_freq(self, target_freq, lo_offset=None):
-        if lo_offset is not None:
-            self._lo_offset = lo_offset
-            self._u.set_lo_offset(self._lo_offset)
-            if self._verbose:
-                print "Set LO offset frequency to: %sHz" % (n2s(lo_offset),)
-
-        if target_freq is None:
-            f = self._u.freq_range()
-            target_freq = float(f[0]+f[1])/2.0
-            if self._verbose:
-                print "Using auto-calculated mid-point frequency"
-
-        tr = self._u.set_center_freq(target_freq)
-        fs = "%sHz" % (n2s(target_freq),)
-        if tr is not None:
-            self._freq = target_freq
-
-        else:
-            return True # Waveform not yet set
-        
-        if self._verbose: print "Set amplitude to:", amplitude
-        return True
-
-    def set_gain(self, gain):
-        if gain is None:
-            g = self._u.gain_range()
-            gain = float(g[0]+g[1])/2
-            if self._verbose:
-                print "Using auto-calculated mid-point TX gain"
-        self._u.set_gain(gain)
-        self._gain = gain
-        if self._verbose:
-            print "Set TX gain to:", self._gain
-
-    def set_freq(self, target_freq, lo_offset=None):
-        if lo_offset is not None:
-            self._lo_offset = lo_offset
-            self._u.set_lo_offset(self._lo_offset)
-            if self._verbose:
-                print "Set LO offset frequency to: %sHz" % (n2s(lo_offset),)
-
-        if target_freq is None:
-            f = self._u.freq_range()
-            target_freq = float(f[0]+f[1])/2.0
-            if self._verbose:
-                print "Using auto-calculated mid-point frequency"
-
-        tr = self._u.set_center_freq(target_freq)
-        fs = "%sHz" % (n2s(target_freq),)
-        if tr is not None:
-            self._freq = target_freq
-            self._ddc_freq = tr.dxc_freq
-            self._bb_freq = tr.baseband_freq
-            if self._verbose:
-                print "Set center frequency to", fs
-                print "Tx baseband frequency: %sHz" % (n2s(tr.baseband_freq),)
-                print "Tx DDC frequency: %sHz" % (n2s(tr.dxc_freq),)
-                print "Tx residual frequency: %sHz" % (n2s(tr.residual_freq),)
-                
-        return tr
-
-    def set_waveform_freq(self, freq):
-        self._waveform_freq = freq
-        if self._type == gr.GR_SIN_WAVE:
-            self._src.set_frequency(freq)
-        elif self._type == "2tone" or self._type == "sweep":
-            self._src1.set_frequency(freq)
-        return True
-
-    def set_waveform2_freq(self, freq):
-        self._waveform2_freq = freq
-        if self._type == "2tone":
-            self._src2.set_frequency(freq)
-        elif self._type == "sweep":
-            self._src1.set_frequency(freq)
-        return True
-
-    def set_waveform(self, type):
-        self.lock()
-        self.disconnect_all()
-
-        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
-            self._src = gr.sig_source_c(self._eth_rate,      # Sample rate
-                                        type,                # Waveform type
-                                        self._waveform_freq, # Waveform frequency
-                                        self._amplitude,     # Waveform amplitude
-                                        self._offset)        # Waveform offset
-        elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
-            self._src = gr.noise_source_c(type, self._amplitude)
-        elif type == "2tone":
-            self._src1 = gr.sig_source_c(self._eth_rate,
-                                         gr.GR_SIN_WAVE,
-                                         self._waveform_freq,
-                                         self._amplitude/2.0,
-                                         0)
-            if(self._waveform2_freq is None):
-                self._waveform2_freq = -self._waveform_freq
-
-            self._src2 = gr.sig_source_c(self._eth_rate,
-                                         gr.GR_SIN_WAVE,
-                                         self._waveform2_freq,
-                                         self._amplitude/2.0,
-                                         0)
-            self._src = gr.add_cc()
-            self.connect(self._src1,(self._src,0))
-            self.connect(self._src2,(self._src,1))
-        elif type == "sweep":
-            # rf freq is center frequency
-            # waveform_freq is total swept width
-            # waveform2_freq is sweep rate
-            # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
-            if self._waveform2_freq is None:
-                self._waveform2_freq = 0.1
-
-            self._src1 = gr.sig_source_f(self._eth_rate,
-                                         gr.GR_TRI_WAVE,
-                                         self._waveform2_freq,
-                                         1.0,
-                                         -0.5)
-            self._src2 = gr.frequency_modulator_fc(self._waveform_freq*2*math.pi/self._eth_rate)
-            self._src = gr.multiply_const_cc(self._amplitude)
-            self.connect(self._src1,self._src2,self._src)
-        else:
-            raise RuntimeError("Unknown waveform type")
-
-        self.connect(self._src, self._u)
-        self._type = type
-        self.unlock()
-
-        if self._verbose:
-            print "Set baseband modulation to:", waveforms[self._type]
-            if type == gr.GR_SIN_WAVE:
-                print "Modulation frequency: %sHz" % (n2s(self._waveform_freq),)
-                print "Initial phase:", self._offset
-            elif type == "2tone":
-                print "Tone 1: %sHz" % (n2s(self._waveform_freq),)
-                print "Tone 2: %sHz" % (n2s(self._waveform2_freq),)
-            elif type == "sweep":
-                print "Sweeping across %sHz to %sHz" % (n2s(-self._waveform_freq/2.0),n2s(self._waveform_freq/2.0))
-                print "Sweep rate: %sHz" % (n2s(self._waveform2_freq),)
-            print "TX amplitude:", self._amplitude
-
-
-    def set_amplitude(self, amplitude):
-        if amplitude < 0.0 or amplitude > 1.0:
-            if self._verbose: print "Amplitude out of range:", amplitude
-            return False
-
-        self._amplitude = amplitude
-
-        if (self._type == gr.GR_SIN_WAVE or 
-            self._type == gr.GR_CONST_WAVE or
-            self._type == gr.GR_GAUSSIAN or
-            self._type == gr.GR_UNIFORM):
-            self._src.set_amplitude(amplitude)
-        elif self._type == "2tone":
-            self._src1.set_amplitude(amplitude/2.0)
-            self._src2.set_amplitude(amplitude/2.0)
-        elif self._type == "sweep":
-            self._src.set_k(amplitude)
-        else:
-            return True # Waveform not yet set
-        
-        if self._verbose: print "Set amplitude to:", amplitude
-        return True
-
-
-    # Property getters
-
-    def mac_addr(self):
-        return self._u.mac_addr()
-
-    def interface_name(self):
-        return self._u.interface_name()
-
-    def daughterboard_id(self):
-        return self._u.daughterboard_id()
-
-    def interp_rate(self):
-        return self._interp
-
-    def eth_rate(self):
-        return self._eth_rate
-
-    def freq(self):
-        return self._freq
-
-    def freq_range(self):
-        return self._u.freq_range()
-
-    def ddc_freq(self):
-        return self._ddc_freq
-
-    def baseband_freq(self):
-        return self._bb_freq
-
-    def amplitude(self):
-        return self._amplitude
-
-    def waveform_type(self):
-        return self._type
-
-    def waveform_freq(self):
-        return self._waveform_freq
-
-    def waveform2_freq(self):
-        if self._waveform2_freq is None:
-            return -self._waveform_freq
-        else:
-            return self._waveform2_freq
-
-def get_options():
-    usage="%prog: [options]"
-
-    parser = OptionParser(option_class=eng_option, usage=usage)
-
-    parser.add_option("-e", "--interface", type="string", default="eth0",
-                      help="Use specified Ethernet interface [default=%default]")
-    parser.add_option("-m", "--mac-addr", type="string", default="",
-                      help="Use USRP2 at specified MAC address [default=None]")  
-    parser.add_option("-i", "--interp", type="int", default=16, metavar="INTERP",
-                      help="Set FPGA interpolation rate of INTERP [default=%default]")
-    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("--lo-offset", type="eng_float", default=None,
-                      help="set daughterboard LO offset to OFFSET [default=hw default]")
-    parser.add_option("-g", "--gain", type="eng_float", default=None,
-                      help="Set TX gain to GAIN [default=mid-point]")
-    parser.add_option("-w", "--waveform-freq", type="eng_float", default=0,
-                      help="Set baseband waveform frequency to FREQ [default=%default]")
-    parser.add_option("-x", "--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=gr.GR_SIN_WAVE,
-                      help="Generate a carrier modulated by a complex sine wave", default=gr.GR_SIN_WAVE)
-    parser.add_option("--const", dest="type", action="store_const", const=gr.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=gr.GR_GAUSSIAN,
-                      help="Generate Gaussian random output")
-    parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
-                      help="Generate Uniform random output")
-    parser.add_option("--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",
-                      help="Generate a swept sine wave")
-    parser.add_option("-a", "--amplitude", type="eng_float", default=0.1,
-                      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]")
-
-    (options, args) = parser.parse_args()
-
-    return (options, args)
-
-# If this script is executed, the following runs. If it is imported, the below does not run.
-if __name__ == "__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) = get_options()
-        tb = top_block(options, args)
-
-    except RuntimeError, e:
-        print e
-        sys.exit(1)
-
-    # Run it
-    try:
-        tb.run()
-
-    except KeyboardInterrupt:
-        pass
diff --git a/gr-utils/src/python/usrp2_siggen_gui.py b/gr-utils/src/python/usrp2_siggen_gui.py
deleted file mode 100755
index 89bc6e5894..0000000000
--- a/gr-utils/src/python/usrp2_siggen_gui.py
+++ /dev/null
@@ -1,275 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009 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.
-# 
-
-import wx
-from gnuradio.wxgui import form, slider, gui
-import usrp2_siggen
-import sys, math
-
-class app_gui(object):
-    def __init__(self, frame, panel, vbox, top_block, options, args):
-        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
-
-        freq_range = self.tb.freq_range()
-        self.min_freq = freq_range[0]
-        self.max_freq = freq_range[1]
-        self.freq_step = (self.max_freq-self.min_freq)/100.0
-        self._types = dict([v, k] for k, v in usrp2_siggen.waveforms.items())
-
-        self.build_gui()
-
-        # TODO: turn these into listeners
-        self.myform['ifc'].set_value(self.tb.interface_name())
-        self.myform['mac'].set_value(self.tb.mac_addr())
-        dbid = self.tb.daughterboard_id()
-        self.myform['dbid'].set_value("%04x" % (dbid,))
-
-        w = usrp2_siggen.waveforms[self.tb.waveform_type()]
-        self.myform['type'].set_value(w)
-        self.myform['w1freq'].set_value(self.tb.waveform_freq())
-        self.myform['w2freq'].set_value(self.tb.waveform2_freq())
-
-        freq = self.tb.freq()
-        if freq is None:
-            self.evt_set_status_msg("Failed to set initial frequency")
-        else:
-            self.myform['freq'].set_value(freq)
-            self.myform['freq_slider'].set_value(self.tb.freq())
-
-        amp = self.tb.amplitude()
-        if (amp > 0.0):
-            db = 20*math.log10(amp)
-        else:
-            db = -100.0
-        self.myform['amp'].set_value(amp)
-        self.myform['amp_slider'].set_value(db)
-        self.myform['eth'].set_value(self.tb.eth_rate())
-        self.myform['gbe'].set_value(self.tb.eth_rate()*32)
-        self.myform['interp'].set_value(self.tb.interp_rate())
-        self.myform['DDC'].set_value(self.tb.ddc_freq())
-        self.myform['analog'].set_value(self.tb.baseband_freq())
-
-    # Event response handlers
-    def evt_set_status_msg(self, msg):
-        self.frame.SetStatusText(msg, 0)
-
-    def evt_set_freq1(self, kv):
-        return self.tb.set_waveform_freq(kv['w1freq'])
-
-    def evt_set_freq2(self, kv):
-        return self.tb.set_waveform2_freq(kv['w2freq'])
-
-    def evt_set_freq(self, kv):
-        if type(kv) == type(0.0):              # Set from slider
-            tr = self.tb.set_freq(kv)
-            if tr is not None:
-                self.myform['freq'].set_value(kv)
-        else:                                  # Set from edit box
-            f = kv['freq']
-            tr = self.tb.set_freq(f)
-            if tr is not None:
-                self.myform['freq_slider'].set_value(f)
-
-        if tr is not None:
-            self.myform['DDC'].set_value(tr.dxc_freq)
-            self.myform['analog'].set_value(tr.baseband_freq)
-
-        return (tr is not None)
-
-    def evt_set_amplitude(self, kv):
-        if type(kv) == type(0.0):              # Set from slider
-            amp = math.pow(10, kv/20.0)
-            self.myform['amp'].set_value(amp)
-            return self.tb.set_amplitude(amp)
-        else:                                  # Set from edit box
-            amp = kv['amp']
-            if amp < 0.0 or amp > 1.0:
-                return False
-            if amp == 0.0:
-                db = -100.0
-            else:
-                db = 20*math.log10(amp)
-            self.myform['amp_slider'].set_value(db)
-            return self.tb.set_amplitude(amp)
-
-    def evt_set_interp(self):
-        interp = self.myform['interp'].get_value()
-        if self.tb.set_interp(interp):
-            eth_rate = self.tb.eth_rate()
-            self.myform['eth'].set_value(eth_rate)
-            self.myform['gbe'].set_value(eth_rate*32)
-            return True
-        return False
-
-    def evt_set_waveform_type(self, type):
-        # TODO: update frequency labels
-        return self.tb.set_waveform(self._types[type])
-
-    # GUI construction
-    def build_gui(self):
-        self.myform = myform = form.form()
-
-        # Baseband controls
-        bb_sbox = wx.StaticBox(parent=self.panel, label="Baseband Modulation")
-        bb_vbox = wx.StaticBoxSizer(bb_sbox, wx.VERTICAL) # Holds all baseband controls as unit
-
-        # First row of baseband controls (modulation type)
-        mod_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        mod_hbox.Add((10,0), 0, 0)
-        myform['type'] = form.radiobox_field(
-            parent=self.panel, label="Type", sizer=mod_hbox, value=None,
-            callback=self.evt_set_waveform_type, weight=1, major_dimension=0,
-            choices=usrp2_siggen.waveforms.values() )
-        bb_vbox.Add((0,10), 0, 0)
-        bb_vbox.Add(mod_hbox, 0, wx.EXPAND)
-
-        # Second row of baseband controls (frequencies)
-        bbf_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        bbf_hbox.Add((10,0), 0, 0)
-        myform['w1freq'] = form.float_field(
-            parent=self.panel, sizer=bbf_hbox, label="Frequency 1 (Hz)", weight=1,
-            callback=myform.check_input_and_call(self.evt_set_freq1, self.evt_set_status_msg) )
-        bbf_hbox.Add((10,0), 0, 0)
-        myform['w2freq'] = form.float_field(
-            parent=self.panel, sizer=bbf_hbox, label="Frequency 2 (Hz)", weight=1,
-            callback=myform.check_input_and_call(self.evt_set_freq2, self.evt_set_status_msg) )
-        bbf_hbox.Add((10,0), 0, 0)
-        
-        bb_vbox.Add((0,10), 0, 0)
-        bb_vbox.Add(bbf_hbox, 0, wx.EXPAND)
-
-        # Add baseband controls to top window sizer
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(bb_vbox, 0, wx.EXPAND)
-
-        # Frequency controls
-        fc_sbox = wx.StaticBox(parent=self.panel, label="Center Frequency")
-        fc_vbox = wx.StaticBoxSizer(fc_sbox, wx.VERTICAL) # Holds all frequency controls as unit
-
-        # First row of frequency controls (center frequency)
-        freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        freq_hbox.Add((10,0), 0, 0)
-        myform['freq'] = form.float_field(
-            parent=self.panel, sizer=freq_hbox, label=None, weight=1,
-            callback=myform.check_input_and_call(self.evt_set_freq, self.evt_set_status_msg) )
-        freq_hbox.Add((10,0), 0, 0)
-        myform['freq_slider'] = form.quantized_slider_field(
-            parent=self.panel, sizer=freq_hbox, label="Min-Max", weight=4,
-            range = (self.min_freq, self.max_freq, self.freq_step),
-            callback=self.evt_set_freq)
-        freq_hbox.Add((10,0), 0, 0)
-
-        fc_vbox.Add((10,0), 0, 0)
-        fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
-
-        # Second row of frequency controls (results)
-        tr_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        tr_hbox.Add((10,0), 0, 0)
-        myform['analog'] = form.static_float_field(
-            parent=self.panel, sizer=tr_hbox, label="Daughterboard: (Hz)", weight=1)
-        tr_hbox.Add((10,0), 0, 0)
-        myform['DDC'] = form.static_float_field(
-            parent=self.panel, sizer=tr_hbox, label="USRP2 DDC (Hz)", weight=1)
-        tr_hbox.Add((10,0), 0, 0)
-        fc_vbox.Add(tr_hbox, 0, wx.EXPAND)
-
-        # Add frequency controls to top window sizer
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(fc_vbox, 0, wx.EXPAND)
-
-        # Amplitude row
-        amp_sbox = wx.StaticBox(parent=self.panel, label="Amplitude")
-        amp_hbox = wx.StaticBoxSizer(amp_sbox, wx.HORIZONTAL)
-        amp_hbox.Add((10,0), 0, 0)
-        myform['amp'] = form.float_field(
-            parent=self.panel, sizer=amp_hbox, label="Linear\n(0.0-1.0)", weight=1,
-            callback=myform.check_input_and_call(self.evt_set_amplitude, self.evt_set_status_msg) )
-        amp_hbox.Add((10,0), 0, 0)
-        myform['amp_slider'] = form.quantized_slider_field(
-            parent=self.panel, sizer=amp_hbox, label="dB Full Scale\n(-100-0)", weight=4,
-            range=(-100.0, 0.0, 1), callback=self.evt_set_amplitude)
-        amp_hbox.Add((10,0), 0, 0)
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(amp_hbox, 0, wx.EXPAND)
-
-        # Sample rate row
-        sam_sbox = wx.StaticBox(parent=self.panel, label="Sample Rate")
-        sam_hbox = wx.StaticBoxSizer(sam_sbox, wx.HORIZONTAL)
-        sam_hbox.Add((10,0), 0, 0)
-        myform['interp'] = form.int_field(
-            parent=self.panel, sizer=sam_hbox, label="Interpolation", weight=1,
-            callback=self.evt_set_interp)
-        sam_hbox.Add((10,0), 0, 0)
-        myform['eth'] = form.static_float_field(
-            parent=self.panel, sizer=sam_hbox, label="Sample Rate (sps)", weight=1)
-        sam_hbox.Add((10,0), 0, 0)
-        myform['gbe'] = form.static_float_field(
-            parent=self.panel, sizer=sam_hbox, label="GbE Rate (bits/sec)", weight=1)
-        sam_hbox.Add((10,0), 0, 0)
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(sam_hbox, 0, wx.EXPAND)
-
-        # USRP2 row
-        u2_sbox = wx.StaticBox(parent=self.panel, label="USRP2 Hardware")
-        u2_hbox = wx.StaticBoxSizer(u2_sbox, wx.HORIZONTAL)
-        u2_hbox.Add((10,0), 0, 0)
-        myform['ifc'] = form.static_text_field(parent=self.panel, sizer=u2_hbox, 
-                                               label="Interface", weight=2)
-        u2_hbox.Add((10,0), 0, 0)
-        myform['mac'] = form.static_text_field(parent=self.panel, sizer=u2_hbox, 
-                                               label="MAC Address", weight=2)
-        u2_hbox.Add((10,0), 0, 0)
-        myform['dbid'] = form.static_text_field(parent=self.panel, sizer=u2_hbox, 
-                                                label="Daughterboard ID", weight=1)
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(u2_hbox, 0, wx.EXPAND)
-        self.vbox.Add((0,20), 0, 0)
-
-if __name__ == "__main__":
-    try:
-        # Get command line parameters
-        (options, args) = usrp2_siggen.get_options()
-
-        # Create the top block using these
-        tb = usrp2_siggen.top_block(options, args)
-
-        # 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="USRP2 Signal Generator",  # Top window title
-                      nstatus=1,                       # Number of status lines
-                      start=True,                      # Whether to start flowgraph
-                      realtime=True)                   # Whether to set realtime priority
-
-        # And run it
-        app.MainLoop()
-
-    except RuntimeError, e:
-        print e
-        sys.exit(1)
diff --git a/gr-utils/src/python/usrp_siggen.py b/gr-utils/src/python/usrp_siggen.py
index 8ae2fbfbfd..8ee8cfd2ad 100755
--- a/gr-utils/src/python/usrp_siggen.py
+++ b/gr-utils/src/python/usrp_siggen.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2004,2005,2007,2008 Free Software Foundation, Inc.
+# Copyright 2008,2009 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -20,200 +20,307 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, gru
-from gnuradio import usrp
+DESC_KEY = 'desc'
+SAMP_RATE_KEY = 'samp_rate'
+LINK_RATE_KEY = 'link_rate'
+DAC_RATE_KEY = 'dac_rate'
+INTERP_KEY = 'interp'
+GAIN_KEY = 'gain'
+TX_FREQ_KEY = 'tx_freq'
+DDC_FREQ_KEY = 'ddc_freq'
+BB_FREQ_KEY = 'bb_freq'
+AMPLITUDE_KEY = 'amplitude'
+AMPL_RANGE_KEY = 'ampl_range'
+WAVEFORM_FREQ_KEY = 'waveform_freq'
+WAVEFORM_OFFSET_KEY = 'waveform_offset'
+WAVEFORM2_FREQ_KEY = 'waveform2_freq'
+FREQ_RANGE_KEY = 'freq_range'
+GAIN_RANGE_KEY = 'gain_range'
+TYPE_KEY = 'type'
+
+def setter(ps, key, val): ps[key] = val
+
+from gnuradio import gr, eng_notation
+from gnuradio.gr.pubsub import pubsub
 from gnuradio.eng_option import eng_option
-from gnuradio import eng_notation
+from gnuradio import usrp_options
 from optparse import OptionParser
 import sys
+import math
 
+n2s = eng_notation.num_to_str
 
-class my_top_block(gr.top_block):
-    def __init__ (self, nsamples):
+waveforms = { gr.GR_SIN_WAVE   : "Complex Sinusoid",
+              gr.GR_CONST_WAVE : "Constant",
+              gr.GR_GAUSSIAN   : "Gaussian Noise",
+              gr.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):
         gr.top_block.__init__(self)
+        pubsub.__init__(self)
+        self._verbose = options.verbose
+        #initialize values from options
+        self._setup_usrpx(options)
+        self.subscribe(INTERP_KEY, lambda i: setter(self, SAMP_RATE_KEY, self[DAC_RATE_KEY]/i))
+        self.subscribe(SAMP_RATE_KEY, lambda e: setter(self, LINK_RATE_KEY, e*32))
+        self[INTERP_KEY] = options.interp or 16
+        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
+        self[BB_FREQ_KEY] = 0
+        self[DDC_FREQ_KEY] = 0
+        #subscribe set methods
+        self.subscribe(INTERP_KEY, self.set_interp)
+        self.subscribe(GAIN_KEY, self.set_gain)
+        self.subscribe(TX_FREQ_KEY, self.set_freq)
+        self.subscribe(AMPLITUDE_KEY, self.set_amplitude)
+        self.subscribe(WAVEFORM_FREQ_KEY, self.set_waveform_freq)
+        self.subscribe(WAVEFORM2_FREQ_KEY, self.set_waveform2_freq)
+        self.subscribe(TYPE_KEY, self.set_waveform)
+        #force update on pubsub keys
+        for key in (INTERP_KEY, GAIN_KEY, TX_FREQ_KEY,
+            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 = usrp_options.create_usrp_sink(options)
+        self.publish(DESC_KEY, lambda: str(self._u))
+        self.publish(DAC_RATE_KEY, self._u.dac_rate)
+        self.publish(FREQ_RANGE_KEY, self._u.freq_range)
+        self.publish(GAIN_RANGE_KEY, self._u.gain_range)
+        self.publish(GAIN_KEY, self._u.gain)
+        if self._verbose: print str(self._u)
+
+    def _set_tx_amplitude(self, ampl):
+        """
+        Sets the transmit amplitude sent to the USRP
+        @param ampl the amplitude or None for automatic
+        """
+        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_interp(self, interp):
+        if not self._u.set_interp(interp):
+            raise RuntimeError("Failed to set interpolation rate %i" % (interp,))
+
+        if self._verbose:
+            print "USRP interpolation rate:", interp
+            print "USRP IF bandwidth: %sHz" % (n2s(self[SAMP_RATE_KEY]),)
+
+        if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE):
+            self._src.set_sampling_freq(self[SAMP_RATE_KEY])
+        elif self[TYPE_KEY] == "2tone":
+            self._src1.set_sampling_freq(self[SAMP_RATE_KEY])
+            self._src2.set_sampling_freq(self[SAMP_RATE_KEY])
+        elif self[TYPE_KEY] == "sweep":
+            self._src1.set_sampling_freq(self[SAMP_RATE_KEY])
+            self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
+        else:
+            return True # Waveform not yet set
         
-        # controllable values
-        self.interp = 64
-        self.waveform_type = gr.GR_SIN_WAVE
-        self.waveform_ampl = 16000
-        self.waveform_freq = 100.12345e3
-        self.waveform_offset = 0
-        self.nsamples = nsamples
-        self._instantiate_blocks ()
-        self.set_waveform_type (self.waveform_type)
-
-    def usb_freq (self):
-        return self.u.dac_freq() / self.interp
-
-    def usb_throughput (self):
-        return self.usb_freq () * 4
-        
-    def set_waveform_type (self, type):
-        '''
-        valid waveform types are: gr.GR_SIN_WAVE, gr.GR_CONST_WAVE,
-        gr.GR_UNIFORM and gr.GR_GAUSSIAN
-        '''
-        self._configure_graph (type)
-        self.waveform_type = type
-
-    def set_waveform_ampl (self, ampl):
-        self.waveform_ampl = ampl
-        self.siggen.set_amplitude (ampl)
-        self.noisegen.set_amplitude (ampl)
-
-    def set_waveform_freq (self, freq):
-        self.waveform_freq = freq
-        self.siggen.set_frequency (freq)
-        
-    def set_waveform_offset (self, offset):
-        self.waveform_offset = offset
-        self.siggen.set_offset (offset)
-
-    def set_interpolator (self, interp):
-        self.interp = interp
-        self.siggen.set_sampling_freq (self.usb_freq ())
-        self.u.set_interp_rate (interp)
-
-    def _instantiate_blocks (self):
-        self.src = None
-        self.u = usrp.sink_c (0, self.interp)
-        
-        self.siggen = gr.sig_source_c (self.usb_freq (),
-                                       gr.GR_SIN_WAVE,
-                                       self.waveform_freq,
-                                       self.waveform_ampl,
-                                       self.waveform_offset)
-
-        self.noisegen = gr.noise_source_c (gr.GR_UNIFORM,
-                                           self.waveform_ampl)
-
-        self.head = None
-        if self.nsamples > 0:
-            self.head = gr.head(gr.sizeof_gr_complex, int(self.nsamples))
-
-        # self.file_sink = gr.file_sink (gr.sizeof_gr_complex, "siggen.dat")
-
-    def _configure_graph (self, type):
-        try:
-            self.lock()
-            self.disconnect_all ()
-
-            if self.head:
-                self.connect(self.head, self.u)
-                tail = self.head
-            else:
-                tail = self.u
-                
-            if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
-                self.connect (self.siggen, tail)
-                # self.connect (self.siggen, self.file_sink)
-                self.siggen.set_waveform (type)
-                self.src = self.siggen
-            elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN:
-                self.connect (self.noisegen, tail)
-                self.noisegen.set_type (type)
-                self.src = self.noisegen
-            else:
-                raise ValueError, type
-        finally:
-            self.unlock()
+        if self._verbose: print "Set interpolation rate to:", interp
+        return True
+
+    def set_gain(self, gain):
+        if gain is None:
+            g = self[GAIN_RANGE_KEY]
+            gain = float(g[0]+g[1])/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):
-        """
-        Set the center frequency we're interested in.
 
-        @param target_freq: frequency in Hz
-        @rypte: bool
-
-        Tuning is a two step process.  First we ask the front-end to
-        tune as close to the desired frequency as it can.  Then we use
-        the result of that operation and our target_frequency to
-        determine the value for the digital up converter.
-        """
-        r = self.u.tune(self.subdev.which(), self.subdev, target_freq)
-        if r:
-            #print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq)
-            #print "r.dxc_freq      =", eng_notation.num_to_str(r.dxc_freq)
-            #print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq)
-            #print "r.inverted      =", r.inverted
-            return True
-
-        return False
-
-
-
-def main ():
-    parser = OptionParser (option_class=eng_option)
-    parser.add_option ("-T", "--tx-subdev-spec", type="subdev", default=(0, 0),
-                       help="select USRP Tx side A or B")
-    parser.add_option ("-f", "--rf-freq", type="eng_float", default=None,
-                       help="set RF center frequency to FREQ")
-    parser.add_option ("-i", "--interp", type="int", default=64,
-                       help="set fgpa interpolation rate to INTERP [default=%default]")
-
-    parser.add_option ("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
-                       help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE)
-    parser.add_option ("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, 
-                       help="generate a constant output")
-    parser.add_option ("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
-                       help="generate Gaussian random output")
-    parser.add_option ("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
-                       help="generate Uniform random output")
-
-    parser.add_option ("-w", "--waveform-freq", type="eng_float", default=0,
-                       help="set waveform frequency to FREQ [default=%default]")
-    parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3,
-                       help="set waveform amplitude to AMPLITUDE [default=%default]", metavar="AMPL")
-    parser.add_option ("-g", "--gain", type="eng_float", default=None,
-                       help="set output gain to GAIN [default=%default]")
-    parser.add_option ("-o", "--offset", type="eng_float", default=0,
-                       help="set waveform offset to OFFSET [default=%default]")
-    parser.add_option ("-N", "--nsamples", type="eng_float", default=0,
-                       help="set number of samples to transmit [default=+inf]")
-    (options, args) = parser.parse_args ()
-
-    if len(args) != 0:
-        parser.print_help()
-        raise SystemExit
-
-    if options.rf_freq is None:
-        sys.stderr.write("usrp_siggen: must specify RF center frequency with -f RF_FREQ\n")
-        parser.print_help()
-        raise SystemExit
-
-    tb = my_top_block(options.nsamples)
-    tb.set_interpolator (options.interp)
-    tb.set_waveform_type (options.type)
-    tb.set_waveform_freq (options.waveform_freq)
-    tb.set_waveform_ampl (options.amplitude)
-    tb.set_waveform_offset (options.offset)
-
-    # determine the daughterboard subdevice we're using
-    if options.tx_subdev_spec is None:
-        options.tx_subdev_spec = usrp.pick_tx_subdevice(tb.u)
-
-    m = usrp.determine_tx_mux_value(tb.u, options.tx_subdev_spec)
-    #print "mux = %#04x" % (m,)
-    tb.u.set_mux(m)
-    tb.subdev = usrp.selected_subdev(tb.u, options.tx_subdev_spec)
-    print "Using TX d'board %s" % (tb.subdev.side_and_name(),)
-    
-    if options.gain is None:
-        tb.subdev.set_gain(tb.subdev.gain_range()[1])    # set max Tx gain
-    else:
-        tb.subdev.set_gain(options.gain)    # set max Tx gain
-
-    if not tb.set_freq(options.rf_freq):
-        sys.stderr.write('Failed to set RF frequency\n')
-        raise SystemExit
+        if target_freq is None:
+            f = self[FREQ_RANGE_KEY]
+            target_freq = float(f[0]+f[1])/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[DDC_FREQ_KEY] = tr.dxc_freq
+            self[BB_FREQ_KEY] = tr.baseband_freq
+            if self._verbose:
+                print "Set center frequency to", fs
+                print "Tx baseband frequency: %sHz" % (n2s(tr.baseband_freq),)
+                print "Tx DDC frequency: %sHz" % (n2s(tr.dxc_freq),)
+                print "Tx residual frequency: %sHz" % (n2s(tr.residual_freq),)
+        elif self._verbose: print "Failed to set freq." 
+        return tr
+
+    def set_waveform_freq(self, freq):
+        if self[TYPE_KEY] == gr.GR_SIN_WAVE:
+            self._src.set_frequency(freq)
+        elif self[TYPE_KEY] == "2tone":
+            self._src1.set_frequency(freq)
+        elif self[TYPE_KEY] == 'sweep':
+            #there is no set sensitivity, redo fg
+            self[TYPE_KEY] = self[TYPE_KEY]
+        return True
+
+    def set_waveform2_freq(self, freq):
+        if freq is None:
+            self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY]
+            return
+        if self[TYPE_KEY] == "2tone":
+            self._src2.set_frequency(freq)
+        elif self[TYPE_KEY] == "sweep":
+            self._src1.set_frequency(freq)
+        return True
+
+    def set_waveform(self, type):
+        self.lock()
+        self.disconnect_all()
+        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
+            self._src = gr.sig_source_c(self[SAMP_RATE_KEY],      # Sample rate
+                                        type,                # Waveform type
+                                        self[WAVEFORM_FREQ_KEY], # Waveform frequency
+                                        self[AMPLITUDE_KEY],     # Waveform amplitude
+                                        self[WAVEFORM_OFFSET_KEY])        # Waveform offset
+        elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
+            self._src = gr.noise_source_c(type, self[AMPLITUDE_KEY])
+        elif type == "2tone":
+            self._src1 = gr.sig_source_c(self[SAMP_RATE_KEY],
+                                         gr.GR_SIN_WAVE,
+                                         self[WAVEFORM_FREQ_KEY],
+                                         self[AMPLITUDE_KEY]/2.0,
+                                         0)
+            if(self[WAVEFORM2_FREQ_KEY] is None):
+                self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY]
+
+            self._src2 = gr.sig_source_c(self[SAMP_RATE_KEY],
+                                         gr.GR_SIN_WAVE,
+                                         self[WAVEFORM2_FREQ_KEY],
+                                         self[AMPLITUDE_KEY]/2.0,
+                                         0)
+            self._src = gr.add_cc()
+            self.connect(self._src1,(self._src,0))
+            self.connect(self._src2,(self._src,1))
+        elif type == "sweep":
+            # rf freq is center frequency
+            # waveform_freq is total swept width
+            # waveform2_freq is sweep rate
+            # 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 = gr.sig_source_f(self[SAMP_RATE_KEY],
+                                         gr.GR_TRI_WAVE,
+                                         self[WAVEFORM2_FREQ_KEY],
+                                         1.0,
+                                         -0.5)
+            self._src2 = gr.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
+            self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY])
+            self.connect(self._src1,self._src2,self._src)
+        else:
+            raise RuntimeError("Unknown waveform type")
+
+        self.connect(self._src, self._u)
+        self.unlock()
+
+        if self._verbose:
+            print "Set baseband modulation to:", waveforms[type]
+            if type == gr.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]
+
+
+    def set_amplitude(self, amplitude):
+        if amplitude < 0.0 or amplitude > 1.0:
+            if self._verbose: print "Amplitude out of range:", amplitude
+            return False
+
+        if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE, gr.GR_GAUSSIAN, gr.GR_UNIFORM):
+            self._src.set_amplitude(amplitude)
+        elif self[TYPE_KEY] == "2tone":
+            self._src1.set_amplitude(amplitude/2.0)
+            self._src2.set_amplitude(amplitude/2.0)
+        elif self[TYPE_KEY] == "sweep":
+            self._src.set_k(amplitude)
+        else:
+            return True # Waveform not yet set
+        
+        if self._verbose: print "Set amplitude to:", amplitude
+        return True
+
+def get_options():
+    usage="%prog: [options]"
+
+    parser = OptionParser(option_class=eng_option, usage=usage)
+    usrp_options.add_tx_options(parser)
+    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=gr.GR_SIN_WAVE,
+                      help="Generate a carrier modulated by a complex sine wave", default=gr.GR_SIN_WAVE)
+    parser.add_option("--const", dest="type", action="store_const", const=gr.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=gr.GR_GAUSSIAN,
+                      help="Generate Gaussian random output")
+    parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
+                      help="Generate Uniform random output")
+    parser.add_option("--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",
+                      help="Generate a swept sine wave")
+    parser.add_option("-A", "--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]")
+
+    (options, args) = parser.parse_args()
+
+    return (options, args)
+
+# If this script is executed, the following runs. If it is imported, the below does not run.
+if __name__ == "__main__":
+    if gr.enable_realtime_scheduling() != gr.RT_OK:
+        print "Note: failed to enable realtime scheduling, continuing"
     
-    tb.subdev.set_enable(True)                       # enable transmitter
+    # Grab command line options and create top block
+    try:
+        (options, args) = get_options()
+        tb = top_block(options, args)
 
+    except RuntimeError, e:
+        print e
+        sys.exit(1)
+
+    # Run it
     try:
         tb.run()
+
     except KeyboardInterrupt:
         pass
-
-
-if __name__ == '__main__':
-    main ()
diff --git a/gr-utils/src/python/usrp_siggen_gui.py b/gr-utils/src/python/usrp_siggen_gui.py
new file mode 100755
index 0000000000..5ac2369fb4
--- /dev/null
+++ b/gr-utils/src/python/usrp_siggen_gui.py
@@ -0,0 +1,310 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 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.
+# 
+
+import wx
+from gnuradio import gr
+from gnuradio.gr.pubsub import pubsub
+from gnuradio.wxgui import gui, forms
+import usrp_siggen
+import sys, math
+
+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()
+
+    # Event response handlers
+    def evt_set_status_msg(self, msg):
+        self.frame.SetStatusText(msg, 0)
+
+    # GUI construction
+    def build_gui(self):
+        self.vbox.AddSpacer(5)
+        self.vbox.AddStretchSpacer()
+        ##################################################
+        # Baseband 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 == gr.GR_SIN_WAVE)
+            sweep_bb_hbox.ShowItems(type == 'sweep')
+            tone_bb_hbox.ShowItems(type == '2tone')
+            self.vbox.Layout()
+        self.tb.subscribe(usrp_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=usrp_siggen.WAVEFORM_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        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=usrp_siggen.WAVEFORM_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        sweep_bb_hbox.AddStretchSpacer()
+        forms.text_box(
+            parent=self.panel, sizer=sweep_bb_hbox,
+            label='Sweep Rate (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM2_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        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=usrp_siggen.WAVEFORM_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        tone_bb_hbox.AddStretchSpacer()
+        forms.text_box(
+            parent=self.panel, sizer=tone_bb_hbox,
+            label='Tone 2 (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM2_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        tone_bb_hbox.AddStretchSpacer()
+        forms.radio_buttons(
+            parent=self.panel, sizer=bb_vbox,
+            choices=usrp_siggen.waveforms.keys(),
+            labels=usrp_siggen.waveforms.values(),
+            ps=self.tb,
+            key=usrp_siggen.TYPE_KEY,
+            style=wx.NO_BORDER | wx.RA_HORIZONTAL,
+        )
+        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[usrp_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=usrp_siggen.TX_FREQ_KEY,
+        )
+        freq_hbox.AddSpacer(10)
+        forms.slider(
+            parent=self.panel, sizer=freq_hbox,
+            proportion=2,
+            ps=self.tb,
+            key=usrp_siggen.TX_FREQ_KEY,
+            minimum=self.tb[usrp_siggen.FREQ_RANGE_KEY][0],
+            maximum=self.tb[usrp_siggen.FREQ_RANGE_KEY][1],
+            num_steps=100,
+        )
+        freq_hbox.AddSpacer(5)
+        tr_hbox.AddSpacer(5)
+        forms.static_text(
+            parent=self.panel, sizer=tr_hbox,
+            label='Daughterboard (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.BB_FREQ_KEY,
+            converter=forms.float_converter(),
+            proportion=1,
+        )
+        tr_hbox.AddSpacer(10)
+        forms.static_text(
+            parent=self.panel, sizer=tr_hbox,
+            label='USRP DDC (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.DDC_FREQ_KEY,
+            converter=forms.float_converter(),
+            proportion=1,
+        )
+        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=usrp_siggen.AMPLITUDE_KEY,
+            label="Level (0.0-1.0)",
+        )
+        lvl_hbox.AddSpacer(10)
+        forms.log_slider(
+            parent=self.panel, sizer=lvl_hbox,
+            proportion=2,
+            ps=self.tb,
+            key=usrp_siggen.AMPLITUDE_KEY,
+            min_exp=-5,
+            max_exp=0,
+            base=10,
+            step_size=1,
+        )
+        lvl_hbox.AddSpacer(5)
+        if self.tb[usrp_siggen.GAIN_RANGE_KEY][0] < self.tb[usrp_siggen.GAIN_RANGE_KEY][1]:
+            gain_hbox.AddSpacer(5)
+            forms.text_box(
+                parent=self.panel, sizer=gain_hbox,
+                proportion=1,
+                converter=forms.float_converter(),
+                ps=self.tb,
+                key=usrp_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=usrp_siggen.GAIN_KEY,
+                minimum=self.tb[usrp_siggen.GAIN_RANGE_KEY][0],
+                maximum=self.tb[usrp_siggen.GAIN_RANGE_KEY][1],
+                step_size=self.tb[usrp_siggen.GAIN_RANGE_KEY][2],
+            )
+            gain_hbox.AddSpacer(5)
+        ##################################################
+        # Sample Rate controls
+        ##################################################
+        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.AddSpacer(5)
+        forms.text_box(
+            parent=self.panel, sizer=sam_hbox,
+            converter=forms.int_converter(),
+            ps=self.tb,
+            key=usrp_siggen.INTERP_KEY,
+            label="Interpolation",
+        )
+        sam_hbox.AddStretchSpacer(20)
+        forms.static_text(
+            parent=self.panel, sizer=sam_hbox,
+            label='Sample Rate (sps)',
+            ps=self.tb,
+            key=usrp_siggen.SAMP_RATE_KEY,
+            converter=forms.float_converter(),
+        )
+        sam_hbox.AddStretchSpacer(20)
+        forms.static_text(
+            parent=self.panel, sizer=sam_hbox,
+            label='Link Rate (bits/sec)',
+            ps=self.tb,
+            key=usrp_siggen.LINK_RATE_KEY,
+            converter=forms.float_converter(),
+        )
+        sam_hbox.AddSpacer(5)
+        ##################################################
+        # USRP status
+        ##################################################
+        u2_hbox = forms.static_box_sizer(parent=self.panel, label="USRP Status", 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=usrp_siggen.DESC_KEY,
+            converter=forms.str_converter(),
+        )
+        self.vbox.AddSpacer(5)
+        self.vbox.AddStretchSpacer()
+
+if __name__ == "__main__":
+    try:
+        # Get command line parameters
+        (options, args) = usrp_siggen.get_options()
+
+        # Create the top block using these
+        tb = usrp_siggen.top_block(options, args)
+
+        # 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="USRP Signal Generator",  # Top window title
+                      nstatus=1,                       # Number of status lines
+                      start=True,                      # Whether to start flowgraph
+                      realtime=True)                   # Whether to set realtime priority
+
+        # And run it
+        app.MainLoop()
+
+    except RuntimeError, e:
+        print e
+        sys.exit(1)
-- 
cgit v1.2.3