[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8813 - gnuradio/branches/features/experimental-gui
From: |
jcorgan |
Subject: |
[Commit-gnuradio] r8813 - gnuradio/branches/features/experimental-gui |
Date: |
Sun, 6 Jul 2008 15:42:50 -0600 (MDT) |
Author: jcorgan
Date: 2008-07-06 15:42:27 -0600 (Sun, 06 Jul 2008)
New Revision: 8813
Added:
gnuradio/branches/features/experimental-gui/README
gnuradio/branches/features/experimental-gui/fft_controller.py
gnuradio/branches/features/experimental-gui/fft_top_block.py
gnuradio/branches/features/experimental-gui/prop_val.py
gnuradio/branches/features/experimental-gui/simple_usrp.py
gnuradio/branches/features/experimental-gui/usrp_fft.py
Modified:
gnuradio/branches/features/experimental-gui/
Log:
Experimental property/value interface code with USRP FFT code
as a partial implementation. See README for details.
Property changes on: gnuradio/branches/features/experimental-gui
___________________________________________________________________
Name: svn:ignore
+ *.pyc
Added: gnuradio/branches/features/experimental-gui/README
===================================================================
--- gnuradio/branches/features/experimental-gui/README
(rev 0)
+++ gnuradio/branches/features/experimental-gui/README 2008-07-06 21:42:27 UTC
(rev 8813)
@@ -0,0 +1,37 @@
+Experimental code demonstrating the property value abstraction and layering
+of topblock/controller/GUI code.
+
+* fft_top_block.py:
+
+Pure GNU Radio flowgraph implementing FFT stream. Doesn't know anything
+about GUIs or application operation.
+
+* fft_controller.py:
+
+Application controller implementing property/value interface. Manipulates
+the top block in response to property changes/queries.
+
+* fft_gui.py: (Not yet written)
+
+Implements user interface. Doesn't know anything about GNU Radio, but
+simply queries, sets, or listens to properties on the controller.
+
+* usrp_fft.py:
+
+Top-level script. Implements command line parameters, instantiates
+top block, controller and GUI (not yet written).
+
+* prop_val.py:
+
+Implements the property/value interface.
+
+* simple_usrp.py:
+
+Utility class for simplifying USRP operation. May eventually make it into
+blks2.
+
+STATUS:
+
+Currently, the top block and controller are written, but the GUI is not. There
+is temporary code in usrp_fft.py to print a line to the screen every time the
+FFT frame is updated.
Added: gnuradio/branches/features/experimental-gui/fft_controller.py
===================================================================
--- gnuradio/branches/features/experimental-gui/fft_controller.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/fft_controller.py
2008-07-06 21:42:27 UTC (rev 8813)
@@ -0,0 +1,85 @@
+#
+# Copyright 2008 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.
+#
+
+"""!
+GNU Radio controller for FFT streamer. Implements property/value abstraction
+above fft_top_block.
+"""
+
+from prop_val import prop_val_interface
+import threading
+
+class fft_controller(prop_val_interface, threading.Thread):
+ def __init__(self, tb):
+ prop_val_interface.__init__(self)
+ threading.Thread.__init__(self)
+ self._tb = tb
+
+ # External control interface. These properties, when set by an external
+ # caller, result in the correct top block methods being invoked.
+ # These could be expanded to member functions to implement more advanced
+ # application logic, but here lambdas do the trick.
+
+ self.add_listener('decim', lambda x: self._tb.set_decim(x))
+ self.add_listener('gain', lambda x: self._tb.set_gain(x))
+ self.add_listener('freq', lambda x: self._tb.set_freq(x))
+ self.add_listener('avg_alpha', lambda x: self._tb.set_avg_alpha(x))
+ self.add_listener('average', lambda x: self._tb.set_average(x))
+
+ # TODO: set providers for various properties an external caller might
+ # like to know about here. Can be member functions or lambdas, and
+ # would make calls on the top block to retrieve info.
+ #
+ # self.set_provider('foo', lambda: return 'bar')
+ # self.set_provider('decim', lambda: return self._tb.decim())
+
+ # The controller is a thread
+ self.setDaemon(1)
+ self._keep_running = True
+
+ def on_init(self):
+ """
+ This method gets called by the external GUI or other code to start its
+ operation.
+ """
+ self._tb.start()
+ self.start()
+
+ def run(self):
+ """
+ The background thread of the controller simply reads FFT frames from
the
+ top block message queue and sets the 'fft' property to their string
representation.
+ External code can add one or more listeners to this property to receive
+ notification when an FFT frame comes in.
+ """
+ while self._keep_running:
+ msg = self._tb.queue().delete_head()
+ self['fft'] = msg.to_string()
+
+ def on_exit(self):
+ """
+ This method gets called to shutdown the controller. It lets the
background
+ thread exit (not strictly necessary as Python will do so after the
setDaemon(1)
+ call), then calls stop() and wait() on the top block.
+ """
+ self._keep_running = False
+ self._tb.stop()
+ self._tb.wait()
Added: gnuradio/branches/features/experimental-gui/fft_top_block.py
===================================================================
--- gnuradio/branches/features/experimental-gui/fft_top_block.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/fft_top_block.py
2008-07-06 21:42:27 UTC (rev 8813)
@@ -0,0 +1,108 @@
+#
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, blks2
+import simple_usrp
+
+class fft_top_block(gr.top_block):
+ """!
+ GNU Radio top block to create a stream of FFT frames at a particular
+ frame rate from a USRP. The frames are enqueued in a gr.msg_queue for
+ external retrieval.
+
+ Provides functions to dynamically set USRP decimation rate, daughterboard
+ gain, receive center frequency, and averaging.
+ """
+ def __init__(self,
+ fft_size=512,
+ frame_rate=30,
+ ref_scale=50,
+ which=0,
+ decim=16,
+ width_8=False,
+ no_hb=False,
+ subdev_spec=None,
+ gain=None,
+ freq=None,
+ antenna=None,
+ avg_alpha=0.1,
+ average=False):
+ """!
+ Create an fft_top_block.
+
+ @param fft_size Number of FFT bins (default is 512)
+ @param frame_rate Number of frames/sec to create (default is
30)
+ @param ref_scale Sets 0 dB input amplitude
+ @param which USRP # on USB bus (default is 0)
+ @param decim Receive sample rate decimation (default is
16)
+ @param width_8 Use 8-bit instead of 16-bit samples
(default is False)
+ @param no_hb Don't use half-band filter (default is
False)
+ @param subdev_spec Daughterboard selection (default is first
found)
+ @param gain Daughterboard RX gain (default is mid-range)
+ @param freq Daughterboard RX frequency (default is
mid-range)
+ @param antenna Daughterboard RX antenna (default is
board-default)
+ @param avg_alpha FFT averaging (over time) constant
[0.0-1.0] (default is 0.1)
+ @param average Whether to implement FFT averaging [True,
False] (default is False)
+ """
+
+ gr.top_block.__init__(self, "fft_top_block")
+
+ self._u = simple_usrp.source_c(which=which,
+ decim=decim,
+ width_8=width_8,
+ no_hb=no_hb,
+ subdev_spec=subdev_spec,
+ gain=gain,
+ freq=freq,
+ antenna=antenna)
+
+ self._fft = blks2.logpwrfft_c(sample_rate=self._u.sample_rate(),
+ fft_size=fft_size,
+ frame_rate=frame_rate,
+ ref_scale=ref_scale,
+ avg_alpha=avg_alpha,
+ average=average)
+
+ self._msgq = gr.msg_queue(2)
+ self._sink = gr.message_sink(gr.sizeof_float*fft_size, self._msgq, True)
+
+ self.connect(self._u, self._fft, self._sink)
+
+ # "Setters", which are called externally to affect flowgraph operation
+ def set_gain(self, gain):
+ return self._u.set_gain(gain)
+
+ def set_freq(self, freq):
+ return self._u.set_freq(freq)
+
+ def set_decim(self, decim):
+ self._u.set_decim(decim)
+ self._fft.set_sample_rate(self._u.sample_rate())
+
+ def set_avg_alpha(self, avg_alpha):
+ return self._fft.set_avg_alpha(avg_alpha)
+
+ def set_average(self, average):
+ return self._fft.set_average(average)
+
+ # Getters, which are called externally to get information about the
flowgraph
+ def queue(self):
+ return self._msgq
Added: gnuradio/branches/features/experimental-gui/prop_val.py
===================================================================
--- gnuradio/branches/features/experimental-gui/prop_val.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/prop_val.py 2008-07-06
21:42:27 UTC (rev 8813)
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+#
+# Copyright 2008 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.
+#
+
+"""!
+Abstract GNU Radio property/value dictionary with functional getters
+and setters.
+
+This is a proof of concept implementation, will likely change significantly.
+"""
+
+class property(object):
+ """
+ A property has a value that can be set or queried externally.
+ """
+
+ def __init__(self):
+ self._provider = (None, None)
+ self._listeners = [ ]
+ self._cache = None
+
+ def set_provider(self, handler, obj=None):
+ """
+ A property provider gets invoked whenever the property's value is
+ queried.
+
+ If the handler is an object method, 'obj' must be a reference
+ to the object. Otherwise, the handler is treated as a bare function.
+ """
+ self._provider = (handler, obj)
+
+ def add_listener(self, handler, obj=None):
+ """
+ A property listener gets invoked whenever the property's value is
+ set. A property may have multiple listeners.
+
+ If the handler is an object method, 'obj' must be a reference
+ to the object. Otherwise, the handler is treated as a bare function.
+ """
+ self._listeners.append((handler, obj))
+
+ def set(self, value):
+ """
+ In response to being set, the property will call a series of listeners
+ with the new value. If there is no provider for the property, the
+ value will be cached.
+ """
+ (handler, obj) = self._provider
+ if handler is None:
+ self._cache = value
+ if len(self._listeners) > 0:
+ for (handler, obj) in self._listeners:
+ if obj is not None:
+ handler(obj, value)
+ else:
+ handler(value)
+
+ def get(self):
+ """
+ In response to being queried, if there is a provider set for the
property,
+ it is invoked to retrieve the value. Otherwise, the cached value is
+ returned.
+ """
+ (handler, obj) = self._provider
+ if handler is not None:
+ if obj is not None:
+ return handler(obj)
+ else:
+ return handler()
+ else:
+ return self._cache
+
+class prop_val_interface(object):
+ """
+ The prop_val_interface mimics an automatic dictionary. Properties are set
+ or queried using Python dictionary syntax, and non-existent keys are
+ automatically generated.
+ """
+ def __init__(self):
+ self._props = { }
+
+ def _get_prop(self, key):
+ try:
+ p = self._props[key]
+ except KeyError:
+ p = property()
+ self._props[key] = p
+ return p
+
+ def __getitem__(self, key):
+ return self._get_prop(key).get()
+
+ def __setitem__(self, key, value):
+ self._get_prop(key).set(value)
+
+ def add_listener(self, key, handler, obj=None):
+ """
+ Invokes add_listener(...) on the selected property.
+ """
+ self._get_prop(key).add_listener(handler, obj)
+
+ def set_provider(self, key, handler, obj=None):
+ """
+ Invokes set_provider(...) on the selected property.
+ """
+ self._get_prop(key).set_provider(handler, obj)
Added: gnuradio/branches/features/experimental-gui/simple_usrp.py
===================================================================
--- gnuradio/branches/features/experimental-gui/simple_usrp.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/simple_usrp.py 2008-07-06
21:42:27 UTC (rev 8813)
@@ -0,0 +1,120 @@
+#
+# Copyright 2008 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.
+#
+
+"""!
+High-level interfaces to USRP, simplifying common operations.
+
+This is proof-of-concept code and will likely change in incompatible ways.
+"""
+
+from gnuradio import gr, usrp
+
+class source_c(gr.hier_block2):
+ def __init__(self,
+ which=0,
+ decim=16,
+ width_8=False,
+ no_hb=False,
+ subdev_spec=None,
+ gain=None,
+ freq=None,
+ antenna=None):
+ """!
+ Create a simple_usrp object supplying complex samples.
+
+ @param which USRP # on USB bus (default is 0)
+ @param decim Receive sample rate decimation (default is 16)
+ @param width_8 Use 8-bit instead of 16-bit samples (default is
False)
+ @param no_hb Don't use half-band filter (default is False)
+ @param subdev_spec Daughterboard selection (default is first found)
+ @param gain Daughterboard RX gain (default is mid-range)
+ @param freq Daughterboard RX frequency (default is
mid-range)
+ @param antenna Daughterboard RX antenna (default is
board-default)
+ """
+
+ gr.hier_block2.__init__(self, "simple_usrp.source_c",
+ gr.io_signature(0, 0, 0), #
Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) #
Output signature
+
+ self._setup_usrp(which, decim, width_8, no_hb)
+ self._setup_db(subdev_spec, gain, freq, antenna)
+ self.connect(self._u, self)
+
+ def _setup_usrp(self, which, decim, width_8, no_hb):
+ if no_hb or decim < 8:
+ self._fpga_filename = 'std_4rx_0tx.rbf'
+ else:
+ self._fpga_filename = 'std_2rxhb_2tx.rbf'
+
+ self._u = usrp.source_c(which=which,
+ fpga_filename=self._fpga_filename)
+
+ self.set_decim(decim)
+ if width_8:
+ format = self._u.make_format(8, 8)
+ self._u.set_format(format)
+
+ def _setup_db(self, subdev_spec, gain, freq, antenna):
+ if subdev_spec is None:
+ subdev_spec = usrp.pick_rx_subdevice(self._u)
+ self._u.set_mux(usrp.determine_rx_mux_value(self._u, subdev_spec))
+ self._subdev = usrp.selected_subdev(self._u, subdev_spec)
+ self.set_gain(gain)
+ self.set_freq(freq)
+ if antenna is not None:
+ self.subdev.select_rx_antenna(antenna)
+
+ def set_decim(self, decim):
+ """!
+ Set USRP RX decimation.
+
+ @param decim RX decimation rate
+ """
+ self._decim = decim
+ self._u.set_decim_rate(decim)
+
+ def set_gain(self, gain):
+ """!
+ Set USRP daughterboard gain.
+
+ @param gain RX daughterboard gain, (None=mid-range)
+ """
+ if gain is None:
+ g = self._subdev.gain_range()
+ gain = float(g[0]+g[1])/2.0
+ self._subdev.set_gain(gain)
+
+ def set_freq(self, freq):
+ """!
+ Set USRP/Daughterboard RX center frequency.
+
+ @param freq RX center frequency, (None=mid-range)
+ """
+ if freq is None:
+ f = self._subdev.freq_range()
+ freq = float(f[0]+f[1])/2.0
+ return self._u.tune(0, self._subdev, freq)
+
+ def sample_rate(self):
+ """!
+ Get USRP RX sample rate in samples/sec.
+ """
+ return self._u.adc_rate()/self._decim
Added: gnuradio/branches/features/experimental-gui/usrp_fft.py
===================================================================
--- gnuradio/branches/features/experimental-gui/usrp_fft.py
(rev 0)
+++ gnuradio/branches/features/experimental-gui/usrp_fft.py 2008-07-06
21:42:27 UTC (rev 8813)
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+#
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from optparse import OptionParser
+from gnuradio.eng_option import eng_option
+import sys
+
+# Import the top_block
+from fft_top_block import fft_top_block
+
+# Import the controller object
+from fft_controller import fft_controller
+
+# Import the GUI object
+# from fft_gui import fft_gui
+
+def get_options():
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("-w", "--which", type="int", default=0,
+ help="select which USRP (0, 1, ...) default is %default",
+ metavar="NUM")
+ parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+ help="select USRP Rx side A or B (default=first one with
a daughterboard)")
+ parser.add_option("-A", "--antenna", default=None,
+ help="select Rx Antenna (only on RFX-series boards)")
+ parser.add_option("-d", "--decim", type="int", default=16,
+ help="set fgpa decimation rate to DECIM
[default=%default]")
+ parser.add_option("-f", "--freq", type="eng_float", default=None,
+ help="set frequency to FREQ", metavar="FREQ")
+ parser.add_option("-g", "--gain", type="eng_float", default=None,
+ help="set gain in dB (default is midpoint)")
+ parser.add_option("-8", "--width-8", action="store_true", default=False,
+ help="Enable 8-bit samples across USB")
+ parser.add_option( "--no-hb", action="store_true", default=False,
+ help="don't use halfband filter in usrp")
+ parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
+ help="Set fftsink averaging factor, default=[%default]")
+ parser.add_option("", "--ref-scale", type="eng_float", default=13490.0,
+ help="Set dBFS=0dB input value, default=[%default]")
+
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ sys.exit(1)
+ return (options, args)
+
+
+if __name__ == "__main__":
+ (options, args) = get_options()
+
+ # Applications have a 3-step initialization
+
+ # Step 1: Create the GNU Radio top block. This top block knows
+ # nothing of the GUI, and is manipulated by a GUI independent
+ # controller.
+ tb = fft_top_block(fft_size=512,
+ frame_rate=10,
+ ref_scale=50,
+ which=options.which,
+ decim=options.decim,
+ width_8=options.width_8,
+ no_hb=options.no_hb,
+ subdev_spec=options.rx_subdev_spec,
+ gain=options.gain,
+ freq=options.freq,
+ antenna=options.antenna,
+ avg_alpha=options.avg_alpha,
+ average=False)
+
+ # Step 2: Create the application controller and pass it
+ # the top block it manipulates. The controller implements
+ # a property/value interface to allow setting, getting, and
+ # listening properties that affect the application operation.
+ controller = fft_controller(tb)
+
+ # Step 3: Create the GUI and pass it the controller
+ # to manipulate. The GUI code doesn't know anything about GNU
+ # Radio proper; it simply gets, sets, or listens to properties
+ # on the controller. The 'GUI' can actually be a CLI batch
+ # program, an interactive shell, or anything that knows what to
+ # do with the controller properties.
+ #
+ # gui = fft_gui(controller)
+ # gui.run()
+
+ # END
+
+
+ # Temporary until GUI is written
+ #
+ # This simply adds a listener that prints a line whenever the FFT
+ # property is updated, and invokes the controller init and exit
+ # methods.
+ controller.add_listener('fft', lambda x: sys.stdout.write('FFT updated:
'+`len(x)/4`+' bins\n'))
+ controller.on_init()
+ try:
+ raw_input("Press ENTER to stop...\n")
+ except KeyboardInterrupt:
+ pass
+ controller.on_exit()
+ # end temporary code
Property changes on: gnuradio/branches/features/experimental-gui/usrp_fft.py
___________________________________________________________________
Name: svn:executable
+ *
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8813 - gnuradio/branches/features/experimental-gui,
jcorgan <=