diff options
Diffstat (limited to 'gr-utils')
-rw-r--r-- | gr-utils/src/python/Makefile.am | 5 | ||||
-rwxr-xr-x | gr-utils/src/python/usrp2_siggen.py | 439 | ||||
-rwxr-xr-x | gr-utils/src/python/usrp2_siggen_gui.py | 275 |
3 files changed, 599 insertions, 120 deletions
diff --git a/gr-utils/src/python/Makefile.am b/gr-utils/src/python/Makefile.am index 965f74c80..5eb2ae555 100644 --- a/gr-utils/src/python/Makefile.am +++ b/gr-utils/src/python/Makefile.am @@ -54,6 +54,7 @@ bin_SCRIPTS = \ usrp_test_loopback.py \ usrp2_fft.py \ usrp2_rx_cfile.py \ - usrp2_siggen.py - + usrp2_siggen.py \ + usrp2_siggen_gui.py + MOSTLYCLEANFILES = *~ *.pyc diff --git a/gr-utils/src/python/usrp2_siggen.py b/gr-utils/src/python/usrp2_siggen.py index 9cea2eff1..71f12cf4a 100755 --- a/gr-utils/src/python/usrp2_siggen.py +++ b/gr-utils/src/python/usrp2_siggen.py @@ -20,8 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, eng_notation -from gnuradio import usrp2 +from gnuradio import gr, eng_notation, usrp2 from gnuradio.eng_option import eng_option from optparse import OptionParser import sys @@ -29,165 +28,369 @@ import math n2s = eng_notation.num_to_str -class siggen_top_block(gr.top_block): - def __init__(self, options): +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._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,)) - # Create a USRP2 sink with the requested interpolation rate - self._u = usrp2.sink_32fc(options.interface, options.mac_addr) - self._u.set_interp(options.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),) - # Set the Tx daughterboard gain as requested - if options.gain is None: + 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() - options.gain = float(g[0]+g[1])/2 - self._u.set_gain(options.gain) + 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),) - # Tune the USRP2 FPGA and daughterboard to the requested center frequency - # and LO offset - if options.lo_offset is not None: - self._u.set_lo_offset(options.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(options.tx_freq) - if tr == None: - sys.stderr.write('Failed to set center frequency\n') - raise SystemExit, 1 + tr = self._u.set_center_freq(target_freq) + fs = "%sHz" % (n2s(target_freq),) + if tr is not None: + self._freq = target_freq - eth_rate = self._u.dac_rate()/self._u.interp() + else: + return True # Waveform not yet set - # Create a source for the requested waveform type - if options.type == gr.GR_SIN_WAVE or options.type == gr.GR_CONST_WAVE: - self._src = gr.sig_source_c(eth_rate, # Sample rate - options.type, # Waveform type - options.waveform_freq, # Waveform frequency - options.amplitude, # Waveform amplitude - options.offset) # Waveform offset - - elif options.type == gr.GR_GAUSSIAN or options.type == gr.GR_UNIFORM: - self._src = gr.noise_source_c(options.type, options.amplitude) - elif options.type == "2tone": - self._src1 = gr.sig_source_c(eth_rate, + 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, - options.waveform_freq, - options.amplitude, + self._waveform_freq, + self._amplitude/2.0, 0) - if(options.waveform2_freq is None): - w2freq = -options.waveform_freq - else: - w2freq = options.waveform2_freq - self._src2 = gr.sig_source_c(eth_rate, + 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, - w2freq, - options.amplitude, + 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 options.type == "sweep": + 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) - self._src1 = gr.sig_source_f(eth_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, - options.waveform2_freq, - 1.0, # options.waveform_freq, + self._waveform2_freq, + 1.0, -0.5) - self._src2 = gr.frequency_modulator_fc(options.waveform_freq*2*math.pi/eth_rate) - self._src = gr.multiply_const_cc(options.amplitude) + 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: - sys.stderr.write('Unknown waveform type\n') - raise SystemExit, 1 - - if options.verbose: - print "Network interface:", options.interface - print "USRP2 address:", self._u.mac_addr() - #print "Using TX d'board %s" % (self._u.tx_name(),) - print "Tx gain:", options.gain - print "Tx baseband frequency:", n2s(tr.baseband_freq), "Hz" - print "Tx DDC frequency:", n2s(tr.dxc_freq), "Hz" - print "Tx residual frequency:", n2s(tr.residual_freq), "Hz" - print "Tx interpolation rate:", options.interp - print "Tx GbE sample rate:", n2s(eth_rate), "samples/sec" - if options.type == gr.GR_SIN_WAVE: - print "Baseband waveform type: Sine wave" - print "Baseband waveform frequency:", n2s(options.waveform_freq), "Hz" - elif options.type == gr.GR_CONST_WAVE: - print "Baseband waveform type: Constant" - elif options.type == gr.GR_GAUSSIAN: - print "Baseband waveform type: Gaussian noise" - elif options.type == gr.GR_UNIFORM: - print "Baseband waveform type: Uniform noise" - - # Wire the flowgraph + 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 interface(self): + # return self._u.ifc_name() + + def mac_addr(self): + return self._u.mac_addr() + + def ifc_name(self): + return self._u.ifc_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): + fr = self._u.freq_range() + if self._u.daughterboard_id() == 0x0000: + fr = (-50e6, 50e6) # DEBUG + return fr + + 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]") + 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, - help="set fgpa decimation rate to DECIM [default=%default]") - parser.add_option("-g", "--gain", type="eng_float", default=None, - help="set output gain to GAIN [default=%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 frequency to FREQ", metavar="FREQ") - parser.add_option("-v", "--verbose", action="store_true", default=False, - help="verbose output") - parser.add_option("-w", "--waveform-freq", type="eng_float", default=0, - help="set waveform frequency to FREQ [default=%default]") - parser.add_option("-x", "--waveform2-freq", type="eng_float", default=None, - help="set waveform frequency to FREQ [default=%default]") - parser.add_option("-a", "--amplitude", type="eng_float", default=0.5, - help="set waveform amplitude to AMPLITUDE (0-1.0) [default=%default]", metavar="AMPL") - parser.add_option("--offset", type="eng_float", default=0, - help="set waveform offset to OFFSET [default=%default]") + 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 complex sinusoid [default]", default=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 output") + 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") + help="Generate Gaussian random output") parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM, - help="generate Uniform random output") + help="Generate Uniform random output") parser.add_option("--2tone", dest="type", action="store_const", const="2tone", - help="generate Two Tone signal for IMD testing") + 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") - - (options, args) = parser.parse_args () - if len(args) != 0: - parser.print_help() - raise SystemExit, 1 - - if options.tx_freq is None: - parser.print_help() - sys.stderr.write('You must specify the frequency with -f FREQ\n'); - raise SystemExit, 1 - - return options + 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() -if __name__ == '__main__': - options = get_options() - tb = siggen_top_block(options) + 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" - # Attempt to enable realtime scheduling - r = gr.enable_realtime_scheduling() - if r == gr.RT_OK: - realtime = True - else: - realtime = False - print "Note: failed to enable realtime scheduling" + # 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 new file mode 100755 index 000000000..2d9f4f4df --- /dev/null +++ b/gr-utils/src/python/usrp2_siggen_gui.py @@ -0,0 +1,275 @@ +#!/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 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.ifc_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) |