commit-gnuradio
[Top][All Lists]
Advanced

[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)





reply via email to

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