[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r10726 - gnuradio/branches/features/experimental-gui
From: |
jblum |
Subject: |
[Commit-gnuradio] r10726 - gnuradio/branches/features/experimental-gui |
Date: |
Tue, 31 Mar 2009 19:01:28 -0600 (MDT) |
Author: jblum
Date: 2009-03-31 19:01:28 -0600 (Tue, 31 Mar 2009)
New Revision: 10726
Added:
gnuradio/branches/features/experimental-gui/forms.py
gnuradio/branches/features/experimental-gui/usrp2_siggen.py
gnuradio/branches/features/experimental-gui/usrp2_siggen_gui.py
Log:
Copied usrp2_siggen and gui for experimental work.
WIP for experimental pubsub-aware wx forms.
Work on checkbox, radio buttons, drop down, button, and notebook.
All forms are compadible with non-pubsub usage through optional
callback and set/get methods.
Added: gnuradio/branches/features/experimental-gui/forms.py
===================================================================
--- gnuradio/branches/features/experimental-gui/forms.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/forms.py 2009-04-01
01:01:28 UTC (rev 10726)
@@ -0,0 +1,256 @@
+#
+# 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.
+#
+
+PRI_FORM_KEY = 'pri_form'
+
+import wx
+from gnuradio.gr.pubsub import pubsub
+
+#NOTE not used yet in forms
+class LabelText(wx.StaticText):
+ """
+ Label text to give the wx plots a uniform look.
+ Get the default label text and set the font bold.
+ """
+ def __init__(self, parent, label):
+ wx.StaticText.__init__(self, parent, label=label)
+ font = self.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ self.SetFont(font)
+
+#NOTE used in button and drop_down
+class LabelBox(wx.BoxSizer):
+ def __init__(self, parent, label, widget, style=wx.HORIZONTAL):
+ wx.BoxSizer.__init__(self, style)
+ if style == wx.HORIZONTAL:
+ self.Add(wx.StaticText(parent, label=' %s '%label), 1,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+ self.Add(widget, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_RIGHT)
+ if style == wx.VERTICAL:
+ self.Add(wx.StaticText(parent, label=' %s '%label), 1,
wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_TOP)
+ self.Add(widget, 0, wx.ALIGN_CENTER_HORIZONTAL |
wx.ALIGN_BOTTOM)
+
+########################################################################
+# Base Class Form
+########################################################################
+class _form_base(pubsub, wx.BoxSizer):
+ def __init__(self, parent=None, sizer=None, weight=0, ps=None, key='',
value=None, callback=None):
+ pubsub.__init__(self)
+ wx.BoxSizer.__init__(self, wx.VERTICAL)
+ self._parent = parent
+ #add to the sizer if provided
+ if sizer: sizer.Add(self, weight, wx.EXPAND)
+ #proxy the pubsub and key into this form
+ if ps is not None:
+ assert key
+ self.proxy(PRI_FORM_KEY, ps, key)
+ #no pubsub passed, must set initial value
+ else: self.set_value(value)
+ #subscribe callbacks for changes
+ self.subscribe(PRI_FORM_KEY, self._update)
+ if callback: self.subscribe(PRI_FORM_KEY, callback)
+
+ #override in subclasses to update the gui form
+ def _update(self, value): pass
+
+ #provide a set/get interface for this form
+ def get_value(self): return self[PRI_FORM_KEY]
+ def set_value(self, value): self[PRI_FORM_KEY] = value
+
+#TODO slider base class, log slider, linear slider, float & int types
+#TODO text box base class, eng notation, float, int, other
+#TODO static text display, float, int, other
+
+########################################################################
+# Check Box Form
+########################################################################
+class check_box(_form_base):
+ def __init__(self, label='', **kwargs):
+ _form_base.__init__(self, **kwargs)
+ self._check_box = wx.CheckBox(self._parent,
style=wx.CHK_2STATE, label=label)
+ self.Add(self._check_box, 0, wx.ALIGN_CENTER)
+ self._check_box.Bind(wx.EVT_CHECKBOX, self._handle)
+ self.set_value(self.get_value())
+
+ def _handle(self, event):
+ self[PRI_FORM_KEY] = bool(self._check_box.IsChecked())
+
+ def _update(self, value):
+ self._check_box.SetValue(bool(value))
+
+########################################################################
+# Base Class Chooser Form
+########################################################################
+class _chooser_base(_form_base):
+ def __init__(self, choices=[], labels=None, **kwargs):
+ _form_base.__init__(self, **kwargs)
+ self._choices = choices
+ self._labels = map(str, labels or choices)
+
+########################################################################
+# Drop Down Chooser Form
+########################################################################
+class drop_down(_chooser_base):
+ def __init__(self, label='', **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ self._drop_down = wx.Choice(self._parent, choices=self._labels)
+ self.Add(LabelBox(self._parent, label, self._drop_down), 0,
wx.ALIGN_CENTER)
+ self._drop_down.Bind(wx.EVT_CHOICE, self._handle)
+ self.set_value(self.get_value())
+
+ def _handle(self, event):
+ self[PRI_FORM_KEY] =
self._choices[self._drop_down.GetSelection()]
+
+ def _update(self, value):
+ try: self._drop_down.SetSelection(self._choices.index(value))
+ except ValueError: pass
+
+########################################################################
+# Button Chooser Form
+# Circularly move through the choices with each click.
+# Can be a single-click button with one choice.
+# Can be a 2-state button with two choices.
+########################################################################
+class button(_chooser_base):
+ def __init__(self, label='', **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ self._button = wx.Button(self._parent)
+ self.Add(LabelBox(self._parent, label, self._button), 0,
wx.ALIGN_CENTER)
+ self._button.Bind(wx.EVT_BUTTON, self._handle)
+ self.set_value(self.get_value())
+
+ def _handle(self, event):
+ self._index = (self._index + 1)%len(self._choices) #circularly
increment index
+ self[PRI_FORM_KEY] = self._choices[self._index]
+
+ def _update(self, value):
+ try:
+ self._index = self._choices.index(value)
+ self._button.SetLabel(self._labels[self._index])
+ except ValueError: pass
+
+########################################################################
+# Radio Buttons Chooser Form
+########################################################################
+class radio_buttons(_chooser_base):
+ def __init__(self, style=wx.VERTICAL, label='', **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ #compute the style
+ if style == wx.HORIZONTAL: style = wx.RA_HORIZONTAL
+ if style == wx.VERTICAL: style = wx.RA_VERTICAL
+ #create radio buttons
+ self._radio_buttons = wx.RadioBox(self._parent,
choices=self._labels, style=style, label=label)
+ self.Add(self._radio_buttons, 0, wx.ALIGN_CENTER)
+ self._radio_buttons.Bind(wx.EVT_RADIOBOX, self._handle)
+ self.set_value(self.get_value())
+
+ def _handle(self, event):
+ self[PRI_FORM_KEY] =
self._choices[self._radio_buttons.GetSelection()]
+
+ def _update(self, value):
+ try:
self._radio_buttons.SetSelection(self._choices.index(value))
+ except ValueError: pass
+
+########################################################################
+# Notebook Chooser Form
+# The notebook pages/tabs are for selecting between choices.
+# A page must be added to the notebook for each choice.
+########################################################################
+class notebook(_chooser_base):
+ def __init__(self, **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ self._notebook = wx.Notebook(self._parent)
+ self.Add(self._notebook, 0, wx.ALIGN_CENTER)
+ self._notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._handle)
+
+ #get at the real notebook object for adding pages and such
+ def get_notebook(self): return self._notebook
+
+ def _handle(self, event):
+ self[PRI_FORM_KEY] =
self._choices[self._notebook.GetSelection()]
+
+ def _update(self, value):
+ try: self._notebook.SetSelection(self._choices.index(value))
+ except ValueError: pass
+
+# ----------------------------------------------------------------
+# Stand-alone test application
+# ----------------------------------------------------------------
+
+import wx
+from gnuradio.wxgui import gui
+
+class app_gui (object):
+ def __init__(self, frame, panel, vbox, top_block, options, args):
+
+ def callback(v): print v
+
+ radio_buttons(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ labels=['two', 'four', 'eight', 'sixteen'],
+ value=4,
+ style=wx.VERTICAL,
+ label='test radio long string',
+ )
+
+
+
+ button(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ labels=['two', 'four', 'eight', 'sixteen'],
+ value=16,
+ label='button value'
+ )
+
+
+ drop_down(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ value=2,
+ label='Choose One'
+ )
+ check_box(
+ sizer=vbox,
+ parent=panel,
+ value=False,
+ label='check me',
+ callback=callback,
+ )
+
+if __name__ == "__main__":
+ try:
+
+ # Create the GUI application
+ app = gui.app(
+ gui=app_gui, # User interface class
+ title="Test Forms", # Top window title
+ )
+
+ # And run it
+ app.MainLoop()
+
+ except RuntimeError, e:
+ print e
+ sys.exit(1)
Copied: gnuradio/branches/features/experimental-gui/usrp2_siggen.py (from rev
10722, gnuradio/trunk/gr-utils/src/python/usrp2_siggen.py)
===================================================================
--- gnuradio/branches/features/experimental-gui/usrp2_siggen.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/usrp2_siggen.py 2009-04-01
01:01:28 UTC (rev 10726)
@@ -0,0 +1,418 @@
+#!/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.
+#
+
+INTERFACE_KEY = 'interface'
+MAC_ADDR_KEY = 'mac_addr'
+INTERP_KEY = 'interp'
+GAIN_KEY = 'gain'
+TX_FREQ_KEY = 'tx_freq'
+LO_OFFSET_KEY = 'lo_offset'
+AMPLITUDE_KEY = 'amplitude'
+WAVEFROM_FREQ_KEY = 'waveform_freq'
+WAVEFROM2_FREQ_KEY = 'waveform2_freq'
+TYPE_KEY = 'type'
+
+from gnuradio import gr, eng_notation, usrp2
+from gnuradio.gr.pubsub import pubsub
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+import math
+
+class dummy_usrp2(gr.hier_block2):
+ def __init__(self, *args, **kwargs):
+ gr.hier_block2.__init__(self,
+ "dummy usrp2", gr.io_signature(1, 1, gr.sizeof_gr_complex),
gr.io_signature(0, 0, 0))
+ self.connect(self, gr.throttle(gr.sizeof_gr_complex, 50000),
gr.null_sink(gr.sizeof_gr_complex))
+ def dac_rate(self): return int(100e6)
+ def mac_addr(self): return 'ff:ff:ff:ff:ff'
+ def daughterboard_id(self): return -1
+ def set_center_freq(self, *args, **kwargs): pass
+ def set_interp(self, *args, **kwargs): return True
+ def gain_range(self, *args, **kwargs): return (0., 1.)
+ def set_gain(self, *args, **kwargs): return True
+ def freq_range(self, *args, **kwargs): return (-100e6, 1, 100e6)
+ def interface_name(self, *args, **kwargs): return 'eth-x'
+usrp2.sink_32fc = dummy_usrp2
+
+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, pubsub):
+ def __init__(self, options, args):
+ gr.top_block.__init__(self)
+ pubsub.__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
Copied: gnuradio/branches/features/experimental-gui/usrp2_siggen_gui.py (from
rev 10722, gnuradio/trunk/gr-utils/src/python/usrp2_siggen_gui.py)
===================================================================
--- gnuradio/branches/features/experimental-gui/usrp2_siggen_gui.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/usrp2_siggen_gui.py
2009-04-01 01:01:28 UTC (rev 10726)
@@ -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 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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r10726 - gnuradio/branches/features/experimental-gui,
jblum <=