Merge commit 'origin' into new_eth
authorMatt Ettus <matt@ettus.com>
Fri, 25 Sep 2009 05:34:06 +0000 (22:34 -0700)
committerMatt Ettus <matt@ettus.com>
Fri, 25 Sep 2009 05:34:06 +0000 (22:34 -0700)
Conflicts:
.gitignore

138 files changed:
.gitignore
config/Makefile.am
config/grc_gr_noaa.m4 [new file with mode: 0644]
config/grc_grc.m4
configure.ac
gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
gnuradio-core/src/python/gnuradio/Makefile.am
gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
gnuradio-core/src/python/gnuradio/blks2impl/generic_usrp.py [new file with mode: 0644]
gnuradio-core/src/python/gnuradio/eng_option.py
gnuradio-core/src/python/gnuradio/usrp_options.py [new file with mode: 0644]
gnuradio-examples/python/digital/Makefile.am
gnuradio-examples/python/digital/benchmark_qt_rx.py
gnuradio-examples/python/digital/generic_usrp.py [deleted file]
gnuradio-examples/python/digital/usrp_options.py [deleted file]
gnuradio-examples/python/digital/usrp_receive_path.py
gnuradio-examples/python/digital/usrp_transmit_path.py
gr-noaa/.gitignore [new file with mode: 0644]
gr-noaa/Makefile.am [new file with mode: 0644]
gr-noaa/README [new file with mode: 0644]
gr-noaa/apps/.gitignore [new file with mode: 0644]
gr-noaa/apps/Makefile.am [new file with mode: 0644]
gr-noaa/apps/demod_hrpt_file.grc [new file with mode: 0644]
gr-noaa/apps/demod_hrpt_file.py [new file with mode: 0755]
gr-noaa/apps/usrp_rx_hrpt.cfg [new file with mode: 0644]
gr-noaa/apps/usrp_rx_hrpt.grc [new file with mode: 0644]
gr-noaa/apps/usrp_rx_hrpt.py [new file with mode: 0755]
gr-noaa/apps/usrp_rx_lrit.grc [new file with mode: 0644]
gr-noaa/apps/usrp_rx_lrit.py [new file with mode: 0755]
gr-noaa/grc/.gitignore [new file with mode: 0644]
gr-noaa/grc/Makefile.am [new file with mode: 0644]
gr-noaa/grc/noaa_hrpt_decoder.xml [new file with mode: 0644]
gr-noaa/grc/noaa_hrpt_deframer.xml [new file with mode: 0644]
gr-noaa/grc/noaa_hrpt_pll_cf.xml [new file with mode: 0644]
gr-noaa/grc/noaa_hrpt_sync_fb.xml [new file with mode: 0644]
gr-noaa/lib/.gitignore [new file with mode: 0644]
gr-noaa/lib/Makefile.am [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_decoder.cc [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_decoder.h [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_deframer.cc [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_deframer.h [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_pll_cf.cc [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_pll_cf.h [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_sync_fb.cc [new file with mode: 0644]
gr-noaa/lib/noaa_hrpt_sync_fb.h [new file with mode: 0644]
gr-noaa/python/Makefile.am [new file with mode: 0644]
gr-noaa/swig/.gitignore [new file with mode: 0644]
gr-noaa/swig/Makefile.am [new file with mode: 0644]
gr-noaa/swig/Makefile.swig.gen [new file with mode: 0644]
gr-noaa/swig/__init__.py [new file with mode: 0644]
gr-noaa/swig/noaa_hrpt_decoder.i [new file with mode: 0644]
gr-noaa/swig/noaa_hrpt_deframer.i [new file with mode: 0644]
gr-noaa/swig/noaa_hrpt_pll_cf.i [new file with mode: 0644]
gr-noaa/swig/noaa_hrpt_sync_fb.i [new file with mode: 0644]
gr-noaa/swig/noaa_swig.i [new file with mode: 0644]
gr-utils/src/python/Makefile.am
gr-utils/src/python/gr_plot_qt.py
gr-utils/src/python/pyqt_plot.py
gr-utils/src/python/pyqt_plot.ui
gr-utils/src/python/qr_fft.py [deleted file]
gr-utils/src/python/usrp2_siggen.py [deleted file]
gr-utils/src/python/usrp2_siggen_gui.py [deleted file]
gr-utils/src/python/usrp_siggen.py
gr-utils/src/python/usrp_siggen_gui.py [new file with mode: 0755]
gr-wxgui/src/python/fft_window.py
gr-wxgui/src/python/forms/converters.py
gr-wxgui/src/python/forms/forms.py
grc/Makefile.inc
grc/base/Block.py
grc/base/Element.py
grc/base/FlowGraph.py
grc/base/Param.py
grc/base/Platform.py
grc/base/Port.py
grc/blocks/Makefile.am
grc/blocks/band_pass_filter.xml
grc/blocks/band_reject_filter.xml
grc/blocks/blks2_cvsd_decode.xml [new file with mode: 0644]
grc/blocks/blks2_cvsd_encode.xml [new file with mode: 0644]
grc/blocks/block_tree.xml
grc/blocks/gr_noise_source_x.xml
grc/blocks/gr_sig_source_x.xml
grc/blocks/high_pass_filter.xml
grc/blocks/low_pass_filter.xml
grc/blocks/options.xml
grc/blocks/pad_sink.xml
grc/blocks/pad_source.xml
grc/blocks/parameter.xml
grc/blocks/virtual_sink.xml [new file with mode: 0644]
grc/blocks/virtual_source.xml [new file with mode: 0644]
grc/blocks/wxgui_fftsink2.xml
grc/blocks/wxgui_waterfallsink2.xml
grc/examples/Makefile.am
grc/examples/audio/cvsd_sweep.grc [new file with mode: 0644]
grc/gui/ActionHandler.py
grc/gui/Actions.py
grc/gui/Bars.py
grc/gui/Block.py
grc/gui/BlockTreeWindow.py
grc/gui/Connection.py
grc/gui/Dialogs.py
grc/gui/Element.py
grc/gui/FlowGraph.py
grc/gui/MainWindow.py
grc/gui/Makefile.am
grc/gui/NotebookPage.py
grc/gui/Param.py
grc/gui/ParamsDialog.py [deleted file]
grc/gui/Platform.py
grc/gui/Port.py
grc/gui/PropsDialog.py [new file with mode: 0644]
grc/gui/StateCache.py
grc/gui/Utils.py
grc/python/Block.py
grc/python/Connection.py
grc/python/FlowGraph.py
grc/python/Param.py
grc/python/Platform.py
grc/python/Port.py
grc/python/flow_graph.tmpl
grc/scripts/usrp2_probe
grc/scripts/usrp_probe
grc/todo.txt
gruel/src/lib/.gitignore
usrp2/firmware/Makefile.am
usrp2/firmware/configure.gnu
usrp2/fpga/sdr_lib/dsp_core_rx.v
usrp2/fpga/sdr_lib/hb_dec.v
usrp2/fpga/sdr_lib/small_hb_dec.v
vrt/include/vrt/quadradio.h
vrt/lib/quadradio.cc

index 6a6326509c82f31eb39c019279223d57b58a0f2f..b333709ee11bbe673fcfbfc4fd94f0ee99cce818 100644 (file)
@@ -1,3 +1,30 @@
+#
+# NOTE! Don't add files that are generated in specific
+# subdirectories here. Add them in the ".gitignore" file
+# in that subdirectory instead.
+#
+# NOTE! Please use 'git ls-files -i --exclude-standard'
+# command after changing this file, to see if there are
+# any tracked files which get ignored after the change.
+#
+.*
+*.o
+*.a
+*.ko
+*.so
+*.la
+*.lo
+*.py[oc]
+*.gz
+*.patch
+*~
+\#*#
+.deps
+.libs
+TAGS
+*-stamp
+!.gitignore
+make.log
 /configure
 /Makefile.in
 /config.log
@@ -17,5 +44,3 @@
 /compile
 /build
 /run_tests.sh
-/*-stamp
-*~
index d6a3ad393e5b2d2b4116fb2e1ac2d62889787f20..3aead353a986872239918021825d2be08a3bf119 100644 (file)
@@ -61,6 +61,7 @@ m4macros = \
        grc_gr_gcell.m4 \
        grc_gr_gpio.m4 \
        grc_gr_gsm_fr_vocoder.m4 \
+       grc_gr_noaa.m4 \
        grc_gr_radar_mono.m4 \
        grc_gr_radio_astronomy.m4 \
        grc_gr_sounder.m4 \
diff --git a/config/grc_gr_noaa.m4 b/config/grc_gr_noaa.m4
new file mode 100644 (file)
index 0000000..b00579f
--- /dev/null
@@ -0,0 +1,41 @@
+dnl Copyright 2009 Free Software Foundation, Inc.
+dnl 
+dnl This file is part of GNU Radio
+dnl 
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl 
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING.  If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+AC_DEFUN([GRC_GR_NOAA],[
+    GRC_ENABLE(gr-noaa)
+
+    dnl Don't do gr-noaa if gnuradio-core skipped
+    GRC_CHECK_DEPENDENCY(gr-noaa, gnuradio-core)
+    GRC_CHECK_DEPENDENCY(gr-noaa, gr-wxgui)
+    GRC_CHECK_DEPENDENCY(gr-noaa, grc)
+
+    AC_CONFIG_FILES([\
+        gr-noaa/Makefile \
+       gr-noaa/apps/Makefile \
+       gr-noaa/grc/Makefile \
+       gr-noaa/lib/Makefile \
+       gr-noaa/python/Makefile \
+       gr-noaa/swig/Makefile \
+    ])
+
+    GRC_BUILD_CONDITIONAL(gr-noaa,[
+        dnl run_tests is created from run_tests.in.  Make it executable.
+        #AC_CONFIG_COMMANDS([run_tests_noaa], [chmod +x gr-pager/lib/run_tests])
+    ])
+])
index ce23e3c25aee7b175eba890c1074df18a372a02c..7ee009faee171785f7ef76e57fbafbeec99f083e 100644 (file)
@@ -31,7 +31,7 @@ AC_DEFUN([GRC_GRC],[
     if test $passed = yes; then
         PYTHON_CHECK_MODULE([sys],[Python >= 2.5],[],[passed=no],[sys.version.split()[[0]] >= "2.5"])
         PYTHON_CHECK_MODULE([Cheetah],[Python Cheetah templates >= 2.0.0],[],[passed=no],[Cheetah.Version >= "2.0.0"])
-        PYTHON_CHECK_MODULE([lxml.etree],[Python lxml wrappers >= 2.0.0],[],[passed=no],[lxml.etree.LXML_VERSION >= (2, 0, 0, 0)])
+        PYTHON_CHECK_MODULE([lxml.etree],[Python lxml wrappers >= 1.3.6],[],[passed=no],[lxml.etree.LXML_VERSION >= (1, 3, 6, 0)])
         PYTHON_CHECK_MODULE([gtk],[Python gtk wrappers >= 2.10.0],[],[passed=no],[gtk.pygtk_version >= (2, 10, 0)])
     fi
 
index 2bb37935e9a4cb1ef10b664c6a1463f13368a064..b6b596befd2a3174c3bcc704c1a22503c40db2e1 100644 (file)
@@ -27,7 +27,7 @@ AC_CANONICAL_HOST
 AC_CANONICAL_TARGET
 
 
-VERSION=3.3svn
+VERSION=3.3git
 AC_SUBST(VERSION)
 AM_INIT_AUTOMAKE(gnuradio,$VERSION)
 
@@ -352,6 +352,7 @@ GRC_GR_COMEDI
 GRC_GR_CVSD_VOCODER
 GRC_GR_GPIO
 GRC_GR_GSM_FR_VOCODER
+GRC_GR_NOAA
 GRC_GR_PAGER
 GRC_GR_RADAR_MONO
 GRC_GR_RADIO_ASTRONOMY
index bfc4c04675904dac22e59004e8dfe07319438b96..8971d3d39bb5001598559ddee61a6b039c208894 100644 (file)
@@ -28,6 +28,7 @@
 #include <gr_fir_ccf.h>
 #include <gr_fir_util.h>
 #include <gr_io_signature.h>
+#include <cstdio>
 
 gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, 
                                                             const std::vector<float> &taps,
index b79a89fe93027c834f762f3ffc356f36f0ffeb60..d4c886ec378b439458914ca51c15e1ab6e0cc9be 100644 (file)
@@ -91,8 +91,8 @@ class gr_fir_ccf;
  * The theory behind this block can be found in Chapter 7.5 of 
  * the following book.
  *
- *    <B><EM>f. harris, Multirate Signal Processing for Communication 
- *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ *    <B><EM>f. harris, "Multirate Signal Processing for Communication 
+ *       Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
  */
 
 class gr_pfb_arb_resampler_ccf : public gr_block
index 7be611e236049bd309878313197df03afdc40a4f..a7e8de62ad6a65e7bb1e8914e748c72ecd73a2c6 100644 (file)
@@ -29,6 +29,7 @@
 #include <gr_fir_util.h>
 #include <gri_fft.h>
 #include <gr_io_signature.h>
+#include <cstdio>
 
 gr_pfb_channelizer_ccf_sptr gr_make_pfb_channelizer_ccf (unsigned int numchans, 
                                                         const std::vector<float> &taps)
index 7d0a31c5985c24bbc20a94733bf07f0fcf71e725..b2e67e8173a5558b16499698d4134d6da480c860 100644 (file)
@@ -91,8 +91,8 @@ class gri_fft_complex;
  * The theory behind this block can be found in Chapter 6 of 
  * the following book.
  *
- *    <B><EM>f. harris, Multirate Signal Processing for Communication 
- *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.
+ *    <B><EM>f. harris, "Multirate Signal Processing for Communication 
+ *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
  *
  */
 
index b334f58781a78b1e0c4c7678815ac158ef07a596..e05e18ff2e0f04c38bd3ce6c152402e6876806d5 100644 (file)
@@ -30,6 +30,7 @@
 #include <gri_fft.h>
 #include <gr_io_signature.h>
 #include <gr_expj.h>
+#include <cstdio>
 
 gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int decim, 
                                                     const std::vector<float> &taps,
index 83997c0c901dcb0aede1e50ed12440ea3cd63c68..200adee3d32c6fb74d85fe06dc1b579794fd4d7c 100644 (file)
@@ -88,7 +88,7 @@ class gri_fft_complex;
  * The theory behind this block can be found in Chapter 6 of 
  * the following book.
  *
- *    <B><EM>f. harris, Multirate Signal Processing for Communication 
+ *    <B><EM>f. harris, "Multirate Signal Processing for Communication 
  *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
  */
 
index d5eba885ca98df622c7013bbabe6db74ba4ebbdc..6a9598f344584b51ccb350d96ad5ead2a63143df 100644 (file)
@@ -28,6 +28,7 @@
 #include <gr_fir_ccf.h>
 #include <gr_fir_util.h>
 #include <gr_io_signature.h>
+#include <cstdio>
 
 gr_pfb_interpolator_ccf_sptr gr_make_pfb_interpolator_ccf (unsigned int interp, 
                                                           const std::vector<float> &taps)
index 50849d5108bea2b118866cda676c32bf09f0ff85..d2efc591abf2797a7418390dc1cf4d9dfe23962e 100644 (file)
@@ -74,7 +74,7 @@ class gr_fir_ccf;
  * The theory behind this block can be found in Chapter 7.1 of the
  * following book.
  *
- *    <B><EM>f. harris, <EM>Multirate Signal Processing for Communication
+ *    <B><EM>f. harris, "Multirate Signal Processing for Communication
  *       Systems</EM>," Upper Saddle River, NJ: Prentice Hall,
  *       Inc. 2004.</EM></B>
  */
index ed36bbae7c479e2d8c2cc8c959a2b8ca2a3b3943..dcc0017b3c16660fd7b238a2a106e76720d2b4ee 100644 (file)
@@ -34,5 +34,6 @@ grpython_PYTHON =                     \
        packet_utils.py                 \
        gr_unittest.py                  \
        optfir.py                       \
+       usrp_options.py         \
        window.py
 endif
index 17be09cc73b35ed9239c97700db5e3b463823f5c..f0825b15135fb7cfe19c508578c9466ec2c106c4 100644 (file)
@@ -36,6 +36,7 @@ grblkspython_PYTHON =         \
        filterbank.py           \
        fm_demod.py             \
        fm_emph.py              \
+       generic_usrp.py \
        gmsk.py                 \
        cpm.py                  \
        logpwrfft.py            \
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/generic_usrp.py b/gnuradio-core/src/python/gnuradio/blks2impl/generic_usrp.py
new file mode 100644 (file)
index 0000000..5abbaf9
--- /dev/null
@@ -0,0 +1,244 @@
+#
+# 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.
+#
+
+USRP1_TYPE = 'usrp1'
+USRP2_TYPE = 'usrp2'
+DUMMY_TYPE = 'dummy'
+#usrp2 rates common for decim and interp
+_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
+#dummy common rates
+_DUMMY_XRATES = range(4, 512, 2)
+_DUMMY_CONVERTER_RATE = 100e6
+#dummy freq result
+class _dummy_freq_result(object):
+    def __init__(self, target_freq):
+        self.baseband_freq = target_freq
+        self.dxc_freq = 0
+        self.residual_freq = 0
+from gnuradio import gr
+
+########################################################################
+# generic usrp common stuff
+########################################################################
+class _generic_usrp_base(object):
+
+    def __init__(self, which=0, subdev_spec=None, interface="", mac_addr="",
+        fusb_block_size=0, fusb_nblocks=0, usrpx=None, lo_offset=None, gain=None):
+        self._lo_offset = lo_offset
+        #usrp options
+        self._which = which
+        self._subdev_spec = subdev_spec
+        #usrp2 options
+        self._interface = interface
+        self._mac_addr = mac_addr
+        #fusb options
+        self._fusb_block_size = fusb_block_size
+        self._fusb_nblocks = fusb_nblocks
+        #pick which usrp model
+        if usrpx == '0': self._setup_usrpx(DUMMY_TYPE)
+        elif usrpx == '1' or self._subdev_spec: self._setup_usrpx(USRP1_TYPE)
+        elif usrpx == '2' or self._mac_addr: self._setup_usrpx(USRP2_TYPE)
+        else: #automatic
+            try: self._setup_usrpx(USRP2_TYPE)
+            except:
+                try: self._setup_usrpx(USRP1_TYPE)
+                except: raise Exception, 'Failed to automatically setup a usrp device.'
+        #post usrp setup
+        if self._lo_offset is not None:
+            self.set_lo_offset(self._lo_offset)
+        self.set_gain(gain)
+        self.set_auto_tr(True)
+
+    def _setup_usrpx(self, type):
+        """
+        Call the appropriate setup method.
+        @param type the usrp type constant
+        """
+        self._type = type
+        if self._type == USRP1_TYPE: self._setup_usrp1()
+        elif self._type == USRP2_TYPE: self._setup_usrp2()
+        elif self._type == DUMMY_TYPE: self._setup_dummy()
+
+    def __str__(self):
+        if self._type == USRP1_TYPE: return self._subdev.side_and_name()
+        elif self._type == USRP2_TYPE:
+            return 'Interface: %s    MAC Address: %s    D-Board ID: 0x%.2x'%(
+                self._u.interface_name(), self._u.mac_addr(), self._u.daughterboard_id())
+        elif self._type == DUMMY_TYPE: return 'Dummy USRP Device'
+
+    def gain(self): return self._gain
+
+    def set_gain(self, gain=None):
+        #automatic gain calculation
+        r = self.gain_range()
+        if gain is None: gain = (r[0] + r[1])/2 # set gain to midpoint
+        #set gain for usrp
+        self._gain = gain
+        if self._type == USRP1_TYPE: return self._subdev.set_gain(gain)
+        elif self._type == USRP2_TYPE: return self._u.set_gain(gain)
+        elif self._type == DUMMY_TYPE: return True
+
+    def gain_range(self):
+        if self._type == USRP1_TYPE: return self._subdev.gain_range()
+        elif self._type == USRP2_TYPE: return self._u.gain_range()
+        elif self._type == DUMMY_TYPE: return (0, 0, 0)
+
+    def set_center_freq(self, target_freq):
+        if self._type == USRP1_TYPE:
+            return self._u.tune(self._dxc, self._subdev, target_freq)
+        elif self._type == USRP2_TYPE:
+            return self._u.set_center_freq(target_freq)
+        elif self._type == DUMMY_TYPE: return _dummy_freq_result(target_freq)
+
+    def freq_range(self):
+        if self._type == USRP1_TYPE: return self._subdev.freq_range()
+        elif self._type == USRP2_TYPE: return self._u.freq_range()
+        elif self._type == DUMMY_TYPE: return (-10e9, 10e9, 100e3)
+
+    def set_lo_offset(self, lo_offset):
+        if self._type == USRP1_TYPE: return self._subdev.set_lo_offset(lo_offset)
+        elif self._type == USRP2_TYPE: return self._u.set_lo_offset(lo_offset)
+        elif self._type == DUMMY_TYPE: return True
+
+    def set_auto_tr(self, enable):
+        if self._type == USRP1_TYPE: return self._subdev.set_auto_tr(enable)
+
+    def __del__(self):
+        try: # Avoid weak reference error
+            del self._u
+            del self._subdev
+        except: pass
+
+########################################################################
+# generic usrp source
+########################################################################
+class generic_usrp_source_c(_generic_usrp_base, gr.hier_block2):
+    """
+    Create a generic usrp source that represents usrp and usrp2.
+    Take usrp and usrp2 constructor arguments and try to figure out usrp or usrp2.
+    Provide generic access methods so the API looks the same for both.
+    """
+
+    def __init__(self, **kwargs):
+        gr.hier_block2.__init__(self, "generic_usrp_source",
+            gr.io_signature(0, 0, 0), # Input signature
+            gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+        _generic_usrp_base.__init__(self, **kwargs)
+        self.connect(self._u, self)
+
+    ####################################################################
+    # generic access methods
+    ####################################################################
+    def set_decim(self, decim):
+        if decim not in self.get_decim_rates(): return False
+        if self._type == USRP1_TYPE: return self._u.set_decim_rate(decim)
+        elif self._type == USRP2_TYPE: return self._u.set_decim(decim)
+        elif self._type == DUMMY_TYPE: return True
+
+    def get_decim_rates(self):
+        if self._type == USRP1_TYPE: return range(8, 256+1, 2) #default firmware w/ hb filters
+        if self._type == USRP2_TYPE: return _USRP2_RATES
+        elif self._type == DUMMY_TYPE: return _DUMMY_XRATES
+
+    def adc_rate(self):
+        if self._type == USRP1_TYPE: return self._u.adc_rate()
+        if self._type == USRP2_TYPE: return self._u.adc_rate()
+        elif self._type == DUMMY_TYPE: return _DUMMY_CONVERTER_RATE
+
+    ####################################################################
+    # setup usrp methods
+    ####################################################################
+    def _setup_usrp1(self):
+        from gnuradio import usrp
+        self._u = usrp.source_c (self._which,
+                                fusb_block_size=self._fusb_block_size,
+                                fusb_nblocks=self._fusb_nblocks)
+        # determine the daughterboard subdevice we're using
+        if self._subdev_spec is None:
+            self._subdev_spec = usrp.pick_rx_subdevice(self._u)
+        self._subdev = usrp.selected_subdev(self._u, self._subdev_spec)
+        self._u.set_mux(usrp.determine_rx_mux_value(self._u, self._subdev_spec))
+        self._dxc = 0
+
+    def _setup_usrp2(self):
+        from gnuradio import usrp2
+        self._u = usrp2.source_32fc(self._interface, self._mac_addr)
+
+    def _setup_dummy(self): self._u = gr.null_source(gr.sizeof_gr_complex)
+
+########################################################################
+# generic usrp sink
+########################################################################
+class generic_usrp_sink_c(_generic_usrp_base, gr.hier_block2):
+    """
+    Create a generic usrp sink that represents usrp and usrp2.
+    Take usrp and usrp2 constructor arguments and try to figure out usrp or usrp2.
+    Provide generic access methods so the API looks the same for both.
+    """
+
+    def __init__(self, **kwargs):
+        gr.hier_block2.__init__(self, "generic_usrp_sink",
+            gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+            gr.io_signature(0, 0, 0)) # Output signature
+        _generic_usrp_base.__init__(self, **kwargs)
+        if self._type == USRP1_TYPE: #scale 0.0 to 1.0 input for usrp1
+            self.connect(self, gr.multiply_const_cc((2**15)-1), self._u)
+        else: self.connect(self, self._u)
+
+    ####################################################################
+    # generic access methods
+    ####################################################################
+    def set_interp(self, interp):
+        if interp not in self.get_interp_rates(): return False
+        if self._type == USRP1_TYPE: return self._u.set_interp_rate(interp)
+        elif self._type == USRP2_TYPE: return self._u.set_interp(interp)
+        elif self._type == DUMMY_TYPE: return True
+
+    def get_interp_rates(self):
+        if self._type == USRP1_TYPE: return range(16, 512+1, 4)
+        if self._type == USRP2_TYPE: return _USRP2_RATES
+        elif self._type == DUMMY_TYPE: return _DUMMY_XRATES
+
+    def dac_rate(self):
+        if self._type == USRP1_TYPE: return self._u.dac_rate()
+        if self._type == USRP2_TYPE: return self._u.dac_rate()
+        elif self._type == DUMMY_TYPE: return _DUMMY_CONVERTER_RATE
+
+    ####################################################################
+    # setup usrp methods
+    ####################################################################
+    def _setup_usrp1(self):
+        from gnuradio import usrp
+        self._u = usrp.sink_c (self._which,
+                                fusb_block_size=self._fusb_block_size,
+                                fusb_nblocks=self._fusb_nblocks)
+        # determine the daughterboard subdevice we're using
+        if self._subdev_spec is None:
+            self._subdev_spec = usrp.pick_tx_subdevice(self._u)
+        self._subdev = usrp.selected_subdev(self._u, self._subdev_spec)
+        self._u.set_mux(usrp.determine_tx_mux_value(self._u, self._subdev_spec))
+        self._dxc = self._subdev.which()
+
+    def _setup_usrp2(self):
+        from gnuradio import usrp2
+        self._u = usrp2.sink_32fc(self._interface, self._mac_addr)
+
+    def _setup_dummy(self): self._u = gr.null_sink(gr.sizeof_gr_complex)
index 09c3e1d87771a0a5a26ea2ce0f52b2f62a8def06..e10235f143958329b3ccfbdb70f6e08f4d91eb33 100644 (file)
 
 from copy import copy
 from optparse import Option, OptionValueError
-
-scale_factor = {}
-scale_factor['E'] = 1e18
-scale_factor['P'] = 1e15
-scale_factor['T'] = 1e12
-scale_factor['G'] = 1e9
-scale_factor['M'] = 1e6
-scale_factor['k'] = 1e3
-scale_factor['m'] = 1e-3
-scale_factor['u'] = 1e-6
-scale_factor['n'] = 1e-9
-scale_factor['p'] = 1e-12
-scale_factor['f'] = 1e-15
-scale_factor['a'] = 1e-18
-
+import eng_notation
 
 def check_eng_float (option, opt, value):
     try:
-        scale = 1.0
-        suffix = value[-1]
-        if scale_factor.has_key (suffix):
-            return float (value[0:-1]) * scale_factor[suffix]
-        return float (value)
+        return eng_notation.str_to_num(value)
     except:
         raise OptionValueError (
             "option %s: invalid engineering notation value: %r" % (opt, value))
diff --git a/gnuradio-core/src/python/gnuradio/usrp_options.py b/gnuradio-core/src/python/gnuradio/usrp_options.py
new file mode 100644 (file)
index 0000000..86dba2f
--- /dev/null
@@ -0,0 +1,123 @@
+#
+# 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.
+#
+
+_parser_to_groups_dict = dict()
+class _parser_groups(object):
+    def __init__(self, parser):
+        self.usrpx_grp = parser.add_option_group("General USRP Options")
+        self.usrp1_grp = parser.add_option_group("USRP1 Specific Options")
+        self.usrp1exp_grp = parser.add_option_group("USRP1 Expert Options")
+        self.usrp2_grp = parser.add_option_group("USRP2 Specific Options")
+
+from gnuradio import blks2
+
+def _add_options(parser):
+    """
+    Add options to manually choose between usrp or usrp2.
+    Add options for usb. Add options common to source and sink.
+    @param parser: instance of OptionParser
+    @return the parser group
+    """
+    #cache groups so they dont get added twice on tranceiver apps
+    if not _parser_to_groups_dict.has_key(parser): _parser_to_groups_dict[parser] = _parser_groups(parser)
+    pg = _parser_to_groups_dict[parser]
+    #pick usrp or usrp2
+    pg.usrpx_grp.add_option("-u", "--usrpx", type="string", default=None,
+                      help="specify which usrp model: 1 for USRP, 2 for USRP2 [default=auto]")
+    #fast usb options
+    pg.usrp1exp_grp.add_option("-B", "--fusb-block-size", type="int", default=0,
+                      help="specify fast usb block size [default=%default]")
+    pg.usrp1exp_grp.add_option("-N", "--fusb-nblocks", type="int", default=0,
+                      help="specify number of fast usb blocks [default=%default]")
+    #lo offset
+    pg.usrpx_grp.add_option("--lo-offset", type="eng_float", default=None,
+                      help="set LO Offset in Hz [default=automatic].")
+    #usrp options
+    pg.usrp1_grp.add_option("-w", "--which", type="int", default=0,
+                      help="select USRP board [default=%default]")
+    #usrp2 options
+    pg.usrp2_grp.add_option("-e", "--interface", type="string", default="eth0",
+                      help="Use USRP2 at specified Ethernet interface [default=%default]")
+    pg.usrp2_grp.add_option("-a", "--mac-addr", type="string", default="",
+                      help="Use USRP2 at specified MAC address [default=None]")
+    return pg
+
+def add_rx_options(parser):
+    """
+    Add receive specific usrp options.
+    @param parser: instance of OptionParser
+    """
+    pg = _add_options(parser)
+    pg.usrp1_grp.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Rx side A or B")
+    pg.usrpx_grp.add_option("--rx-gain", type="eng_float", default=None, metavar="GAIN",
+                      help="set receiver gain in dB [default=midpoint].  See also --show-rx-gain-range")
+    pg.usrpx_grp.add_option("--show-rx-gain-range", action="store_true", default=False, 
+                      help="print min and max Rx gain available on selected daughterboard")
+    pg.usrpx_grp.add_option("-d", "--decim", type="intx", default=None,
+                      help="set fpga decimation rate to DECIM [default=%default]")
+
+def create_usrp_source(options):
+    u = blks2.generic_usrp_source_c(
+        usrpx=options.usrpx,
+        which=options.which,
+        subdev_spec=options.rx_subdev_spec,
+        interface=options.interface,
+        mac_addr=options.mac_addr,
+        fusb_block_size=options.fusb_block_size,
+        fusb_nblocks=options.fusb_nblocks,
+        lo_offset=options.lo_offset,
+        gain=options.rx_gain,
+    )
+    if options.show_rx_gain_range:
+        print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g"%tuple(u.gain_range())
+    return u
+
+def add_tx_options(parser):
+    """
+    Add transmit specific usrp options.
+    @param parser: instance of OptionParser
+    """
+    pg = _add_options(parser)
+    pg.usrp1_grp.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Rx side A or B")
+    pg.usrpx_grp.add_option("--tx-gain", type="eng_float", default=None, metavar="GAIN",
+                      help="set transmitter gain in dB [default=midpoint].  See also --show-tx-gain-range")
+    pg.usrpx_grp.add_option("--show-tx-gain-range", action="store_true", default=False, 
+                      help="print min and max Tx gain available on selected daughterboard")
+    pg.usrpx_grp.add_option("-i", "--interp", type="intx", default=None,
+                      help="set fpga interpolation rate to INTERP [default=%default]")
+
+def create_usrp_sink(options):
+    u = blks2.generic_usrp_sink_c(
+        usrpx=options.usrpx,
+        which=options.which,
+        subdev_spec=options.tx_subdev_spec,
+        interface=options.interface,
+        mac_addr=options.mac_addr,
+        fusb_block_size=options.fusb_block_size,
+        fusb_nblocks=options.fusb_nblocks,
+        lo_offset=options.lo_offset,
+        gain=options.tx_gain,
+    )
+    if options.show_tx_gain_range:
+        print "Tx Gain Range: minimum = %g, maximum = %g, step size = %g"%tuple(u.gain_range())
+    return u
index 64ce4ec46625e0d9c6dc51a8ec472bbadad0294c..e32180cd493dd8a7caef30810a944dfd22de90c3 100644 (file)
@@ -25,7 +25,6 @@ ourdatadir = $(exampledir)/digital
 
 dist_ourdata_DATA =            \
        README                  \
-       generic_usrp.py         \
        pick_bitrate.py         \
        qt_digital_window.ui    \
        qt_digital_window.py    \
@@ -33,7 +32,6 @@ dist_ourdata_DATA =           \
        qt_rx_window.py         \
        receive_path.py         \
        transmit_path.py        \
-       usrp_options.py \
        usrp_receive_path.py \
        usrp_transmit_path.py
 
index 33cf94a5c5a9235d2a24b04a5d15b797da7d8c0c..0cbb68d23ee5cbde40c086ddb96b96a5b7cd317d 100755 (executable)
@@ -25,6 +25,7 @@ from gnuradio import usrp
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
 from optparse import OptionParser
+from gnuradio import usrp_options
 
 import random
 import struct
@@ -33,7 +34,6 @@ import sys
 # from current dir
 from receive_path import receive_path
 from pick_bitrate import pick_rx_bitrate
-import usrp_options
 
 try:
     from gnuradio.qtgui import qtgui
diff --git a/gnuradio-examples/python/digital/generic_usrp.py b/gnuradio-examples/python/digital/generic_usrp.py
deleted file mode 100644 (file)
index c7ccbe5..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-#
-# 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.
-#
-
-USRP1_TYPE = 'usrp1'
-USRP2_TYPE = 'usrp2'
-DUMMY_TYPE = 'dummy'
-#usrp2 rates common for decim and interp
-_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
-#dummy common rates
-_DUMMY_XRATES = range(4, 512, 2)
-_DUMMY_CONVERTER_RATE = 100e6
-#dummy freq result
-class _dummy_freq_result(object):
-    def __init__(self, target_freq):
-        self.baseband_freq = target_freq
-        self.dxc_freq = 0
-        self.residual_freq = 0
-from gnuradio import gr, usrp, usrp2
-
-########################################################################
-# generic usrp common stuff
-########################################################################
-class _generic_usrp_base(object):
-
-    def __init__(self, which=0, subdev_spec=None, interface="", mac_addr="",
-        fusb_block_size=0, fusb_nblocks=0, usrpx=None, lo_offset=None, gain=None):
-        self._lo_offset = lo_offset
-        #usrp options
-        self._which = which
-        self._subdev_spec = subdev_spec
-        #usrp2 options
-        self._interface = interface
-        self._mac_addr = mac_addr
-        #fusb options
-        self._fusb_block_size = fusb_block_size
-        self._fusb_nblocks = fusb_nblocks
-        #pick which usrp model
-        if usrpx == '0': self._setup_usrpx(DUMMY_TYPE)
-        elif usrpx == '1' or self._subdev_spec: self._setup_usrpx(USRP1_TYPE)
-        elif usrpx == '2' or self._mac_addr: self._setup_usrpx(USRP2_TYPE)
-        else: #automatic
-            try: self._setup_usrpx(USRP2_TYPE)
-            except:
-                try: self._setup_usrpx(USRP1_TYPE)
-                except: raise Exception, 'Failed to automatically setup a usrp device.'
-        #post usrp setup
-        if self._lo_offset is not None:
-            self.set_lo_offset(self._lo_offset)
-        self.set_gain(gain)
-        self.set_auto_tr(True)
-
-    def _setup_usrpx(self, type):
-        """
-        Call the appropriate setup method.
-        @param type the usrp type constant
-        """
-        self._type = type
-        if self._type == USRP1_TYPE: self._setup_usrp1()
-        elif self._type == USRP2_TYPE: self._setup_usrp2()
-        elif self._type == DUMMY_TYPE: self._setup_dummy()
-
-    def __str__(self):
-        if self._type == USRP1_TYPE: return self._subdev.side_and_name()
-        elif self._type == USRP2_TYPE:
-            return 'Interface: %s    MAC Address: %s    D-Board ID: 0x%.2x'%(
-                self._u.interface_name(), self._u.mac_addr(), self._u.daughterboard_id())
-        elif self._type == DUMMY_TYPE: return 'Dummy USRP Device'
-
-    def gain(self): return self._gain
-
-    def set_gain(self, gain=None):
-        #automatic gain calculation
-        r = self.gain_range()
-        if gain is None: gain = (r[0] + r[1])/2 # set gain to midpoint
-        #set gain for usrp
-        self._gain = gain
-        if self._type == USRP1_TYPE: return self._subdev.set_gain(gain)
-        elif self._type == USRP2_TYPE: return self._u.set_gain(gain)
-        elif self._type == DUMMY_TYPE: return True
-
-    def gain_range(self):
-        if self._type == USRP1_TYPE: return self._subdev.gain_range()
-        elif self._type == USRP2_TYPE: return self._u.gain_range()
-        elif self._type == DUMMY_TYPE: return (0, 0, 0)
-
-    def set_center_freq(self, target_freq):
-        if self._type == USRP1_TYPE:
-            return self._u.tune(self._dxc, self._subdev, target_freq)
-        elif self._type == USRP2_TYPE:
-            return self._u.set_center_freq(target_freq)
-        elif self._type == DUMMY_TYPE: return _dummy_freq_result(target_freq)
-
-    def freq_range(self):
-        if self._type == USRP1_TYPE: return self._subdev.freq_range()
-        elif self._type == USRP2_TYPE: return self._u.freq_range()
-        elif self._type == DUMMY_TYPE: return (-10e9, 10e9, 100e3)
-
-    def set_lo_offset(self, lo_offset):
-        if self._type == USRP1_TYPE: return self._subdev.set_lo_offset(lo_offset)
-        elif self._type == USRP2_TYPE: return self._u.set_lo_offset(lo_offset)
-        elif self._type == DUMMY_TYPE: return True
-
-    def set_auto_tr(self, enable):
-        if self._type == USRP1_TYPE: return self._subdev.set_auto_tr(enable)
-
-    def __del__(self):
-        try: # Avoid weak reference error
-            del self._u
-            del self._subdev
-        except: pass
-
-########################################################################
-# generic usrp source
-########################################################################
-class generic_usrp_source_c(_generic_usrp_base, gr.hier_block2):
-    """
-    Create a generic usrp source that represents usrp and usrp2.
-    Take usrp and usrp2 constructor arguments and try to figure out usrp or usrp2.
-    Provide generic access methods so the API looks the same for both.
-    """
-
-    def __init__(self, **kwargs):
-        gr.hier_block2.__init__(self, "generic_usrp_source",
-            gr.io_signature(0, 0, 0), # Input signature
-            gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
-        _generic_usrp_base.__init__(self, **kwargs)
-        self.connect(self._u, self)
-
-    ####################################################################
-    # generic access methods
-    ####################################################################
-    def set_decim(self, decim):
-        if decim not in self.get_decim_rates(): return False
-        if self._type == USRP1_TYPE: return self._u.set_decim_rate(decim)
-        elif self._type == USRP2_TYPE: return self._u.set_decim(decim)
-        elif self._type == DUMMY_TYPE: return True
-
-    def get_decim_rates(self):
-        if self._type == USRP1_TYPE: return range(8, 256+1, 2) #default firmware w/ hb filters
-        if self._type == USRP2_TYPE: return _USRP2_RATES
-        elif self._type == DUMMY_TYPE: return _DUMMY_XRATES
-
-    def adc_rate(self):
-        if self._type == USRP1_TYPE: return self._u.adc_rate()
-        if self._type == USRP2_TYPE: return self._u.adc_rate()
-        elif self._type == DUMMY_TYPE: return _DUMMY_CONVERTER_RATE
-
-    ####################################################################
-    # setup usrp methods
-    ####################################################################
-    def _setup_usrp1(self):
-        self._u = usrp.source_c (self._which,
-                                fusb_block_size=self._fusb_block_size,
-                                fusb_nblocks=self._fusb_nblocks)
-        # determine the daughterboard subdevice we're using
-        if self._subdev_spec is None:
-            self._subdev_spec = usrp.pick_rx_subdevice(self._u)
-        self._subdev = usrp.selected_subdev(self._u, self._subdev_spec)
-        self._u.set_mux(usrp.determine_rx_mux_value(self._u, self._subdev_spec))
-        self._dxc = 0
-
-    def _setup_usrp2(self):
-        self._u = usrp2.source_32fc(self._interface, self._mac_addr)
-
-    def _setup_dummy(self): self._u = gr.null_source(gr.sizeof_gr_complex)
-
-########################################################################
-# generic usrp sink
-########################################################################
-class generic_usrp_sink_c(_generic_usrp_base, gr.hier_block2):
-    """
-    Create a generic usrp sink that represents usrp and usrp2.
-    Take usrp and usrp2 constructor arguments and try to figure out usrp or usrp2.
-    Provide generic access methods so the API looks the same for both.
-    """
-
-    def __init__(self, **kwargs):
-        gr.hier_block2.__init__(self, "generic_usrp_sink",
-            gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
-            gr.io_signature(0, 0, 0)) # Output signature
-        _generic_usrp_base.__init__(self, **kwargs)
-        if self._type == USRP1_TYPE: #scale 0.0 to 1.0 input for usrp1
-            self.connect(self, gr.multiply_const_cc((2**15)-1), self._u)
-        else: self.connect(self, self._u)
-
-    ####################################################################
-    # generic access methods
-    ####################################################################
-    def set_interp(self, interp):
-        if interp not in self.get_interp_rates(): return False
-        if self._type == USRP1_TYPE: return self._u.set_interp_rate(interp)
-        elif self._type == USRP2_TYPE: return self._u.set_interp(interp)
-        elif self._type == DUMMY_TYPE: return True
-
-    def get_interp_rates(self):
-        if self._type == USRP1_TYPE: return range(16, 512+1, 4)
-        if self._type == USRP2_TYPE: return _USRP2_RATES
-        elif self._type == DUMMY_TYPE: return _DUMMY_XRATES
-
-    def dac_rate(self):
-        if self._type == USRP1_TYPE: return self._u.dac_rate()
-        if self._type == USRP2_TYPE: return self._u.dac_rate()
-        elif self._type == DUMMY_TYPE: return _DUMMY_CONVERTER_RATE
-
-    ####################################################################
-    # setup usrp methods
-    ####################################################################
-    def _setup_usrp1(self):
-        self._u = usrp.sink_c (self._which,
-                                fusb_block_size=self._fusb_block_size,
-                                fusb_nblocks=self._fusb_nblocks)
-        # determine the daughterboard subdevice we're using
-        if self._subdev_spec is None:
-            self._subdev_spec = usrp.pick_tx_subdevice(self._u)
-        self._subdev = usrp.selected_subdev(self._u, self._subdev_spec)
-        self._u.set_mux(usrp.determine_tx_mux_value(self._u, self._subdev_spec))
-        self._dxc = self._subdev.which()
-
-    def _setup_usrp2(self): self._u = usrp2.sink_32fc(self._interface, self._mac_addr)
-
-    def _setup_dummy(self): self._u = gr.null_sink(gr.sizeof_gr_complex)
diff --git a/gnuradio-examples/python/digital/usrp_options.py b/gnuradio-examples/python/digital/usrp_options.py
deleted file mode 100644 (file)
index 380ef60..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-#
-# 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.
-#
-
-_parser_to_groups_dict = dict()
-class _parser_groups(object):
-    def __init__(self, parser):
-        self.usrpx_grp = parser.add_option_group("General USRP Options")
-        self.usrp1_grp = parser.add_option_group("USRP1 Specific Options")
-        self.usrp1exp_grp = parser.add_option_group("USRP1 Expert Options")
-        self.usrp2_grp = parser.add_option_group("USRP2 Specific Options")
-
-import generic_usrp
-
-def _add_options(parser):
-    """
-    Add options to manually choose between usrp or usrp2.
-    Add options for usb. Add options common to source and sink.
-    @param parser: instance of OptionParser
-    @return the parser group
-    """
-    #cache groups so they dont get added twice on tranceiver apps
-    if not _parser_to_groups_dict.has_key(parser): _parser_to_groups_dict[parser] = _parser_groups(parser)
-    pg = _parser_to_groups_dict[parser]
-    #pick usrp or usrp2
-    pg.usrpx_grp.add_option("-u", "--usrpx", type="string", default=None,
-                      help="specify which usrp model: 1 for USRP, 2 for USRP2 [default=auto]")
-    #fast usb options
-    pg.usrp1exp_grp.add_option("-B", "--fusb-block-size", type="int", default=0,
-                      help="specify fast usb block size [default=%default]")
-    pg.usrp1exp_grp.add_option("-N", "--fusb-nblocks", type="int", default=0,
-                      help="specify number of fast usb blocks [default=%default]")
-    #lo offset
-    pg.usrpx_grp.add_option("--lo-offset", type="eng_float", default=None,
-                      help="set LO Offset in Hz [default=automatic].")
-    #usrp options
-    pg.usrp1_grp.add_option("-w", "--which", type="int", default=0,
-                      help="select USRP board [default=%default]")
-    #usrp2 options
-    pg.usrp2_grp.add_option("-e", "--interface", type="string", default="eth0",
-                      help="Use USRP2 at specified Ethernet interface [default=%default]")
-    pg.usrp2_grp.add_option("-a", "--mac-addr", type="string", default="",
-                      help="Use USRP2 at specified MAC address [default=None]")
-    return pg
-
-def add_rx_options(parser):
-    """
-    Add receive specific usrp options.
-    @param parser: instance of OptionParser
-    """
-    pg = _add_options(parser)
-    pg.usrp1_grp.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
-                      help="select USRP Rx side A or B")
-    pg.usrpx_grp.add_option("--rx-gain", type="eng_float", default=None, metavar="GAIN",
-                      help="set receiver gain in dB [default=midpoint].  See also --show-rx-gain-range")
-    pg.usrpx_grp.add_option("--show-rx-gain-range", action="store_true", default=False, 
-                      help="print min and max Rx gain available on selected daughterboard")
-    pg.usrpx_grp.add_option("-d", "--decim", type="intx", default=None,
-                      help="set fpga decimation rate to DECIM [default=%default]")
-
-def create_usrp_source(options):
-    u = generic_usrp.generic_usrp_source_c(
-        usrpx=options.usrpx,
-        which=options.which,
-        subdev_spec=options.rx_subdev_spec,
-        interface=options.interface,
-        mac_addr=options.mac_addr,
-        fusb_block_size=options.fusb_block_size,
-        fusb_nblocks=options.fusb_nblocks,
-        lo_offset=options.lo_offset,
-        gain=options.rx_gain,
-    )
-    if options.show_rx_gain_range:
-        print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g"%tuple(u.gain_range())
-    return u
-
-def add_tx_options(parser):
-    """
-    Add transmit specific usrp options.
-    @param parser: instance of OptionParser
-    """
-    pg = _add_options(parser)
-    pg.usrp1_grp.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
-                      help="select USRP Rx side A or B")
-    pg.usrpx_grp.add_option("--tx-gain", type="eng_float", default=None, metavar="GAIN",
-                      help="set transmitter gain in dB [default=midpoint].  See also --show-tx-gain-range")
-    pg.usrpx_grp.add_option("--show-tx-gain-range", action="store_true", default=False, 
-                      help="print min and max Tx gain available on selected daughterboard")
-    pg.usrpx_grp.add_option("-i", "--interp", type="intx", default=None,
-                      help="set fpga interpolation rate to INTERP [default=%default]")
-
-def create_usrp_sink(options):
-    u = generic_usrp.generic_usrp_sink_c(
-        usrpx=options.usrpx,
-        which=options.which,
-        subdev_spec=options.tx_subdev_spec,
-        interface=options.interface,
-        mac_addr=options.mac_addr,
-        fusb_block_size=options.fusb_block_size,
-        fusb_nblocks=options.fusb_nblocks,
-        lo_offset=options.lo_offset,
-        gain=options.tx_gain,
-    )
-    if options.show_tx_gain_range:
-        print "Tx Gain Range: minimum = %g, maximum = %g, step size = %g"%tuple(u.gain_range())
-    return u
index fd47c2725daee854e14475006cbccae440aa64e4..e28eb0a8cedcbdcfca84a3f69fbacfdb36e80a87 100644 (file)
@@ -20,7 +20,7 @@
 # 
 
 from gnuradio import gr
-import usrp_options
+from gnuradio import usrp_options
 import receive_path
 from pick_bitrate import pick_rx_bitrate
 from gnuradio import eng_notation
index ed2603fa3e632a35580e4559b07440801b06adaa..ad9f741a6309dec1b82106513525ebcb2a324c2f 100644 (file)
@@ -20,7 +20,7 @@
 # 
 
 from gnuradio import gr
-import usrp_options
+from gnuradio import usrp_options
 import transmit_path
 from pick_bitrate import pick_tx_bitrate
 from gnuradio import eng_notation
diff --git a/gr-noaa/.gitignore b/gr-noaa/.gitignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/gr-noaa/Makefile.am b/gr-noaa/Makefile.am
new file mode 100644 (file)
index 0000000..f3f4f6a
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = lib grc
+
+if PYTHON
+SUBDIRS += swig python apps
+endif
+
diff --git a/gr-noaa/README b/gr-noaa/README
new file mode 100644 (file)
index 0000000..d99c0d9
--- /dev/null
@@ -0,0 +1,53 @@
+This component implements an NOAA POES HRPT receiver.  After installation,
+the scripts described below will be install in the users PATH.
+
+As the scripts are generated using GRC, GRC must be installed at runtime
+in order for them to operate.
+
+
+HRPT Operation
+--------------
+
+usrp_rx_hrpt.py
+
+This GUI script will receive HRPT RF, demodulate, synchronize, and deframe
+HRPT minor frames into a file.  The file stores a series of 11090 word,
+16-bits per word corresponding to the HRPT minor frame format (only the
+lower 10-bits per word are significant.)
+
+The script file by default uses USRP side A, 1698 MHz, at decimation 16. A
+configuration file 'usrp_rx_hrpt.cfg' in the current working directory will
+allow changing this, as well as implementing persistent storage of GUI
+entered parameters from invocation to invocation.
+
+The present HRPT demodulator is only tested at decimation 16.  The only other
+valid decimation rates are 24 and 32, which may word but with more bit
+errors.  No other decimation rates will work.
+
+
+demod_hrpt_file.py
+
+This command-line only script will operate on a file generated with
+usrp_rx_cfile.py and output frames in the same format as above.  It does
+*not* use the configuration file above.
+
+Usage: demod_hrpt_file.py: [options]
+
+Options:
+  -h, --help            show this help message and exit
+  -d DECIM, --decim=DECIM
+                        Set Decimation [default=16]
+  -p PLL_ALPHA, --pll-alpha=PLL_ALPHA
+                        Set pll_alpha [default=50m]
+  -s SYNC_ALPHA, --sync-alpha=SYNC_ALPHA
+                        Set sync_alpha [default=50m]
+  -F FILENAME, --filename=FILENAME
+                        Set Filename [default=usrp.dat]
+  -o OUTPUT, --output=OUTPUT
+                        Set Output [default=frames.dat]
+
+
+LRIT Operation
+--------------
+
+The work-in-progress LRIT GRC script is not currently in a usable state.
diff --git a/gr-noaa/apps/.gitignore b/gr-noaa/apps/.gitignore
new file mode 100644 (file)
index 0000000..773a6df
--- /dev/null
@@ -0,0 +1 @@
+*.dat
diff --git a/gr-noaa/apps/Makefile.am b/gr-noaa/apps/Makefile.am
new file mode 100644 (file)
index 0000000..906638f
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# 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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+if PYTHON
+
+dist_bin_SCRIPTS = \
+       demod_hrpt_file.py \
+       usrp_rx_hrpt.py \
+       usrp_rx_lrit.py
+
+EXTRA_DIST = \
+       demod_hrpt_file.grc \
+       usrp_rx_hrpt.grc \
+       usrp_rx_lrit.grc
+endif
diff --git a/gr-noaa/apps/demod_hrpt_file.grc b/gr-noaa/apps/demod_hrpt_file.grc
new file mode 100644 (file)
index 0000000..4a5e871
--- /dev/null
@@ -0,0 +1,781 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+  <timestamp>Wed Sep 23 11:37:25 2009</timestamp>
+  <block>
+    <key>options</key>
+    <param>
+      <key>id</key>
+      <value>demod_hrpt_file</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>USRP HRPT Receiver</value>
+    </param>
+    <param>
+      <key>author</key>
+      <value></value>
+    </param>
+    <param>
+      <key>description</key>
+      <value></value>
+    </param>
+    <param>
+      <key>window_size</key>
+      <value>4096,4096</value>
+    </param>
+    <param>
+      <key>generate_options</key>
+      <value>no_gui</value>
+    </param>
+    <param>
+      <key>category</key>
+      <value>Custom</value>
+    </param>
+    <param>
+      <key>run</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(10, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>max_sync_offset</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.01</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(705, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>max_carrier_offset</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>2*math.pi*100e3/sample_rate</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(575, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>hs</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>int(sps/2.0)</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(499, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sps</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>sample_rate/sym_rate</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(397, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sym_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>600*1109</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(301, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sample_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>64e6/decim</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(198, 17)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Decimation</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>16</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>intx</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value>d</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(404, 102)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>pll_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value></value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>eng_float</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value>p</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(516, 102)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>sync_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value></value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>eng_float</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value>s</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(601, 103)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>import</key>
+    <param>
+      <key>id</key>
+      <value>import_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>import</key>
+      <value>import math</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(9, 92)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>filename</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Filename</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>usrp.dat</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>string</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value>F</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(200, 101)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_file_source</key>
+    <param>
+      <key>id</key>
+      <value>file_source</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>file</key>
+      <value>filename</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>short</value>
+    </param>
+    <param>
+      <key>repeat</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(102, 368)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_short_to_float</key>
+    <param>
+      <key>id</key>
+      <value>s2f</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(305, 380)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_deinterleave</key>
+    <param>
+      <key>id</key>
+      <value>deinterleave</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>num_streams</key>
+      <value>2</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(526, 363)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_float_to_complex</key>
+    <param>
+      <key>id</key>
+      <value>f2c</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(730, 363)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>virtual_sink</key>
+    <param>
+      <key>id</key>
+      <value>samples_sink</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>stream_id</key>
+      <value>samples</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(968, 376)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>virtual_source</key>
+    <param>
+      <key>id</key>
+      <value>samples_source</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>stream_id</key>
+      <value>samples</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(104, 479)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_moving_average_xx</key>
+    <param>
+      <key>id</key>
+      <value>matched_filter</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>length</key>
+      <value>hs</value>
+    </param>
+    <param>
+      <key>scale</key>
+      <value>1.0/hs</value>
+    </param>
+    <param>
+      <key>max_iter</key>
+      <value>4000</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(302, 463)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_pll_cf</key>
+    <param>
+      <key>id</key>
+      <value>pll</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>pll_alpha</value>
+    </param>
+    <param>
+      <key>beta</key>
+      <value>pll_alpha**2/4.0</value>
+    </param>
+    <param>
+      <key>max_offset</key>
+      <value>max_carrier_offset</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(504, 463)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_sync_fb</key>
+    <param>
+      <key>id</key>
+      <value>sync</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>sync_alpha</value>
+    </param>
+    <param>
+      <key>beta</key>
+      <value>sync_alpha**2/4.0</value>
+    </param>
+    <param>
+      <key>sps</key>
+      <value>sps</value>
+    </param>
+    <param>
+      <key>max_offset</key>
+      <value>max_sync_offset</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(711, 455)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_deframer</key>
+    <param>
+      <key>id</key>
+      <value>deframer</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(935, 483)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_file_sink</key>
+    <param>
+      <key>id</key>
+      <value>file_sink</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>file</key>
+      <value>output</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>short</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1136, 479)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_decoder</key>
+    <param>
+      <key>id</key>
+      <value>decoder</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1135, 542)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>output</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Output</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>frames.dat</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>string</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value>o</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(302, 101)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <connection>
+    <source_block_id>deframer</source_block_id>
+    <sink_block_id>file_sink</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>sync</source_block_id>
+    <sink_block_id>deframer</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>pll</source_block_id>
+    <sink_block_id>sync</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>matched_filter</source_block_id>
+    <sink_block_id>pll</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>s2f</source_block_id>
+    <sink_block_id>deinterleave</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>deinterleave</source_block_id>
+    <sink_block_id>f2c</sink_block_id>
+    <source_key>1</source_key>
+    <sink_key>1</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>deinterleave</source_block_id>
+    <sink_block_id>f2c</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>file_source</source_block_id>
+    <sink_block_id>s2f</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>deframer</source_block_id>
+    <sink_block_id>decoder</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>f2c</source_block_id>
+    <sink_block_id>samples_sink</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>samples_source</source_block_id>
+    <sink_block_id>matched_filter</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+</flow_graph>
diff --git a/gr-noaa/apps/demod_hrpt_file.py b/gr-noaa/apps/demod_hrpt_file.py
new file mode 100755 (executable)
index 0000000..a1469e9
--- /dev/null
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: USRP HRPT Receiver
+# Generated: Wed Sep 23 11:37:25 2009
+##################################################
+
+from gnuradio import eng_notation
+from gnuradio import gr
+from gnuradio import noaa
+from gnuradio.eng_option import eng_option
+from gnuradio.gr import firdes
+from optparse import OptionParser
+import math
+
+class demod_hrpt_file(gr.top_block):
+
+       def __init__(self, decim=16, pll_alpha=0.05, sync_alpha=0.05, filename="usrp.dat", output="frames.dat"):
+               gr.top_block.__init__(self, "USRP HRPT Receiver")
+
+               ##################################################
+               # Parameters
+               ##################################################
+               self.decim = decim
+               self.pll_alpha = pll_alpha
+               self.sync_alpha = sync_alpha
+               self.filename = filename
+               self.output = output
+
+               ##################################################
+               # Variables
+               ##################################################
+               self.sym_rate = sym_rate = 600*1109
+               self.sample_rate = sample_rate = 64e6/decim
+               self.sps = sps = sample_rate/sym_rate
+               self.max_sync_offset = max_sync_offset = 0.01
+               self.max_carrier_offset = max_carrier_offset = 2*math.pi*100e3/sample_rate
+               self.hs = hs = int(sps/2.0)
+
+               ##################################################
+               # Blocks
+               ##################################################
+               self.decoder = noaa.hrpt_decoder()
+               self.deframer = noaa.hrpt_deframer()
+               self.deinterleave = gr.deinterleave(gr.sizeof_float*1)
+               self.f2c = gr.float_to_complex(1)
+               self.file_sink = gr.file_sink(gr.sizeof_short*1, output)
+               self.file_source = gr.file_source(gr.sizeof_short*1, filename, False)
+               self.matched_filter = gr.moving_average_cc(hs, 1.0/hs, 4000)
+               self.pll = noaa.hrpt_pll_cf(pll_alpha, pll_alpha**2/4.0, max_carrier_offset)
+               self.s2f = gr.short_to_float()
+               self.sync = noaa.hrpt_sync_fb(sync_alpha, sync_alpha**2/4.0, sps, max_sync_offset)
+
+               ##################################################
+               # Connections
+               ##################################################
+               self.connect((self.deframer, 0), (self.file_sink, 0))
+               self.connect((self.sync, 0), (self.deframer, 0))
+               self.connect((self.pll, 0), (self.sync, 0))
+               self.connect((self.matched_filter, 0), (self.pll, 0))
+               self.connect((self.s2f, 0), (self.deinterleave, 0))
+               self.connect((self.deinterleave, 1), (self.f2c, 1))
+               self.connect((self.deinterleave, 0), (self.f2c, 0))
+               self.connect((self.file_source, 0), (self.s2f, 0))
+               self.connect((self.deframer, 0), (self.decoder, 0))
+               self.connect((self.f2c, 0), (self.matched_filter, 0))
+
+       def set_decim(self, decim):
+               self.decim = decim
+               self.set_sample_rate(64e6/self.decim)
+
+       def set_pll_alpha(self, pll_alpha):
+               self.pll_alpha = pll_alpha
+               self.pll.set_alpha(self.pll_alpha)
+               self.pll.set_beta(self.pll_alpha**2/4.0)
+
+       def set_sync_alpha(self, sync_alpha):
+               self.sync_alpha = sync_alpha
+               self.sync.set_alpha(self.sync_alpha)
+               self.sync.set_beta(self.sync_alpha**2/4.0)
+
+       def set_filename(self, filename):
+               self.filename = filename
+
+       def set_output(self, output):
+               self.output = output
+
+       def set_sym_rate(self, sym_rate):
+               self.sym_rate = sym_rate
+               self.set_sps(self.sample_rate/self.sym_rate)
+
+       def set_sample_rate(self, sample_rate):
+               self.sample_rate = sample_rate
+               self.set_max_carrier_offset(2*math.pi*100e3/self.sample_rate)
+               self.set_sps(self.sample_rate/self.sym_rate)
+
+       def set_sps(self, sps):
+               self.sps = sps
+               self.set_hs(int(self.sps/2.0))
+
+       def set_max_sync_offset(self, max_sync_offset):
+               self.max_sync_offset = max_sync_offset
+               self.sync.set_max_offset(self.max_sync_offset)
+
+       def set_max_carrier_offset(self, max_carrier_offset):
+               self.max_carrier_offset = max_carrier_offset
+               self.pll.set_max_offset(self.max_carrier_offset)
+
+       def set_hs(self, hs):
+               self.hs = hs
+               self.matched_filter.set_length_and_scale(self.hs, 1.0/self.hs)
+
+if __name__ == '__main__':
+       parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+       parser.add_option("-d", "--decim", dest="decim", type="intx", default=16,
+               help="Set Decimation [default=%default]")
+       parser.add_option("-p", "--pll-alpha", dest="pll_alpha", type="eng_float", default=eng_notation.num_to_str(0.05),
+               help="Set pll_alpha [default=%default]")
+       parser.add_option("-s", "--sync-alpha", dest="sync_alpha", type="eng_float", default=eng_notation.num_to_str(0.05),
+               help="Set sync_alpha [default=%default]")
+       parser.add_option("-F", "--filename", dest="filename", type="string", default="usrp.dat",
+               help="Set Filename [default=%default]")
+       parser.add_option("-o", "--output", dest="output", type="string", default="frames.dat",
+               help="Set Output [default=%default]")
+       (options, args) = parser.parse_args()
+       tb = demod_hrpt_file(decim=options.decim, pll_alpha=options.pll_alpha, sync_alpha=options.sync_alpha, filename=options.filename, output=options.output)
+       tb.start()
+       raw_input('Press Enter to quit: ')
+       tb.stop()
+
diff --git a/gr-noaa/apps/usrp_rx_hrpt.cfg b/gr-noaa/apps/usrp_rx_hrpt.cfg
new file mode 100644 (file)
index 0000000..69f3c0b
--- /dev/null
@@ -0,0 +1,13 @@
+[output]
+filename = frames.dat
+
+[demod]
+pll_alpha = 0.05
+sync_alpha = 0.05
+
+[usrp]
+freq = 1698000000.0
+decim = 16
+side = A
+gain = 35.0
+
diff --git a/gr-noaa/apps/usrp_rx_hrpt.grc b/gr-noaa/apps/usrp_rx_hrpt.grc
new file mode 100644 (file)
index 0000000..90d8687
--- /dev/null
@@ -0,0 +1,1394 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+  <timestamp>Wed Sep 23 11:32:00 2009</timestamp>
+  <block>
+    <key>options</key>
+    <param>
+      <key>id</key>
+      <value>usrp_rx_hrpt</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>USRP HRPT Receiver</value>
+    </param>
+    <param>
+      <key>author</key>
+      <value></value>
+    </param>
+    <param>
+      <key>description</key>
+      <value></value>
+    </param>
+    <param>
+      <key>window_size</key>
+      <value>4096,4096</value>
+    </param>
+    <param>
+      <key>generate_options</key>
+      <value>wx_gui</value>
+    </param>
+    <param>
+      <key>category</key>
+      <value>Custom</value>
+    </param>
+    <param>
+      <key>run</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(10, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>max_carrier_offset</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>2*math.pi*100e3/sample_rate</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(575, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_moving_average_xx</key>
+    <param>
+      <key>id</key>
+      <value>matched_filter</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>length</key>
+      <value>hs</value>
+    </param>
+    <param>
+      <key>scale</key>
+      <value>1.0/hs</value>
+    </param>
+    <param>
+      <key>max_iter</key>
+      <value>4000</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(441, 723)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>import</key>
+    <param>
+      <key>id</key>
+      <value>import_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>import</key>
+      <value>import math</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(11, 76)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>'usrp_rx_hrpt.cfg'</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(12, 129)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sym_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>600*1109</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(301, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sps</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>sample_rate/sym_rate</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(397, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>hs</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>int(sps/2.0)</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(499, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sample_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>64e6/decim</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(198, 17)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>RX Gain</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_gain</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>100</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>100</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 1, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(340, 106)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_text_box</key>
+    <param>
+      <key>id</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Frequency</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_freq</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>formatter</key>
+      <value>None</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(199, 106)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>pll_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>PLL Alpha</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_pll_alpha</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0.0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>100</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 2, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(479, 106)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>sync_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>SYNC Alpha</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_sync_alpha</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0.0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>100</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 3, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(618, 106)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_static_text</key>
+    <param>
+      <key>id</key>
+      <value>side_text</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>USRP Side</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>side</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>str_converter</value>
+    </param>
+    <param>
+      <key>formatter</key>
+      <value>None</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(828, 20)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>side</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>'A'</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>string</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'usrp'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'side'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>side</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(194, 253)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>16</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'usrp'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'decim'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(351, 255)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_freq</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>1698e6</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'usrp'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'freq'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(507, 258)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_gain</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>35</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'usrp'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'gain'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(664, 259)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_pll_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'demod'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'pll_alpha'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>pll_alpha</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(823, 258)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_sync_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'demod'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'sync_alpha'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>sync_alpha</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(981, 258)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>output_filename</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>'frames.dat'</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>string</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>'output'</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>'filename'</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>output_filename</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1139, 259)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_static_text</key>
+    <param>
+      <key>id</key>
+      <value>decim_text</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Decimation</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>formatter</key>
+      <value>None</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 1, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(973, 20)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>max_sync_offset</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.01</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(705, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>usrp_simple_source_x</key>
+    <param>
+      <key>id</key>
+      <value>usrp_source</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>format</key>
+      <value></value>
+    </param>
+    <param>
+      <key>which</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>decimation</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>frequency</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>lo_offset</key>
+      <value>float('inf')</value>
+    </param>
+    <param>
+      <key>gain</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>side</key>
+      <value>side</value>
+    </param>
+    <param>
+      <key>rx_ant</key>
+      <value>RXA</value>
+    </param>
+    <param>
+      <key>hb_filters</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(56, 699)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_agc_xx</key>
+    <param>
+      <key>id</key>
+      <value>agc</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>rate</key>
+      <value>1e-6</value>
+    </param>
+    <param>
+      <key>reference</key>
+      <value>1.0</value>
+    </param>
+    <param>
+      <key>gain</key>
+      <value>1.0</value>
+    </param>
+    <param>
+      <key>max_gain</key>
+      <value>1.0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(273, 715)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>rx_scope</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>RX Waveform</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>sample_rate</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>20.0/sample_rate</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(439, 829)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_fftsink2</key>
+    <param>
+      <key>id</key>
+      <value>rx_fft</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>RX Spectrum</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>sample_rate</value>
+    </param>
+    <param>
+      <key>baseband_freq</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>y_per_div</key>
+      <value>5</value>
+    </param>
+    <param>
+      <key>y_divs</key>
+      <value>8</value>
+    </param>
+    <param>
+      <key>ref_level</key>
+      <value>-5</value>
+    </param>
+    <param>
+      <key>ref_scale</key>
+      <value>2.0</value>
+    </param>
+    <param>
+      <key>fft_size</key>
+      <value>1024</value>
+    </param>
+    <param>
+      <key>fft_rate</key>
+      <value>30</value>
+    </param>
+    <param>
+      <key>peak_hold</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>average</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>avg_alpha</key>
+      <value>0.1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(439, 465)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>pll_scope</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Post-PLL</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>sample_rate</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>20.0/sample_rate</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(605, 552)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>notebook</key>
+    <param>
+      <key>id</key>
+      <value>displays</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.NB_TOP</value>
+    </param>
+    <param>
+      <key>labels</key>
+      <value>['RX','Demod']</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>2, 0, 1, 4</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(15, 237)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_pll_cf</key>
+    <param>
+      <key>id</key>
+      <value>pll</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>pll_alpha</value>
+    </param>
+    <param>
+      <key>beta</key>
+      <value>pll_alpha**2/4.0</value>
+    </param>
+    <param>
+      <key>max_offset</key>
+      <value>max_carrier_offset</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(632, 723)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_sync_fb</key>
+    <param>
+      <key>id</key>
+      <value>sync</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>sync_alpha</value>
+    </param>
+    <param>
+      <key>beta</key>
+      <value>sync_alpha**2/4.0</value>
+    </param>
+    <param>
+      <key>sps</key>
+      <value>sps</value>
+    </param>
+    <param>
+      <key>max_offset</key>
+      <value>max_sync_offset</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(840, 715)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_deframer</key>
+    <param>
+      <key>id</key>
+      <value>deframer</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1071, 743)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>noaa_hrpt_decoder</key>
+    <param>
+      <key>id</key>
+      <value>decoder</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1274, 743)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_file_sink</key>
+    <param>
+      <key>id</key>
+      <value>frame_sink</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>file</key>
+      <value>output_filename</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>short</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1273, 851)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <connection>
+    <source_block_id>deframer</source_block_id>
+    <sink_block_id>frame_sink</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>sync</source_block_id>
+    <sink_block_id>deframer</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>pll</source_block_id>
+    <sink_block_id>sync</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>pll</source_block_id>
+    <sink_block_id>pll_scope</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>agc</source_block_id>
+    <sink_block_id>rx_scope</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>agc</source_block_id>
+    <sink_block_id>rx_fft</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>agc</source_block_id>
+    <sink_block_id>matched_filter</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>matched_filter</source_block_id>
+    <sink_block_id>pll</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>deframer</source_block_id>
+    <sink_block_id>decoder</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>usrp_source</source_block_id>
+    <sink_block_id>agc</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+</flow_graph>
diff --git a/gr-noaa/apps/usrp_rx_hrpt.py b/gr-noaa/apps/usrp_rx_hrpt.py
new file mode 100755 (executable)
index 0000000..7efbecd
--- /dev/null
@@ -0,0 +1,435 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: USRP HRPT Receiver
+# Generated: Wed Sep 23 11:32:04 2009
+##################################################
+
+from gnuradio import eng_notation
+from gnuradio import gr
+from gnuradio import noaa
+from gnuradio.eng_option import eng_option
+from gnuradio.gr import firdes
+from gnuradio.wxgui import fftsink2
+from gnuradio.wxgui import forms
+from gnuradio.wxgui import scopesink2
+from grc_gnuradio import usrp as grc_usrp
+from grc_gnuradio import wxgui as grc_wxgui
+from optparse import OptionParser
+import ConfigParser
+import math
+import wx
+
+class usrp_rx_hrpt(grc_wxgui.top_block_gui):
+
+       def __init__(self):
+               grc_wxgui.top_block_gui.__init__(self, title="USRP HRPT Receiver")
+
+               ##################################################
+               # Variables
+               ##################################################
+               self.config_filename = config_filename = 'usrp_rx_hrpt.cfg'
+               self._decim_config = ConfigParser.ConfigParser()
+               self._decim_config.read(config_filename)
+               try: decim = self._decim_config.getfloat('usrp', 'decim')
+               except: decim = 16
+               self.decim = decim
+               self.sym_rate = sym_rate = 600*1109
+               self.sample_rate = sample_rate = 64e6/decim
+               self.sps = sps = sample_rate/sym_rate
+               self._side_config = ConfigParser.ConfigParser()
+               self._side_config.read(config_filename)
+               try: side = self._side_config.get('usrp', 'side')
+               except: side = 'A'
+               self.side = side
+               self._saved_sync_alpha_config = ConfigParser.ConfigParser()
+               self._saved_sync_alpha_config.read(config_filename)
+               try: saved_sync_alpha = self._saved_sync_alpha_config.getfloat('demod', 'sync_alpha')
+               except: saved_sync_alpha = 0.05
+               self.saved_sync_alpha = saved_sync_alpha
+               self._saved_pll_alpha_config = ConfigParser.ConfigParser()
+               self._saved_pll_alpha_config.read(config_filename)
+               try: saved_pll_alpha = self._saved_pll_alpha_config.getfloat('demod', 'pll_alpha')
+               except: saved_pll_alpha = 0.05
+               self.saved_pll_alpha = saved_pll_alpha
+               self._saved_gain_config = ConfigParser.ConfigParser()
+               self._saved_gain_config.read(config_filename)
+               try: saved_gain = self._saved_gain_config.getfloat('usrp', 'gain')
+               except: saved_gain = 35
+               self.saved_gain = saved_gain
+               self._saved_freq_config = ConfigParser.ConfigParser()
+               self._saved_freq_config.read(config_filename)
+               try: saved_freq = self._saved_freq_config.getfloat('usrp', 'freq')
+               except: saved_freq = 1698e6
+               self.saved_freq = saved_freq
+               self.sync_alpha = sync_alpha = saved_sync_alpha
+               self.side_text = side_text = side
+               self.pll_alpha = pll_alpha = saved_pll_alpha
+               self._output_filename_config = ConfigParser.ConfigParser()
+               self._output_filename_config.read(config_filename)
+               try: output_filename = self._output_filename_config.get('output', 'filename')
+               except: output_filename = 'frames.dat'
+               self.output_filename = output_filename
+               self.max_sync_offset = max_sync_offset = 0.01
+               self.max_carrier_offset = max_carrier_offset = 2*math.pi*100e3/sample_rate
+               self.hs = hs = int(sps/2.0)
+               self.gain = gain = saved_gain
+               self.freq = freq = saved_freq
+               self.decim_text = decim_text = decim
+
+               ##################################################
+               # Notebooks
+               ##################################################
+               self.displays = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
+               self.displays.AddPage(grc_wxgui.Panel(self.displays), "RX")
+               self.displays.AddPage(grc_wxgui.Panel(self.displays), "Demod")
+               self.GridAdd(self.displays, 2, 0, 1, 4)
+
+               ##################################################
+               # Controls
+               ##################################################
+               _sync_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._sync_alpha_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_sync_alpha_sizer,
+                       value=self.sync_alpha,
+                       callback=self.set_sync_alpha,
+                       label="SYNC Alpha",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._sync_alpha_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_sync_alpha_sizer,
+                       value=self.sync_alpha,
+                       callback=self.set_sync_alpha,
+                       minimum=0.0,
+                       maximum=0.5,
+                       num_steps=100,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_sync_alpha_sizer, 0, 3, 1, 1)
+               self._side_text_static_text = forms.static_text(
+                       parent=self.GetWin(),
+                       value=self.side_text,
+                       callback=self.set_side_text,
+                       label="USRP Side",
+                       converter=forms.str_converter(),
+               )
+               self.GridAdd(self._side_text_static_text, 1, 0, 1, 1)
+               _pll_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._pll_alpha_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_pll_alpha_sizer,
+                       value=self.pll_alpha,
+                       callback=self.set_pll_alpha,
+                       label="PLL Alpha",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._pll_alpha_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_pll_alpha_sizer,
+                       value=self.pll_alpha,
+                       callback=self.set_pll_alpha,
+                       minimum=0.0,
+                       maximum=0.5,
+                       num_steps=100,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_pll_alpha_sizer, 0, 2, 1, 1)
+               _gain_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._gain_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_gain_sizer,
+                       value=self.gain,
+                       callback=self.set_gain,
+                       label="RX Gain",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._gain_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_gain_sizer,
+                       value=self.gain,
+                       callback=self.set_gain,
+                       minimum=0,
+                       maximum=100,
+                       num_steps=100,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_gain_sizer, 0, 1, 1, 1)
+               self._freq_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       value=self.freq,
+                       callback=self.set_freq,
+                       label="Frequency",
+                       converter=forms.float_converter(),
+               )
+               self.GridAdd(self._freq_text_box, 0, 0, 1, 1)
+               self._decim_text_static_text = forms.static_text(
+                       parent=self.GetWin(),
+                       value=self.decim_text,
+                       callback=self.set_decim_text,
+                       label="Decimation",
+                       converter=forms.float_converter(),
+               )
+               self.GridAdd(self._decim_text_static_text, 1, 1, 1, 1)
+
+               ##################################################
+               # Blocks
+               ##################################################
+               self.agc = gr.agc_cc(1e-6, 1.0, 1.0, 1.0)
+               self.decoder = noaa.hrpt_decoder()
+               self.deframer = noaa.hrpt_deframer()
+               self.frame_sink = gr.file_sink(gr.sizeof_short*1, output_filename)
+               self.matched_filter = gr.moving_average_cc(hs, 1.0/hs, 4000)
+               self.pll = noaa.hrpt_pll_cf(pll_alpha, pll_alpha**2/4.0, max_carrier_offset)
+               self.pll_scope = scopesink2.scope_sink_f(
+                       self.displays.GetPage(1).GetWin(),
+                       title="Post-PLL",
+                       sample_rate=sample_rate,
+                       v_scale=0.5,
+                       t_scale=20.0/sample_rate,
+                       ac_couple=False,
+                       xy_mode=False,
+                       num_inputs=1,
+               )
+               self.displays.GetPage(1).GridAdd(self.pll_scope.win, 0, 0, 1, 1)
+               self.rx_fft = fftsink2.fft_sink_c(
+                       self.displays.GetPage(0).GetWin(),
+                       baseband_freq=freq,
+                       y_per_div=5,
+                       y_divs=8,
+                       ref_level=-5,
+                       ref_scale=2.0,
+                       sample_rate=sample_rate,
+                       fft_size=1024,
+                       fft_rate=30,
+                       average=True,
+                       avg_alpha=0.1,
+                       title="RX Spectrum",
+                       peak_hold=False,
+               )
+               self.displays.GetPage(0).GridAdd(self.rx_fft.win, 0, 0, 1, 1)
+               self.rx_scope = scopesink2.scope_sink_c(
+                       self.displays.GetPage(0).GetWin(),
+                       title="RX Waveform",
+                       sample_rate=sample_rate,
+                       v_scale=0,
+                       t_scale=20.0/sample_rate,
+                       ac_couple=False,
+                       xy_mode=False,
+                       num_inputs=1,
+               )
+               self.displays.GetPage(0).GridAdd(self.rx_scope.win, 1, 0, 1, 1)
+               self.sync = noaa.hrpt_sync_fb(sync_alpha, sync_alpha**2/4.0, sps, max_sync_offset)
+               self.usrp_source = grc_usrp.simple_source_c(which=0, side=side, rx_ant="RXA")
+               self.usrp_source.set_decim_rate(decim)
+               self.usrp_source.set_frequency(freq, verbose=True)
+               self.usrp_source.set_gain(gain)
+
+               ##################################################
+               # Connections
+               ##################################################
+               self.connect((self.deframer, 0), (self.frame_sink, 0))
+               self.connect((self.sync, 0), (self.deframer, 0))
+               self.connect((self.pll, 0), (self.sync, 0))
+               self.connect((self.pll, 0), (self.pll_scope, 0))
+               self.connect((self.agc, 0), (self.rx_scope, 0))
+               self.connect((self.agc, 0), (self.rx_fft, 0))
+               self.connect((self.agc, 0), (self.matched_filter, 0))
+               self.connect((self.matched_filter, 0), (self.pll, 0))
+               self.connect((self.deframer, 0), (self.decoder, 0))
+               self.connect((self.usrp_source, 0), (self.agc, 0))
+
+       def set_config_filename(self, config_filename):
+               self.config_filename = config_filename
+               self._side_config = ConfigParser.ConfigParser()
+               self._side_config.read(self.config_filename)
+               if not self._side_config.has_section('usrp'):
+                       self._side_config.add_section('usrp')
+               self._side_config.set('usrp', 'side', str(self.side))
+               self._side_config.write(open(self.config_filename, 'w'))
+               self._decim_config = ConfigParser.ConfigParser()
+               self._decim_config.read(self.config_filename)
+               if not self._decim_config.has_section('usrp'):
+                       self._decim_config.add_section('usrp')
+               self._decim_config.set('usrp', 'decim', str(self.decim))
+               self._decim_config.write(open(self.config_filename, 'w'))
+               self._saved_freq_config = ConfigParser.ConfigParser()
+               self._saved_freq_config.read(self.config_filename)
+               if not self._saved_freq_config.has_section('usrp'):
+                       self._saved_freq_config.add_section('usrp')
+               self._saved_freq_config.set('usrp', 'freq', str(self.freq))
+               self._saved_freq_config.write(open(self.config_filename, 'w'))
+               self._saved_gain_config = ConfigParser.ConfigParser()
+               self._saved_gain_config.read(self.config_filename)
+               if not self._saved_gain_config.has_section('usrp'):
+                       self._saved_gain_config.add_section('usrp')
+               self._saved_gain_config.set('usrp', 'gain', str(self.gain))
+               self._saved_gain_config.write(open(self.config_filename, 'w'))
+               self._saved_pll_alpha_config = ConfigParser.ConfigParser()
+               self._saved_pll_alpha_config.read(self.config_filename)
+               if not self._saved_pll_alpha_config.has_section('demod'):
+                       self._saved_pll_alpha_config.add_section('demod')
+               self._saved_pll_alpha_config.set('demod', 'pll_alpha', str(self.pll_alpha))
+               self._saved_pll_alpha_config.write(open(self.config_filename, 'w'))
+               self._saved_sync_alpha_config = ConfigParser.ConfigParser()
+               self._saved_sync_alpha_config.read(self.config_filename)
+               if not self._saved_sync_alpha_config.has_section('demod'):
+                       self._saved_sync_alpha_config.add_section('demod')
+               self._saved_sync_alpha_config.set('demod', 'sync_alpha', str(self.sync_alpha))
+               self._saved_sync_alpha_config.write(open(self.config_filename, 'w'))
+               self._output_filename_config = ConfigParser.ConfigParser()
+               self._output_filename_config.read(self.config_filename)
+               if not self._output_filename_config.has_section('output'):
+                       self._output_filename_config.add_section('output')
+               self._output_filename_config.set('output', 'filename', str(self.output_filename))
+               self._output_filename_config.write(open(self.config_filename, 'w'))
+
+       def set_decim(self, decim):
+               self.decim = decim
+               self.set_sample_rate(64e6/self.decim)
+               self._decim_config = ConfigParser.ConfigParser()
+               self._decim_config.read(self.config_filename)
+               if not self._decim_config.has_section('usrp'):
+                       self._decim_config.add_section('usrp')
+               self._decim_config.set('usrp', 'decim', str(self.decim))
+               self._decim_config.write(open(self.config_filename, 'w'))
+               self.set_decim_text(self.decim)
+               self.usrp_source.set_decim_rate(self.decim)
+
+       def set_sym_rate(self, sym_rate):
+               self.sym_rate = sym_rate
+               self.set_sps(self.sample_rate/self.sym_rate)
+
+       def set_sample_rate(self, sample_rate):
+               self.sample_rate = sample_rate
+               self.set_max_carrier_offset(2*math.pi*100e3/self.sample_rate)
+               self.set_sps(self.sample_rate/self.sym_rate)
+               self.rx_scope.set_sample_rate(self.sample_rate)
+               self.rx_fft.set_sample_rate(self.sample_rate)
+               self.pll_scope.set_sample_rate(self.sample_rate)
+
+       def set_sps(self, sps):
+               self.sps = sps
+               self.set_hs(int(self.sps/2.0))
+
+       def set_side(self, side):
+               self.side = side
+               self.set_side_text(self.side)
+               self._side_config = ConfigParser.ConfigParser()
+               self._side_config.read(self.config_filename)
+               if not self._side_config.has_section('usrp'):
+                       self._side_config.add_section('usrp')
+               self._side_config.set('usrp', 'side', str(self.side))
+               self._side_config.write(open(self.config_filename, 'w'))
+
+       def set_saved_sync_alpha(self, saved_sync_alpha):
+               self.saved_sync_alpha = saved_sync_alpha
+               self.set_sync_alpha(self.saved_sync_alpha)
+
+       def set_saved_pll_alpha(self, saved_pll_alpha):
+               self.saved_pll_alpha = saved_pll_alpha
+               self.set_pll_alpha(self.saved_pll_alpha)
+
+       def set_saved_gain(self, saved_gain):
+               self.saved_gain = saved_gain
+               self.set_gain(self.saved_gain)
+
+       def set_saved_freq(self, saved_freq):
+               self.saved_freq = saved_freq
+               self.set_freq(self.saved_freq)
+
+       def set_sync_alpha(self, sync_alpha):
+               self.sync_alpha = sync_alpha
+               self._sync_alpha_slider.set_value(self.sync_alpha)
+               self._sync_alpha_text_box.set_value(self.sync_alpha)
+               self._saved_sync_alpha_config = ConfigParser.ConfigParser()
+               self._saved_sync_alpha_config.read(self.config_filename)
+               if not self._saved_sync_alpha_config.has_section('demod'):
+                       self._saved_sync_alpha_config.add_section('demod')
+               self._saved_sync_alpha_config.set('demod', 'sync_alpha', str(self.sync_alpha))
+               self._saved_sync_alpha_config.write(open(self.config_filename, 'w'))
+               self.sync.set_alpha(self.sync_alpha)
+               self.sync.set_beta(self.sync_alpha**2/4.0)
+
+       def set_side_text(self, side_text):
+               self.side_text = side_text
+               self._side_text_static_text.set_value(self.side_text)
+
+       def set_pll_alpha(self, pll_alpha):
+               self.pll_alpha = pll_alpha
+               self._pll_alpha_slider.set_value(self.pll_alpha)
+               self._pll_alpha_text_box.set_value(self.pll_alpha)
+               self._saved_pll_alpha_config = ConfigParser.ConfigParser()
+               self._saved_pll_alpha_config.read(self.config_filename)
+               if not self._saved_pll_alpha_config.has_section('demod'):
+                       self._saved_pll_alpha_config.add_section('demod')
+               self._saved_pll_alpha_config.set('demod', 'pll_alpha', str(self.pll_alpha))
+               self._saved_pll_alpha_config.write(open(self.config_filename, 'w'))
+               self.pll.set_alpha(self.pll_alpha)
+               self.pll.set_beta(self.pll_alpha**2/4.0)
+
+       def set_output_filename(self, output_filename):
+               self.output_filename = output_filename
+               self._output_filename_config = ConfigParser.ConfigParser()
+               self._output_filename_config.read(self.config_filename)
+               if not self._output_filename_config.has_section('output'):
+                       self._output_filename_config.add_section('output')
+               self._output_filename_config.set('output', 'filename', str(self.output_filename))
+               self._output_filename_config.write(open(self.config_filename, 'w'))
+
+       def set_max_sync_offset(self, max_sync_offset):
+               self.max_sync_offset = max_sync_offset
+               self.sync.set_max_offset(self.max_sync_offset)
+
+       def set_max_carrier_offset(self, max_carrier_offset):
+               self.max_carrier_offset = max_carrier_offset
+               self.pll.set_max_offset(self.max_carrier_offset)
+
+       def set_hs(self, hs):
+               self.hs = hs
+               self.matched_filter.set_length_and_scale(self.hs, 1.0/self.hs)
+
+       def set_gain(self, gain):
+               self.gain = gain
+               self._gain_slider.set_value(self.gain)
+               self._gain_text_box.set_value(self.gain)
+               self._saved_gain_config = ConfigParser.ConfigParser()
+               self._saved_gain_config.read(self.config_filename)
+               if not self._saved_gain_config.has_section('usrp'):
+                       self._saved_gain_config.add_section('usrp')
+               self._saved_gain_config.set('usrp', 'gain', str(self.gain))
+               self._saved_gain_config.write(open(self.config_filename, 'w'))
+               self.usrp_source.set_gain(self.gain)
+
+       def set_freq(self, freq):
+               self.freq = freq
+               self._freq_text_box.set_value(self.freq)
+               self._saved_freq_config = ConfigParser.ConfigParser()
+               self._saved_freq_config.read(self.config_filename)
+               if not self._saved_freq_config.has_section('usrp'):
+                       self._saved_freq_config.add_section('usrp')
+               self._saved_freq_config.set('usrp', 'freq', str(self.freq))
+               self._saved_freq_config.write(open(self.config_filename, 'w'))
+               self.usrp_source.set_frequency(self.freq)
+               self.rx_fft.set_baseband_freq(self.freq)
+
+       def set_decim_text(self, decim_text):
+               self.decim_text = decim_text
+               self._decim_text_static_text.set_value(self.decim_text)
+
+if __name__ == '__main__':
+       parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+       (options, args) = parser.parse_args()
+       tb = usrp_rx_hrpt()
+       tb.Run(True)
+
diff --git a/gr-noaa/apps/usrp_rx_lrit.grc b/gr-noaa/apps/usrp_rx_lrit.grc
new file mode 100644 (file)
index 0000000..55fe397
--- /dev/null
@@ -0,0 +1,1477 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+  <timestamp>Sat Aug 29 11:26:03 2009</timestamp>
+  <block>
+    <key>options</key>
+    <param>
+      <key>id</key>
+      <value>usrp_rx_lrit</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>USRP LRIT Receiver</value>
+    </param>
+    <param>
+      <key>author</key>
+      <value></value>
+    </param>
+    <param>
+      <key>description</key>
+      <value></value>
+    </param>
+    <param>
+      <key>window_size</key>
+      <value>4095, 4095</value>
+    </param>
+    <param>
+      <key>generate_options</key>
+      <value>wx_gui</value>
+    </param>
+    <param>
+      <key>category</key>
+      <value>Custom</value>
+    </param>
+    <param>
+      <key>run</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(10, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>64e6/decim</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(10, 81)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>symbol_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>293e3</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(11, 148)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>sps</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>samp_rate/symbol_rate</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(12, 214)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_text_box</key>
+    <param>
+      <key>id</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Decim</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_decim</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>int_converter</value>
+    </param>
+    <param>
+      <key>formatter</key>
+      <value>None</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(243, 13)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>wxgui_scopesink2_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Waveform</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>20.0/samp_rate</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(434, 551)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_agc_xx</key>
+    <param>
+      <key>id</key>
+      <value>gr_agc_xx_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>rate</key>
+      <value>1e-6</value>
+    </param>
+    <param>
+      <key>reference</key>
+      <value>1.0</value>
+    </param>
+    <param>
+      <key>gain</key>
+      <value>1.0/32767.0</value>
+    </param>
+    <param>
+      <key>max_gain</key>
+      <value>1.0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(261, 493)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>root_raised_cosine_filter</key>
+    <param>
+      <key>id</key>
+      <value>root_raised_cosine_filter_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>fir_filter_ccf</value>
+    </param>
+    <param>
+      <key>decim</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>interp</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>gain</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>sym_rate</key>
+      <value>symbol_rate</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>ntaps</key>
+      <value>50</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(618, 373)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>usrp_simple_source_x</key>
+    <param>
+      <key>id</key>
+      <value>usrp_simple_source_x_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>format</key>
+      <value></value>
+    </param>
+    <param>
+      <key>which</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>decimation</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>frequency</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>lo_offset</key>
+      <value>float('inf')</value>
+    </param>
+    <param>
+      <key>gain</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>side</key>
+      <value>B</value>
+    </param>
+    <param>
+      <key>rx_ant</key>
+      <value>RXA</value>
+    </param>
+    <param>
+      <key>hb_filters</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(11, 477)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_fftsink2</key>
+    <param>
+      <key>id</key>
+      <value>wxgui_fftsink2_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Spectrum</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>baseband_freq</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>y_per_div</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>y_divs</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>ref_level</key>
+      <value>50</value>
+    </param>
+    <param>
+      <key>fft_size</key>
+      <value>1024</value>
+    </param>
+    <param>
+      <key>fft_rate</key>
+      <value>30</value>
+    </param>
+    <param>
+      <key>peak_hold</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>average</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>avg_alpha</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(434, 337)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_throttle</key>
+    <param>
+      <key>id</key>
+      <value>gr_throttle_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>samples_per_second</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(181, 663)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>wxgui_scopesink2_1</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Scope Plot</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0.4</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>20.0/samp_rate</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1126, 251)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_probe_mpsk_snr_c</key>
+    <param>
+      <key>id</key>
+      <value>gr_probe_mpsk_snr_c_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>snr</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>0.0001</value>
+    </param>
+    <param>
+      <key>probe_rate</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1126, 723)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_numbersink2</key>
+    <param>
+      <key>id</key>
+      <value>wxgui_numbersink2_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>SNR</value>
+    </param>
+    <param>
+      <key>units</key>
+      <value>dB</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>min_value</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max_value</key>
+      <value>30</value>
+    </param>
+    <param>
+      <key>factor</key>
+      <value>1.0</value>
+    </param>
+    <param>
+      <key>decimal_places</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>ref_level</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>number_rate</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>peak_hold</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>average</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>avg_alpha</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>show_gauge</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>2, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1335, 651)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_mpsk_receiver_cc</key>
+    <param>
+      <key>id</key>
+      <value>gr_mpsk_receiver_cc_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>M</key>
+      <value>2</value>
+    </param>
+    <param>
+      <key>theta</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>alpha</key>
+      <value>costas_alpha</value>
+    </param>
+    <param>
+      <key>beta</key>
+      <value>costas_alpha*costas_alpha/4.0</value>
+    </param>
+    <param>
+      <key>fmin</key>
+      <value>-0.05</value>
+    </param>
+    <param>
+      <key>fmax</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>mu</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>gain_mu</key>
+      <value>gain_mu</value>
+    </param>
+    <param>
+      <key>omega</key>
+      <value>sps</value>
+    </param>
+    <param>
+      <key>gain_omega</key>
+      <value>gain_mu*gain_mu/4.0</value>
+    </param>
+    <param>
+      <key>omega_relative_limit</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(881, 437)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_complex_to_real</key>
+    <param>
+      <key>id</key>
+      <value>gr_complex_to_real_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1133, 521)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_char_to_float</key>
+    <param>
+      <key>id</key>
+      <value>gr_char_to_float_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1523, 521)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_binary_slicer_fb</key>
+    <param>
+      <key>id</key>
+      <value>gr_binary_slicer_fb_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1343, 521)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_add_const_vxx</key>
+    <param>
+      <key>id</key>
+      <value>gr_add_const_vxx_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>const</key>
+      <value>48.0</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1707, 517)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_float_to_char</key>
+    <param>
+      <key>id</key>
+      <value>gr_float_to_char_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1878, 521)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_file_sink</key>
+    <param>
+      <key>id</key>
+      <value>gr_file_sink_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>file</key>
+      <value>bits.dat</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>byte</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(2059, 517)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_file_source</key>
+    <param>
+      <key>id</key>
+      <value>gr_file_source_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>file</key>
+      <value>lrit.dat</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>repeat</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(11, 655)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>notebook</key>
+    <param>
+      <key>id</key>
+      <value>displays</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.NB_TOP</value>
+    </param>
+    <param>
+      <key>labels</key>
+      <value>['USRP RX', 'Costas Output']</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>2, 0, 1, 3</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(14, 351)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_decim</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>160</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>int</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>main</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>decim</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(246, 172)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Gain</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_gain</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>115</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>115</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 1, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(411, 11)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_gain</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>33</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>main</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(412, 172)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Frequency</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_freq</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>135e6</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>139e6</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>400</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 2, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(574, 12)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_freq</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>137e6</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>main</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>freq</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(576, 170)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>costas_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Costas Alpha</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_costas_alpha</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>100</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(738, 13)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_costas_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.005</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>main</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>costas_alpha</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>costas_alpha</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(739, 170)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_config</key>
+    <param>
+      <key>id</key>
+      <value>saved_gain_mu</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.005</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>real</value>
+    </param>
+    <param>
+      <key>config_file</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>section</key>
+      <value>main</value>
+    </param>
+    <param>
+      <key>option</key>
+      <value>gain_mu</value>
+    </param>
+    <param>
+      <key>writeback</key>
+      <value>gain_mu</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(900, 170)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>gain_mu</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Gain Mu</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>saved_gain_mu</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>100</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 1, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(902, 13)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>config_filename</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>"usrp_rx_lrit.cfg"</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(13, 283)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <connection>
+    <source_block_id>usrp_simple_source_x_0</source_block_id>
+    <sink_block_id>gr_agc_xx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_agc_xx_0</source_block_id>
+    <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_file_source_0</source_block_id>
+    <sink_block_id>gr_throttle_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_throttle_0</source_block_id>
+    <sink_block_id>gr_agc_xx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_probe_mpsk_snr_c_0</source_block_id>
+    <sink_block_id>wxgui_numbersink2_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_mpsk_receiver_cc_0</source_block_id>
+    <sink_block_id>gr_probe_mpsk_snr_c_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_agc_xx_0</source_block_id>
+    <sink_block_id>gr_mpsk_receiver_cc_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_mpsk_receiver_cc_0</source_block_id>
+    <sink_block_id>wxgui_scopesink2_1</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_agc_xx_0</source_block_id>
+    <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_mpsk_receiver_cc_0</source_block_id>
+    <sink_block_id>gr_complex_to_real_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_complex_to_real_0</source_block_id>
+    <sink_block_id>gr_binary_slicer_fb_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_binary_slicer_fb_0</source_block_id>
+    <sink_block_id>gr_char_to_float_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_char_to_float_0</source_block_id>
+    <sink_block_id>gr_add_const_vxx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_add_const_vxx_0</source_block_id>
+    <sink_block_id>gr_float_to_char_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gr_float_to_char_0</source_block_id>
+    <sink_block_id>gr_file_sink_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+</flow_graph>
diff --git a/gr-noaa/apps/usrp_rx_lrit.py b/gr-noaa/apps/usrp_rx_lrit.py
new file mode 100755 (executable)
index 0000000..bc313e3
--- /dev/null
@@ -0,0 +1,399 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: USRP LRIT Receiver
+# Generated: Sat Aug 29 11:26:03 2009
+##################################################
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import fftsink2
+from gnuradio.wxgui import forms
+from gnuradio.wxgui import numbersink2
+from gnuradio.wxgui import scopesink2
+from grc_gnuradio import blks2 as grc_blks2
+from grc_gnuradio import wxgui as grc_wxgui
+from optparse import OptionParser
+import ConfigParser
+import wx
+
+class usrp_rx_lrit(grc_wxgui.top_block_gui):
+
+       def __init__(self):
+               grc_wxgui.top_block_gui.__init__(self, title="USRP LRIT Receiver")
+
+               ##################################################
+               # Variables
+               ##################################################
+               self.config_filename = config_filename = "usrp_rx_lrit.cfg"
+               self._saved_decim_config = ConfigParser.ConfigParser()
+               self._saved_decim_config.read(config_filename)
+               try: saved_decim = self._saved_decim_config.getint("main", "decim")
+               except: saved_decim = 160
+               self.saved_decim = saved_decim
+               self.decim = decim = saved_decim
+               self.symbol_rate = symbol_rate = 293e3
+               self._saved_gain_mu_config = ConfigParser.ConfigParser()
+               self._saved_gain_mu_config.read(config_filename)
+               try: saved_gain_mu = self._saved_gain_mu_config.getfloat("main", "gain_mu")
+               except: saved_gain_mu = 0.005
+               self.saved_gain_mu = saved_gain_mu
+               self._saved_gain_config = ConfigParser.ConfigParser()
+               self._saved_gain_config.read(config_filename)
+               try: saved_gain = self._saved_gain_config.getfloat("main", "gain")
+               except: saved_gain = 33
+               self.saved_gain = saved_gain
+               self._saved_freq_config = ConfigParser.ConfigParser()
+               self._saved_freq_config.read(config_filename)
+               try: saved_freq = self._saved_freq_config.getfloat("main", "freq")
+               except: saved_freq = 137e6
+               self.saved_freq = saved_freq
+               self._saved_costas_alpha_config = ConfigParser.ConfigParser()
+               self._saved_costas_alpha_config.read(config_filename)
+               try: saved_costas_alpha = self._saved_costas_alpha_config.getfloat("main", "costas_alpha")
+               except: saved_costas_alpha = 0.005
+               self.saved_costas_alpha = saved_costas_alpha
+               self.samp_rate = samp_rate = 64e6/decim
+               self.sps = sps = samp_rate/symbol_rate
+               self.gain_mu = gain_mu = saved_gain_mu
+               self.gain = gain = saved_gain
+               self.freq = freq = saved_freq
+               self.costas_alpha = costas_alpha = saved_costas_alpha
+
+               ##################################################
+               # Notebooks
+               ##################################################
+               self.displays = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
+               self.displays.AddPage(grc_wxgui.Panel(self.displays), "USRP RX")
+               self.displays.AddPage(grc_wxgui.Panel(self.displays), "Costas Output")
+               self.GridAdd(self.displays, 2, 0, 1, 3)
+
+               ##################################################
+               # Controls
+               ##################################################
+               self._decim_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       value=self.decim,
+                       callback=self.set_decim,
+                       label="Decim",
+                       converter=forms.int_converter(),
+               )
+               self.GridAdd(self._decim_text_box, 0, 0, 1, 1)
+               _gain_mu_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._gain_mu_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_gain_mu_sizer,
+                       value=self.gain_mu,
+                       callback=self.set_gain_mu,
+                       label="Gain Mu",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._gain_mu_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_gain_mu_sizer,
+                       value=self.gain_mu,
+                       callback=self.set_gain_mu,
+                       minimum=0,
+                       maximum=0.5,
+                       num_steps=100,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_gain_mu_sizer, 1, 1, 1, 1)
+               _gain_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._gain_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_gain_sizer,
+                       value=self.gain,
+                       callback=self.set_gain,
+                       label="Gain",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._gain_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_gain_sizer,
+                       value=self.gain,
+                       callback=self.set_gain,
+                       minimum=0,
+                       maximum=115,
+                       num_steps=115,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_gain_sizer, 0, 1, 1, 1)
+               _freq_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._freq_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_freq_sizer,
+                       value=self.freq,
+                       callback=self.set_freq,
+                       label="Frequency",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._freq_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_freq_sizer,
+                       value=self.freq,
+                       callback=self.set_freq,
+                       minimum=135e6,
+                       maximum=139e6,
+                       num_steps=400,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_freq_sizer, 0, 2, 1, 1)
+               _costas_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
+               self._costas_alpha_text_box = forms.text_box(
+                       parent=self.GetWin(),
+                       sizer=_costas_alpha_sizer,
+                       value=self.costas_alpha,
+                       callback=self.set_costas_alpha,
+                       label="Costas Alpha",
+                       converter=forms.float_converter(),
+                       proportion=0,
+               )
+               self._costas_alpha_slider = forms.slider(
+                       parent=self.GetWin(),
+                       sizer=_costas_alpha_sizer,
+                       value=self.costas_alpha,
+                       callback=self.set_costas_alpha,
+                       minimum=0,
+                       maximum=0.5,
+                       num_steps=100,
+                       style=wx.SL_HORIZONTAL,
+                       cast=float,
+                       proportion=1,
+               )
+               self.GridAdd(_costas_alpha_sizer, 1, 0, 1, 1)
+
+               ##################################################
+               # Blocks
+               ##################################################
+               self.gr_add_const_vxx_0 = gr.add_const_vff((48.0, ))
+               self.gr_agc_xx_0 = gr.agc_cc(1e-6, 1.0, 1.0/32767.0, 1.0)
+               self.gr_binary_slicer_fb_0 = gr.binary_slicer_fb()
+               self.gr_char_to_float_0 = gr.char_to_float()
+               self.gr_complex_to_real_0 = gr.complex_to_real(1)
+               self.gr_file_sink_0 = gr.file_sink(gr.sizeof_char*1, "bits.dat")
+               self.gr_file_source_0 = gr.file_source(gr.sizeof_gr_complex*1, "lrit.dat", False)
+               self.gr_float_to_char_0 = gr.float_to_char()
+               self.gr_mpsk_receiver_cc_0 = gr.mpsk_receiver_cc(2, 0, costas_alpha, costas_alpha*costas_alpha/4.0, -0.05, 0.05, 0.5, gain_mu, sps, gain_mu*gain_mu/4.0, 0.05)
+               self.gr_probe_mpsk_snr_c_0 = grc_blks2.probe_mpsk_snr_c(
+                       type='snr',
+                       alpha=0.0001,
+                       probe_rate=10,
+               )
+               self.gr_throttle_0 = gr.throttle(gr.sizeof_gr_complex*1, samp_rate)
+               self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
+                       self.displays.GetPage(0).GetWin(),
+                       baseband_freq=freq,
+                       y_per_div=10,
+                       y_divs=10,
+                       ref_level=50,
+                       sample_rate=samp_rate,
+                       fft_size=1024,
+                       fft_rate=30,
+                       average=False,
+                       avg_alpha=None,
+                       title="Spectrum",
+                       peak_hold=False,
+               )
+               self.displays.GetPage(0).GridAdd(self.wxgui_fftsink2_0.win, 0, 0, 1, 1)
+               self.wxgui_numbersink2_0 = numbersink2.number_sink_f(
+                       self.displays.GetPage(1).GetWin(),
+                       unit="dB",
+                       minval=0,
+                       maxval=30,
+                       factor=1.0,
+                       decimal_places=1,
+                       ref_level=0,
+                       sample_rate=10,
+                       number_rate=10,
+                       average=False,
+                       avg_alpha=None,
+                       label="SNR",
+                       peak_hold=False,
+                       show_gauge=True,
+               )
+               self.displays.GetPage(1).GridAdd(self.wxgui_numbersink2_0.win, 2, 0, 1, 1)
+               self.wxgui_scopesink2_0 = scopesink2.scope_sink_c(
+                       self.displays.GetPage(0).GetWin(),
+                       title="Waveform",
+                       sample_rate=samp_rate,
+                       v_scale=0.5,
+                       t_scale=20.0/samp_rate,
+                       ac_couple=False,
+                       xy_mode=True,
+                       num_inputs=1,
+               )
+               self.displays.GetPage(0).GridAdd(self.wxgui_scopesink2_0.win, 1, 0, 1, 1)
+               self.wxgui_scopesink2_1 = scopesink2.scope_sink_c(
+                       self.displays.GetPage(1).GetWin(),
+                       title="Scope Plot",
+                       sample_rate=samp_rate,
+                       v_scale=0.4,
+                       t_scale=20.0/samp_rate,
+                       ac_couple=False,
+                       xy_mode=True,
+                       num_inputs=1,
+               )
+               self.displays.GetPage(1).GridAdd(self.wxgui_scopesink2_1.win, 0, 0, 1, 1)
+
+               ##################################################
+               # Connections
+               ##################################################
+               self.connect((self.gr_agc_xx_0, 0), (self.wxgui_scopesink2_0, 0))
+               self.connect((self.gr_file_source_0, 0), (self.gr_throttle_0, 0))
+               self.connect((self.gr_throttle_0, 0), (self.gr_agc_xx_0, 0))
+               self.connect((self.gr_probe_mpsk_snr_c_0, 0), (self.wxgui_numbersink2_0, 0))
+               self.connect((self.gr_mpsk_receiver_cc_0, 0), (self.gr_probe_mpsk_snr_c_0, 0))
+               self.connect((self.gr_agc_xx_0, 0), (self.gr_mpsk_receiver_cc_0, 0))
+               self.connect((self.gr_mpsk_receiver_cc_0, 0), (self.wxgui_scopesink2_1, 0))
+               self.connect((self.gr_agc_xx_0, 0), (self.wxgui_fftsink2_0, 0))
+               self.connect((self.gr_mpsk_receiver_cc_0, 0), (self.gr_complex_to_real_0, 0))
+               self.connect((self.gr_complex_to_real_0, 0), (self.gr_binary_slicer_fb_0, 0))
+               self.connect((self.gr_binary_slicer_fb_0, 0), (self.gr_char_to_float_0, 0))
+               self.connect((self.gr_char_to_float_0, 0), (self.gr_add_const_vxx_0, 0))
+               self.connect((self.gr_add_const_vxx_0, 0), (self.gr_float_to_char_0, 0))
+               self.connect((self.gr_float_to_char_0, 0), (self.gr_file_sink_0, 0))
+
+       def set_config_filename(self, config_filename):
+               self.config_filename = config_filename
+               self._saved_decim_config = ConfigParser.ConfigParser()
+               self._saved_decim_config.read(self.config_filename)
+               if not self._saved_decim_config.has_section("main"):
+                       self._saved_decim_config.add_section("main")
+               self._saved_decim_config.set("main", "decim", str(self.decim))
+               self._saved_decim_config.write(open(self.config_filename, 'w'))
+               self._saved_gain_config = ConfigParser.ConfigParser()
+               self._saved_gain_config.read(self.config_filename)
+               if not self._saved_gain_config.has_section("main"):
+                       self._saved_gain_config.add_section("main")
+               self._saved_gain_config.set("main", "gain", str(self.gain))
+               self._saved_gain_config.write(open(self.config_filename, 'w'))
+               self._saved_freq_config = ConfigParser.ConfigParser()
+               self._saved_freq_config.read(self.config_filename)
+               if not self._saved_freq_config.has_section("main"):
+                       self._saved_freq_config.add_section("main")
+               self._saved_freq_config.set("main", "freq", str(self.freq))
+               self._saved_freq_config.write(open(self.config_filename, 'w'))
+               self._saved_costas_alpha_config = ConfigParser.ConfigParser()
+               self._saved_costas_alpha_config.read(self.config_filename)
+               if not self._saved_costas_alpha_config.has_section("main"):
+                       self._saved_costas_alpha_config.add_section("main")
+               self._saved_costas_alpha_config.set("main", "costas_alpha", str(self.costas_alpha))
+               self._saved_costas_alpha_config.write(open(self.config_filename, 'w'))
+               self._saved_gain_mu_config = ConfigParser.ConfigParser()
+               self._saved_gain_mu_config.read(self.config_filename)
+               if not self._saved_gain_mu_config.has_section("main"):
+                       self._saved_gain_mu_config.add_section("main")
+               self._saved_gain_mu_config.set("main", "gain_mu", str(self.gain_mu))
+               self._saved_gain_mu_config.write(open(self.config_filename, 'w'))
+
+       def set_saved_decim(self, saved_decim):
+               self.saved_decim = saved_decim
+               self.set_decim(self.saved_decim)
+
+       def set_decim(self, decim):
+               self.decim = decim
+               self.set_samp_rate(64e6/self.decim)
+               self._decim_text_box.set_value(self.decim)
+               self._saved_decim_config = ConfigParser.ConfigParser()
+               self._saved_decim_config.read(self.config_filename)
+               if not self._saved_decim_config.has_section("main"):
+                       self._saved_decim_config.add_section("main")
+               self._saved_decim_config.set("main", "decim", str(self.decim))
+               self._saved_decim_config.write(open(self.config_filename, 'w'))
+
+       def set_symbol_rate(self, symbol_rate):
+               self.symbol_rate = symbol_rate
+               self.set_sps(self.samp_rate/self.symbol_rate)
+
+       def set_saved_gain_mu(self, saved_gain_mu):
+               self.saved_gain_mu = saved_gain_mu
+               self.set_gain_mu(self.saved_gain_mu)
+
+       def set_saved_gain(self, saved_gain):
+               self.saved_gain = saved_gain
+               self.set_gain(self.saved_gain)
+
+       def set_saved_freq(self, saved_freq):
+               self.saved_freq = saved_freq
+               self.set_freq(self.saved_freq)
+
+       def set_saved_costas_alpha(self, saved_costas_alpha):
+               self.saved_costas_alpha = saved_costas_alpha
+               self.set_costas_alpha(self.saved_costas_alpha)
+
+       def set_samp_rate(self, samp_rate):
+               self.samp_rate = samp_rate
+               self.set_sps(self.samp_rate/self.symbol_rate)
+               self.wxgui_scopesink2_0.set_sample_rate(self.samp_rate)
+               self.wxgui_fftsink2_0.set_sample_rate(self.samp_rate)
+               self.wxgui_scopesink2_1.set_sample_rate(self.samp_rate)
+
+       def set_sps(self, sps):
+               self.sps = sps
+               self.gr_mpsk_receiver_cc_0.set_omega(self.sps)
+
+       def set_gain_mu(self, gain_mu):
+               self.gain_mu = gain_mu
+               self.gr_mpsk_receiver_cc_0.set_gain_mu(self.gain_mu)
+               self.gr_mpsk_receiver_cc_0.set_gain_omega(self.gain_mu*self.gain_mu/4.0)
+               self._saved_gain_mu_config = ConfigParser.ConfigParser()
+               self._saved_gain_mu_config.read(self.config_filename)
+               if not self._saved_gain_mu_config.has_section("main"):
+                       self._saved_gain_mu_config.add_section("main")
+               self._saved_gain_mu_config.set("main", "gain_mu", str(self.gain_mu))
+               self._saved_gain_mu_config.write(open(self.config_filename, 'w'))
+               self._gain_mu_slider.set_value(self.gain_mu)
+               self._gain_mu_text_box.set_value(self.gain_mu)
+
+       def set_gain(self, gain):
+               self.gain = gain
+               self._gain_slider.set_value(self.gain)
+               self._gain_text_box.set_value(self.gain)
+               self._saved_gain_config = ConfigParser.ConfigParser()
+               self._saved_gain_config.read(self.config_filename)
+               if not self._saved_gain_config.has_section("main"):
+                       self._saved_gain_config.add_section("main")
+               self._saved_gain_config.set("main", "gain", str(self.gain))
+               self._saved_gain_config.write(open(self.config_filename, 'w'))
+
+       def set_freq(self, freq):
+               self.freq = freq
+               self.wxgui_fftsink2_0.set_baseband_freq(self.freq)
+               self._freq_slider.set_value(self.freq)
+               self._freq_text_box.set_value(self.freq)
+               self._saved_freq_config = ConfigParser.ConfigParser()
+               self._saved_freq_config.read(self.config_filename)
+               if not self._saved_freq_config.has_section("main"):
+                       self._saved_freq_config.add_section("main")
+               self._saved_freq_config.set("main", "freq", str(self.freq))
+               self._saved_freq_config.write(open(self.config_filename, 'w'))
+
+       def set_costas_alpha(self, costas_alpha):
+               self.costas_alpha = costas_alpha
+               self.gr_mpsk_receiver_cc_0.set_alpha(self.costas_alpha)
+               self.gr_mpsk_receiver_cc_0.set_beta(self.costas_alpha*self.costas_alpha/4.0)
+               self._costas_alpha_slider.set_value(self.costas_alpha)
+               self._costas_alpha_text_box.set_value(self.costas_alpha)
+               self._saved_costas_alpha_config = ConfigParser.ConfigParser()
+               self._saved_costas_alpha_config.read(self.config_filename)
+               if not self._saved_costas_alpha_config.has_section("main"):
+                       self._saved_costas_alpha_config.add_section("main")
+               self._saved_costas_alpha_config.set("main", "costas_alpha", str(self.costas_alpha))
+               self._saved_costas_alpha_config.write(open(self.config_filename, 'w'))
+
+if __name__ == '__main__':
+       parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+       (options, args) = parser.parse_args()
+       tb = usrp_rx_lrit()
+       tb.Run(True)
+
diff --git a/gr-noaa/grc/.gitignore b/gr-noaa/grc/.gitignore
new file mode 100644 (file)
index 0000000..70845e0
--- /dev/null
@@ -0,0 +1 @@
+Makefile.in
diff --git a/gr-noaa/grc/Makefile.am b/gr-noaa/grc/Makefile.am
new file mode 100644 (file)
index 0000000..1f05647
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# 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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+grcblocksdir = $(prefix)/share/gnuradio/grc/blocks
+
+dist_grcblocks_DATA = \
+       noaa_hrpt_decoder.xml \
+       noaa_hrpt_deframer.xml \
+       noaa_hrpt_pll_cf.xml \
+       noaa_hrpt_sync_fb.xml
+
diff --git a/gr-noaa/grc/noaa_hrpt_decoder.xml b/gr-noaa/grc/noaa_hrpt_decoder.xml
new file mode 100644 (file)
index 0000000..183d72a
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<block>
+  <name>HRPT Decoder</name>
+  <key>noaa_hrpt_decoder</key>
+  <category>NOAA</category>
+  <import>from gnuradio import noaa</import>
+  <make>noaa.hrpt_decoder()</make>
+  <sink>
+    <name>in</name>
+    <type>short</type>
+  </sink>
+</block>
diff --git a/gr-noaa/grc/noaa_hrpt_deframer.xml b/gr-noaa/grc/noaa_hrpt_deframer.xml
new file mode 100644 (file)
index 0000000..af36abf
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<block>
+  <name>HRPT Deframer</name>
+  <key>noaa_hrpt_deframer</key>
+  <category>NOAA</category>
+  <import>from gnuradio import noaa</import>
+  <make>noaa.hrpt_deframer()</make>
+  <sink>
+    <name>in</name>
+    <type>byte</type>
+  </sink>
+  <source>
+    <name>out</name>
+    <type>short</type>
+  </source>
+</block>
diff --git a/gr-noaa/grc/noaa_hrpt_pll_cf.xml b/gr-noaa/grc/noaa_hrpt_pll_cf.xml
new file mode 100644 (file)
index 0000000..bbe15e8
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<block>
+  <name>HRPT PLL</name>
+  <key>noaa_hrpt_pll_cf</key>
+  <category>NOAA</category>
+  <import>from gnuradio import noaa</import>
+  <make>noaa.hrpt_pll_cf($alpha, $beta, $max_offset)</make>
+  <callback>set_alpha($alpha)</callback>
+  <callback>set_beta($beta)</callback>
+  <callback>set_max_offset($max_offset)</callback>
+  <param>
+    <name>Alpha</name>
+    <key>alpha</key>
+    <type>real</type>
+  </param>
+  <param>
+    <name>Beta</name>
+    <key>beta</key>
+    <type>real</type>
+  </param>
+  <param>
+    <name>Max Offset</name>
+    <key>max_offset</key>
+    <type>real</type>
+  </param>
+  <sink>
+    <name>in</name>
+    <type>complex</type>
+  </sink>
+  <source>
+    <name>out</name>
+    <type>float</type>
+  </source>
+</block>
diff --git a/gr-noaa/grc/noaa_hrpt_sync_fb.xml b/gr-noaa/grc/noaa_hrpt_sync_fb.xml
new file mode 100644 (file)
index 0000000..e066e34
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<block>
+  <name>HRPT SYNC</name>
+  <key>noaa_hrpt_sync_fb</key>
+  <category>NOAA</category>
+  <import>from gnuradio import noaa</import>
+  <make>noaa.hrpt_sync_fb($alpha, $beta, $sps, $max_offset)</make>
+  <callback>set_alpha($alpha)</callback>
+  <callback>set_beta($beta)</callback>
+  <callback>set_max_offset($max_offset)</callback>
+  <param>
+    <name>Alpha</name>
+    <key>alpha</key>
+    <type>real</type>
+  </param>
+  <param>
+    <name>Beta</name>
+    <key>beta</key>
+    <type>real</type>
+  </param>
+  <param>
+    <name>Samples/Symbol</name>
+    <key>sps</key>
+    <type>real</type>
+  </param>
+  <param>
+    <name>Max Offset</name>
+    <key>max_offset</key>
+    <type>real</type>
+  </param>
+  <sink>
+    <name>in</name>
+    <type>float</type>
+  </sink>
+  <source>
+    <name>out</name>
+    <type>byte</type>
+  </source>
+</block>
diff --git a/gr-noaa/lib/.gitignore b/gr-noaa/lib/.gitignore
new file mode 100644 (file)
index 0000000..02b0523
--- /dev/null
@@ -0,0 +1,4 @@
+Makefile
+Makefile.in
+.deps
+.libs
diff --git a/gr-noaa/lib/Makefile.am b/gr-noaa/lib/Makefile.am
new file mode 100644 (file)
index 0000000..6435d19
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# 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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = \
+       $(STD_DEFINES_AND_INCLUDES) \
+       $(WITH_INCLUDES)
+
+lib_LTLIBRARIES = \
+       libgnuradio-noaa.la
+
+libgnuradio_noaa_la_SOURCES = \
+       noaa_hrpt_decoder.cc \
+       noaa_hrpt_deframer.cc \
+       noaa_hrpt_pll_cf.cc \
+       noaa_hrpt_sync_fb.cc
+
+libgnuradio_noaa_la_LIBADD = \
+       $(GNURADIO_CORE_LA)
+
+libgnuradio_noaa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
+
+grinclude_HEADERS = \
+       noaa_hrpt_decoder.h \
+       noaa_hrpt_deframer.h \
+       noaa_hrpt_pll_cf.h \
+       noaa_hrpt_sync_fb.h
diff --git a/gr-noaa/lib/noaa_hrpt_decoder.cc b/gr-noaa/lib/noaa_hrpt_decoder.cc
new file mode 100644 (file)
index 0000000..8cfaa91
--- /dev/null
@@ -0,0 +1,77 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <noaa_hrpt_decoder.h>
+#include <gr_io_signature.h>
+
+#define SYNC1 0x0284
+#define SYNC2 0x016F
+#define SYNC3 0x035C
+#define SYNC4 0x019D
+#define SYNC5 0x020F
+#define SYNC6 0x0095
+
+noaa_hrpt_decoder_sptr
+noaa_make_hrpt_decoder()
+{
+  return gnuradio::get_initial_sptr(new noaa_hrpt_decoder());
+}
+
+noaa_hrpt_decoder::noaa_hrpt_decoder()
+  : gr_sync_block("noaa_hrpt_decoder",
+                 gr_make_io_signature(1, 1, sizeof(short)),
+                 gr_make_io_signature(0, 0, 0))
+{
+  d_word_count = 0;
+}
+
+int
+noaa_hrpt_decoder::work(int noutput_items,
+                       gr_vector_const_void_star &input_items,
+                       gr_vector_void_star &output_items)
+{
+  const unsigned short *in = (const unsigned short*)input_items[0];
+
+  int i = 0;
+  while (i < noutput_items) {
+    unsigned short word = in[i++];
+    d_word_count++;
+    //fprintf(stderr, "%5u:  ", d_word_count);
+    for (int pos = 0; pos < 10; pos++) {
+      char ch = (word & (1 << 9)) ? '1' : '0';
+      word = word << 1;
+      //fprintf(stderr, "%c ", ch);
+    }
+    //fprintf(stderr, "\n");
+
+    if (d_word_count == 11090) {
+      d_word_count = 0;
+      //fprintf(stderr, "\n");
+    }
+  }
+
+  return i;
+}
diff --git a/gr-noaa/lib/noaa_hrpt_decoder.h b/gr-noaa/lib/noaa_hrpt_decoder.h
new file mode 100644 (file)
index 0000000..305243b
--- /dev/null
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_NOAA_HRPT_DECODER_H
+#define INCLUDED_NOAA_HRPT_DECODER_H
+
+#include <gr_sync_block.h>
+
+class noaa_hrpt_decoder;
+typedef boost::shared_ptr<noaa_hrpt_decoder> noaa_hrpt_decoder_sptr;
+
+noaa_hrpt_decoder_sptr
+noaa_make_hrpt_decoder();
+
+class noaa_hrpt_decoder : public gr_sync_block
+{
+  friend noaa_hrpt_decoder_sptr noaa_make_hrpt_decoder();
+  noaa_hrpt_decoder();
+
+  unsigned int d_word_count;
+public:
+  int work(int noutput_items,
+          gr_vector_const_void_star &input_items,
+          gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_NOAA_HRPT_DECODER_H */
diff --git a/gr-noaa/lib/noaa_hrpt_deframer.cc b/gr-noaa/lib/noaa_hrpt_deframer.cc
new file mode 100644 (file)
index 0000000..89486aa
--- /dev/null
@@ -0,0 +1,125 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <noaa_hrpt_deframer.h>
+#include <gr_io_signature.h>
+#include <cstring>
+
+#define ST_IDLE   0
+#define ST_SYNCED 1
+
+#define SYNC1 0x0284
+#define SYNC2 0x016F
+#define SYNC3 0x035C
+#define SYNC4 0x019D
+#define SYNC5 0x020F
+#define SYNC6 0x0095
+
+#define HRPT_MINOR_FRAME_SYNC  0x0A116FD719D83C95LL
+
+static int frames_seen = 0;
+
+noaa_hrpt_deframer_sptr
+noaa_make_hrpt_deframer()
+{
+  return gnuradio::get_initial_sptr(new noaa_hrpt_deframer());
+}
+
+noaa_hrpt_deframer::noaa_hrpt_deframer()
+  : gr_block("noaa_hrpt_deframer",
+            gr_make_io_signature(1, 1, sizeof(char)),
+            gr_make_io_signature(1, 1, sizeof(short)))
+{
+  set_output_multiple(6); // room for writing full sync when received
+  enter_idle();
+}
+
+void
+noaa_hrpt_deframer::enter_idle()
+{
+  d_state = ST_IDLE;
+}
+
+void
+noaa_hrpt_deframer::enter_synced()
+{
+  d_state = ST_SYNCED;
+  d_bit_count = HRPT_BITS_PER_WORD;
+  d_word_count = HRPT_MINOR_FRAME_WORDS-HRPT_SYNC_WORDS;
+  d_word = 0;
+}
+
+int
+noaa_hrpt_deframer::general_work(int noutput_items,
+                                gr_vector_int &ninput_items,
+                                gr_vector_const_void_star &input_items,
+                                gr_vector_void_star &output_items)
+{
+  int ninputs = ninput_items[0];
+  const char *in = (const char *)input_items[0];
+  unsigned short *out = (unsigned short *)output_items[0];
+
+  int i = 0, j = 0;
+  while (i < ninputs && j < noutput_items) {
+    char bit = in[i++];
+
+    switch (d_state) {
+    case ST_IDLE:
+      d_shifter = (d_shifter << 1) | bit; // MSB transmitted first
+      
+      if ((d_shifter & 0x0FFFFFFFFFFFFFFFLL) == HRPT_MINOR_FRAME_SYNC) {
+       fprintf(stderr, "SYNC #%i", frames_seen++);
+       out[j++] = SYNC1;
+       out[j++] = SYNC2;
+       out[j++] = SYNC3;
+       out[j++] = SYNC4;
+       out[j++] = SYNC5;
+       out[j++] = SYNC6;
+       enter_synced();
+      }
+      break;
+
+    case ST_SYNCED:
+      d_word = (d_word << 1) | bit; // MSB transmitted first
+      if (--d_bit_count == 0) {
+       out[j++] = d_word;
+       d_word = 0;
+       d_bit_count = HRPT_BITS_PER_WORD;
+       if (--d_word_count == 0) {
+         fprintf(stderr, "...done\n");
+         enter_idle();
+       }
+      }
+      break;
+
+    default:
+      throw std::runtime_error("noaa_hrpt_deframer: bad state\n");
+    }
+  }
+
+  consume_each(i);
+  return j;
+}
diff --git a/gr-noaa/lib/noaa_hrpt_deframer.h b/gr-noaa/lib/noaa_hrpt_deframer.h
new file mode 100644 (file)
index 0000000..0aeb16a
--- /dev/null
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_NOAA_HRPT_DEFRAMER_H
+#define INCLUDED_NOAA_HRPT_DEFRAMER_H
+
+#define HRPT_SYNC_WORDS        6
+#define HRPT_MINOR_FRAME_WORDS 11090
+#define HRPT_BITS_PER_WORD     10
+
+#include <gr_block.h>
+
+class noaa_hrpt_deframer;
+typedef boost::shared_ptr<noaa_hrpt_deframer> noaa_hrpt_deframer_sptr;
+
+noaa_hrpt_deframer_sptr
+noaa_make_hrpt_deframer();
+
+class noaa_hrpt_deframer : public gr_block
+{
+  friend noaa_hrpt_deframer_sptr noaa_make_hrpt_deframer();
+  noaa_hrpt_deframer();
+
+  unsigned int       d_state;
+  unsigned int       d_bit_count;
+  unsigned int       d_word_count;
+  unsigned long long d_shifter;     // 60 bit sync word
+  unsigned short     d_word;        // 10 bit HRPT word
+
+  void enter_idle();
+  void enter_synced();
+public:
+  int general_work(int noutput_items,
+                  gr_vector_int &ninput_items,
+                  gr_vector_const_void_star &input_items,
+                  gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_NOAA_HRPT_DEFRAMER_H */
diff --git a/gr-noaa/lib/noaa_hrpt_pll_cf.cc b/gr-noaa/lib/noaa_hrpt_pll_cf.cc
new file mode 100644 (file)
index 0000000..08ab1d1
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <noaa_hrpt_pll_cf.h>
+#include <gr_io_signature.h>
+#include <gr_math.h>
+#include <gr_sincos.h>
+
+#define M_TWOPI (2*M_PI)
+
+noaa_hrpt_pll_cf_sptr
+noaa_make_hrpt_pll_cf(float alpha, float beta, float max_offset)
+{
+  return gnuradio::get_initial_sptr(new noaa_hrpt_pll_cf(alpha, beta, max_offset));
+}
+
+noaa_hrpt_pll_cf::noaa_hrpt_pll_cf(float alpha, float beta, float max_offset)
+  : gr_sync_block("noaa_hrpt_pll_cf",
+                 gr_make_io_signature(1, 1, sizeof(gr_complex)),
+                 gr_make_io_signature(1, 1, sizeof(float))),
+    d_alpha(alpha), d_beta(beta), d_max_offset(max_offset),
+    d_phase(0.0), d_freq(0.0)
+{
+}
+
+float
+phase_wrap(float phase)
+{
+  while (phase < -M_PI)
+    phase += M_TWOPI;
+  while (phase > M_PI)
+    phase -= M_TWOPI;
+
+  return phase;
+}
+
+int
+noaa_hrpt_pll_cf::work(int noutput_items,
+                      gr_vector_const_void_star &input_items,
+                      gr_vector_void_star &output_items)
+{
+  const gr_complex *in = (const gr_complex *) input_items[0];
+  float *out = (float *) output_items[0];
+
+  for (int i = 0; i < noutput_items; i++) {
+
+    // Adjust PLL phase/frequency
+    float error = phase_wrap(gr_fast_atan2f(in[i].imag(), in[i].real()) - d_phase);
+    d_freq  = gr_branchless_clip(d_freq + error*d_beta, d_max_offset);
+    d_phase = phase_wrap(d_phase + error*d_alpha + d_freq);
+
+    // Generate and mix out carrier
+    float re, im;
+    gr_sincosf(d_phase, &im, &re);
+    out[i] = (in[i]*gr_complex(re, -im)).imag();
+  }
+
+  return noutput_items;
+}
diff --git a/gr-noaa/lib/noaa_hrpt_pll_cf.h b/gr-noaa/lib/noaa_hrpt_pll_cf.h
new file mode 100644 (file)
index 0000000..507d47f
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_NOAA_HRPT_PLL_CF_H
+#define INCLUDED_NOAA_HRPT_PLL_CF_H
+
+#include <gr_sync_block.h>
+
+class noaa_hrpt_pll_cf;
+typedef boost::shared_ptr<noaa_hrpt_pll_cf> noaa_hrpt_pll_cf_sptr;
+
+noaa_hrpt_pll_cf_sptr
+noaa_make_hrpt_pll_cf(float alpha, float beta, float max_offset);
+
+class noaa_hrpt_pll_cf : public gr_sync_block
+{
+  friend noaa_hrpt_pll_cf_sptr noaa_make_hrpt_pll_cf(float alpha, float beta, float max_offset);
+  noaa_hrpt_pll_cf(float alpha, float beta, float max_offset);
+
+  float d_alpha;               // 1st order loop constant
+  float d_beta;                        // 2nd order loop constant
+  float d_max_offset;          // Maximum frequency offset, radians/sample
+  float d_phase;               // Instantaneous carrier phase
+  float d_freq;                        // Instantaneous carrier frequency, radians/sample
+
+ public:
+  virtual int work(int noutput_items,
+                  gr_vector_const_void_star &input_items,
+                  gr_vector_void_star &output_items);
+
+  void set_alpha(float alpha) { d_alpha = alpha; }
+  void set_beta(float beta) { d_beta = beta; }
+  void set_max_offset(float max_offset) { d_max_offset = max_offset; }
+};
+
+#endif /* INCLUDED_NOAA_HRPT_PLL_CF_H */
diff --git a/gr-noaa/lib/noaa_hrpt_sync_fb.cc b/gr-noaa/lib/noaa_hrpt_sync_fb.cc
new file mode 100644 (file)
index 0000000..f99947f
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <noaa_hrpt_sync_fb.h>
+#include <gr_io_signature.h>
+
+inline int signum(float f)
+{
+  return f >= 0.0 ? 1 : -1;
+}
+
+noaa_hrpt_sync_fb_sptr
+noaa_make_hrpt_sync_fb(float alpha, float beta, float sps, float max_offset)
+{
+  return gnuradio::get_initial_sptr(new noaa_hrpt_sync_fb(alpha, beta, sps, max_offset));
+}
+
+noaa_hrpt_sync_fb::noaa_hrpt_sync_fb(float alpha, float beta, float sps, float max_offset)
+  : gr_block("noaa_hrpt_sync_fb",
+            gr_make_io_signature(1, 1, sizeof(float)),
+            gr_make_io_signature(1, 1, sizeof(char))),
+    d_alpha(alpha), d_beta(beta), 
+    d_sps(sps), d_max_offset(max_offset),
+    d_phase(0.0), d_freq(1.0/sps),
+    d_last_sign(1)
+{
+}
+
+int
+noaa_hrpt_sync_fb::general_work(int noutput_items,
+                               gr_vector_int &ninput_items,
+                               gr_vector_const_void_star &input_items,
+                               gr_vector_void_star &output_items)
+{
+  int ninputs = ninput_items[0];
+  const float *in = (const float *)input_items[0];
+  char *out = (char *)output_items[0];
+
+  int i = 0, j = 0;
+  while (i < ninputs && j < noutput_items) {
+    float sample = in[i++];
+    int sign = signum(sample);
+    d_phase += d_freq;
+
+    // Train on zero crossings in center region of symbol
+    if (sign != d_last_sign) {
+      if (d_phase > 0.25 && d_phase < 0.75) {
+       float phase_err = d_phase-0.5;
+       d_phase -= phase_err*d_alpha;        // 1st order phase adjustment
+       d_freq -= phase_err*d_beta;          // 2nd order frequency adjustment
+      }
+
+      d_last_sign = sign;
+    }
+
+    if (d_phase > 1.0) {
+      if (sample < 0.0)
+       out[j++] = 1;
+      else
+       out[j++] = 0;
+      d_phase -= 1.0;
+    }
+  }
+
+  consume_each(i);
+  return j;
+}
diff --git a/gr-noaa/lib/noaa_hrpt_sync_fb.h b/gr-noaa/lib/noaa_hrpt_sync_fb.h
new file mode 100644 (file)
index 0000000..a9416b9
--- /dev/null
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_NOAA_HRPT_SYNC_FB_H
+#define INCLUDED_NOAA_HRPT_SYNC_FB_H
+
+#include <gr_block.h>
+
+class noaa_hrpt_sync_fb;
+typedef boost::shared_ptr<noaa_hrpt_sync_fb> noaa_hrpt_sync_fb_sptr;
+
+noaa_hrpt_sync_fb_sptr
+noaa_make_hrpt_sync_fb(float alpha, float beta, float sps, float max_offset);
+
+class noaa_hrpt_sync_fb : public gr_block
+{
+  friend noaa_hrpt_sync_fb_sptr noaa_make_hrpt_sync_fb(float alpha, float beta, float sps, float max_offset);
+  noaa_hrpt_sync_fb(float alpha, float beta, float sps, float max_offset);
+
+  float d_alpha;               // 1st order loop constant
+  float d_beta;                        // 2nd order loop constant
+  float d_sps;                  // samples per symbol
+  float d_max_offset;          // Maximum frequency offset for d_sps, samples/symbol
+  float d_phase;               // Instantaneous symbol phase
+  float d_freq;                        // Instantaneous symbol frequency, samples/symbol
+  int   d_last_sign;            // Tracks zero crossings
+
+ public:
+  int general_work(int noutput_items,
+                  gr_vector_int &ninput_items,
+                  gr_vector_const_void_star &input_items,
+                  gr_vector_void_star &output_items);
+
+  void set_alpha(float alpha) { d_alpha = alpha; }
+  void set_beta(float beta) { d_beta = beta; }
+  void set_max_offset(float max_offset) { d_max_offset = max_offset; }
+};
+
+#endif /* INCLUDED_NOAA_HRPT_SYNC_FB_H */
diff --git a/gr-noaa/python/Makefile.am b/gr-noaa/python/Makefile.am
new file mode 100644 (file)
index 0000000..869c5f3
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# 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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+if PYTHON
+
+endif
+
diff --git a/gr-noaa/swig/.gitignore b/gr-noaa/swig/.gitignore
new file mode 100644 (file)
index 0000000..d18a966
--- /dev/null
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+.deps
+.libs
+noaa_swig.cc
+noaa_swig.py
diff --git a/gr-noaa/swig/Makefile.am b/gr-noaa/swig/Makefile.am
new file mode 100644 (file)
index 0000000..cd7686e
--- /dev/null
@@ -0,0 +1,68 @@
+#
+# Copyright 2004,2005,2006,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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = \
+       $(STD_DEFINES_AND_INCLUDES) \
+       $(PYTHON_CPPFLAGS) \
+       $(WITH_INCLUDES) \
+       -I$(top_srcdir)/gr-noaa/lib
+
+if PYTHON
+# ----------------------------------------------------------------
+# The SWIG library
+# TESTS = run_tests
+
+TOP_SWIG_IFILES = \
+       noaa_swig.i
+
+# Install so that they end up available as:
+#   import gnuradio.noaa
+# This ends up at:
+#   ${prefix}/lib/python${python_version}/site-packages/gnuradio/noaa
+noaa_swig_pythondir_category = \
+       gnuradio/noaa
+
+# additional libraries for linking with the SWIG-generated library
+noaa_swig_la_swig_libadd = \
+       $(top_builddir)/gr-noaa/lib/libgnuradio-noaa.la
+
+# additional Python files to be installed along with the SWIG-generated one
+noaa_swig_python = \
+       __init__.py
+
+# additional SWIG files to be installed
+noaa_swig_swiginclude_headers =        \
+       noaa_swig.i \
+       noaa_hrpt_decoder.i \
+       noaa_hrpt_deframer.i \
+       noaa_hrpt_pll_cf.i \
+       noaa_hrpt_sync_fb.i
+
+include $(top_srcdir)/Makefile.swig
+
+# add some of the variables generated inside the Makefile.swig.gen
+BUILT_SOURCES = $(swig_built_sources)
+
+# Do not distribute the output of SWIG
+no_dist_files = $(swig_built_sources)
+endif
diff --git a/gr-noaa/swig/Makefile.swig.gen b/gr-noaa/swig/Makefile.swig.gen
new file mode 100644 (file)
index 0000000..3d7102f
--- /dev/null
@@ -0,0 +1,259 @@
+# -*- Makefile -*-
+#
+# 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.
+# 
+
+# Makefile.swig.gen for noaa_swig.i
+
+## Default install locations for these files:
+##
+## Default location for the Python directory is:
+##  ${prefix}/lib/python${python_version}/site-packages/[category]/noaa_swig
+## Default location for the Python exec directory is:
+##  ${exec_prefix}/lib/python${python_version}/site-packages/[category]/noaa_swig
+##
+## The following can be overloaded to change the install location, but
+## this has to be done in the including Makefile.am -before-
+## Makefile.swig is included.
+
+noaa_swig_pythondir_category ?= gnuradio/noaa_swig
+noaa_swig_pylibdir_category ?= $(noaa_swig_pythondir_category)
+noaa_swig_pythondir = $(pythondir)/$(noaa_swig_pythondir_category)
+noaa_swig_pylibdir = $(pyexecdir)/$(noaa_swig_pylibdir_category)
+
+## SWIG headers are always installed into the same directory.
+
+noaa_swig_swigincludedir = $(swigincludedir)
+
+## This is a template file for a "generated" Makefile addition (in
+## this case, "Makefile.swig.gen").  By including the top-level
+## Makefile.swig, this file will be used to generate the SWIG
+## dependencies.  Assign the variable TOP_SWIG_FILES to be the list of
+## SWIG .i files to generated wrappings for; there can be more than 1
+## so long as the names are unique (no sorting is done on the
+## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i
+## file will generate .cc, .py, and possibly .h files -- meaning that
+## all of these files will have the same base name (that provided for
+## the SWIG .i file).
+##
+## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the
+## right thing.  For more info, see <
+## http://sources.redhat.com/automake/automake.html#Multiple-Outputs >
+
+## Stamps used to ensure parallel make does the right thing.  These
+## are removed by "make clean", but otherwise unused except during the
+## parallel built.  These will not be included in a tarball, because
+## the SWIG-generated files will be removed from the distribution.
+
+STAMPS += $(DEPDIR)/noaa_swig-generate-*
+
+## Other cleaned files: dependency files generated by SWIG or this Makefile
+
+MOSTLYCLEANFILES += $(DEPDIR)/*.S*
+
+## Add the .py and .cc files to the list of SWIG built sources.  The
+## .h file is sometimes built, but not always ... so that one has to
+## be added manually by the including Makefile.am .
+
+swig_built_sources += noaa_swig.py noaa_swig.cc
+
+## Various SWIG variables.  These can be overloaded in the including
+## Makefile.am by setting the variable value there, then including
+## Makefile.swig .
+
+noaa_swig_swiginclude_HEADERS =                \
+       noaa_swig.i                     \
+       $(noaa_swig_swiginclude_headers)
+
+noaa_swig_pylib_LTLIBRARIES =          \
+       _noaa_swig.la
+
+_noaa_swig_la_SOURCES =                        \
+       noaa_swig.cc                    \
+       $(noaa_swig_la_swig_sources)
+
+_noaa_swig_la_LIBADD =                 \
+       $(STD_SWIG_LA_LIB_ADD)          \
+       $(noaa_swig_la_swig_libadd)
+
+_noaa_swig_la_LDFLAGS =                        \
+       $(STD_SWIG_LA_LD_FLAGS)         \
+       $(noaa_swig_la_swig_ldflags)
+
+_noaa_swig_la_CXXFLAGS =                       \
+       $(STD_SWIG_CXX_FLAGS)           \
+       $(noaa_swig_la_swig_cxxflags)
+
+noaa_swig_python_PYTHON =                      \
+       noaa_swig.py                    \
+       $(noaa_swig_python)
+
+## Entry rule for running SWIG
+
+noaa_swig.h noaa_swig.py noaa_swig.cc: noaa_swig.i
+## This rule will get called only when MAKE decides that one of the
+## targets needs to be created or re-created, because:
+##
+## * The .i file is newer than any or all of the generated files;
+##
+## * Any or all of the .cc, .h, or .py files does not exist and is
+##   needed (in the case this file is not needed, the rule for it is
+##   ignored); or
+##
+## * Some SWIG-based dependecy of the .cc file isn't met and hence the
+##   .cc file needs be be regenerated.  Explanation: Because MAKE
+##   knows how to handle dependencies for .cc files (regardless of
+##   their name or extension), then the .cc file is used as a target
+##   instead of the .i file -- but with the dependencies of the .i
+##   file.  It is this last reason why the line:
+##
+##             if test -f $@; then :; else
+##
+##   cannot be used in this case: If a .i file dependecy is not met,
+##   then the .cc file needs to be rebuilt.  But if the stamp is newer
+##   than the .cc file, and the .cc file exists, then in the original
+##   version (with the 'test' above) the internal MAKE call will not
+##   be issued and hence the .cc file will not be rebuilt.
+##
+## Once execution gets to here, it should always proceed no matter the
+## state of a stamp (as discussed in link above).  The
+## $(DEPDIR)/noaa_swig-generate stuff is used to allow for parallel
+## builds to "do the right thing".  The stamp has no relationship with
+## either the target files or dependency file; it is used solely for
+## the protection of multiple builds during a given call to MAKE.
+##
+## Catch signals SIGHUP (1), SIGINT (2), SIGPIPE (13), and SIGTERM
+## (15).  At a caught signal, the quoted command will be issued before
+## exiting.  In this case, remove any stamp, whether temporary of not.
+## The trap is valid until the process exits; the process includes all
+## commands appended via "\"s.
+##
+       trap 'rm -rf $(DEPDIR)/noaa_swig-generate-*' 1 2 13 15; \
+##
+## Create a temporary directory, which acts as a lock.  The first
+## process to create the directory will succeed and issue the MAKE
+## command to do the actual work, while all subsequent processes will
+## fail -- leading them to wait for the first process to finish.
+##
+       if mkdir $(DEPDIR)/noaa_swig-generate-lock 2>/dev/null; then \
+##
+## This code is being executed by the first process to succeed in
+## creating the directory lock.
+##
+## Remove the stamp associated with this filename.
+##
+               rm -f $(DEPDIR)/noaa_swig-generate-stamp; \
+##
+## Tell MAKE to run the rule for creating this stamp.
+##
+               $(MAKE) $(AM_MAKEFLAGS) $(DEPDIR)/noaa_swig-generate-stamp WHAT=$<; \
+##
+## Now that the .cc, .h, and .py files have been (re)created from the
+## .i file, future checking of this rule during the same MAKE
+## execution will come back that the rule doesn't need to be executed
+## because none of the conditions mentioned at the start of this rule
+## will be positive.  Remove the the directory lock, which frees up
+## any waiting process(es) to continue.
+##
+               rmdir $(DEPDIR)/noaa_swig-generate-lock; \
+       else \
+##
+## This code is being executed by any follower processes while the
+## directory lock is in place.
+##
+## Wait until the first process is done, testing once per second.
+##
+               while test -d $(DEPDIR)/noaa_swig-generate-lock; do \
+                       sleep 1; \
+               done; \
+##
+## Succeed if and only if the first process succeeded; exit this
+## process returning the status of the generated stamp.
+##
+               test -f $(DEPDIR)/noaa_swig-generate-stamp; \
+               exit $$?; \
+       fi;
+
+$(DEPDIR)/noaa_swig-generate-stamp:
+## This rule will be called only by the first process issuing the
+## above rule to succeed in creating the lock directory, after
+## removing the actual stamp file in order to guarantee that MAKE will
+## execute this rule.
+##
+## Call SWIG to generate the various output files; special
+## post-processing on 'mingw32' host OS for the dependency file.
+##
+       if $(SWIG) $(STD_SWIG_PYTHON_ARGS) $(noaa_swig_swig_args) \
+               -MD -MF $(DEPDIR)/noaa_swig.Std \
+               -module noaa_swig -o noaa_swig.cc $(WHAT); then \
+           if test $(host_os) = mingw32; then \
+               $(RM) $(DEPDIR)/noaa_swig.Sd; \
+               $(SED) 's,\\\\,/,g' < $(DEPDIR)/noaa_swig.Std \
+                       > $(DEPDIR)/noaa_swig.Sd; \
+               $(RM) $(DEPDIR)/noaa_swig.Std; \
+               $(MV) $(DEPDIR)/noaa_swig.Sd $(DEPDIR)/noaa_swig.Std; \
+           fi; \
+       else \
+           $(RM) $(DEPDIR)/noaa_swig.S*; exit 1; \
+       fi;
+##
+## Mess with the SWIG output .Std dependency file, to create a
+## dependecy file valid for the input .i file: Basically, simulate the
+## dependency file created for libraries by GNU's libtool for C++,
+## where all of the dependencies for the target are first listed, then
+## each individual dependency is listed as a target with no further
+## dependencies.
+##
+## (1) remove the current dependency file
+##
+       $(RM) $(DEPDIR)/noaa_swig.d
+##
+## (2) Copy the whole SWIG file:
+##
+       cp $(DEPDIR)/noaa_swig.Std $(DEPDIR)/noaa_swig.d
+##
+## (3) all a carriage return to the end of the dependency file.
+##
+       echo "" >> $(DEPDIR)/noaa_swig.d
+##
+## (4) from the SWIG file, remove the first line (the target); remove
+##     trailing " \" and " " from each line.  Append ":" to each line,
+##     followed by 2 carriage returns, then append this to the end of
+##     the dependency file.
+##
+       $(SED) -e '1d;s, \\,,g;s, ,,g' < $(DEPDIR)/noaa_swig.Std | \
+               awk '{ printf "%s:\n\n", $$0 }' >> $(DEPDIR)/noaa_swig.d
+##
+## (5) remove the SWIG-generated file
+##
+       $(RM) $(DEPDIR)/noaa_swig.Std
+##
+## Create the stamp for this filename generation, to signal success in
+## executing this rule; allows other threads waiting on this process
+## to continue.
+##
+       touch $(DEPDIR)/noaa_swig-generate-stamp
+
+# KLUDGE: Force runtime include of a SWIG dependency file.  This is
+# not guaranteed to be portable, but will probably work.  If it works,
+# we have accurate dependencies for our swig stuff, which is good.
+
+@am__include@ @am__quote@./$(DEPDIR)/noaa_swig.d@am__quote@
+
diff --git a/gr-noaa/swig/__init__.py b/gr-noaa/swig/__init__.py
new file mode 100644 (file)
index 0000000..d8d337e
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# 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.
+# 
+
+# The presence of this file turns this directory into a Python package
+
+# Add SWIG generated code to this namespace
+from noaa_swig import *
+
+# Add other content from pure-Python modules here
+
diff --git a/gr-noaa/swig/noaa_hrpt_decoder.i b/gr-noaa/swig/noaa_hrpt_decoder.i
new file mode 100644 (file)
index 0000000..ddf181c
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(noaa,hrpt_decoder)
+
+noaa_hrpt_decoder_sptr
+noaa_make_hrpt_decoder();
+
+class noaa_hrpt_decoder : public gr_sync_block
+{
+private:
+  noaa_hrpt_decoder();
+};
diff --git a/gr-noaa/swig/noaa_hrpt_deframer.i b/gr-noaa/swig/noaa_hrpt_deframer.i
new file mode 100644 (file)
index 0000000..6914b93
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(noaa,hrpt_deframer)
+
+noaa_hrpt_deframer_sptr
+noaa_make_hrpt_deframer();
+
+class noaa_hrpt_deframer : public gr_block
+{
+private:
+  noaa_hrpt_deframer();
+};
diff --git a/gr-noaa/swig/noaa_hrpt_pll_cf.i b/gr-noaa/swig/noaa_hrpt_pll_cf.i
new file mode 100644 (file)
index 0000000..859548a
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(noaa,hrpt_pll_cf)
+
+noaa_hrpt_pll_cf_sptr
+noaa_make_hrpt_pll_cf(float alpha, float beta, float max_offset);
+
+class noaa_hrpt_pll_cf : public gr_sync_block
+{
+private:
+  noaa_hrpt_pll_cf();
+
+public:
+  void set_alpha(float alpha);
+  void set_beta(float beta);
+  void set_max_offset(float min_freq);
+};
diff --git a/gr-noaa/swig/noaa_hrpt_sync_fb.i b/gr-noaa/swig/noaa_hrpt_sync_fb.i
new file mode 100644 (file)
index 0000000..a8e5b21
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(noaa,hrpt_sync_fb)
+
+noaa_hrpt_sync_fb_sptr
+noaa_make_hrpt_sync_fb(float alpha, float beta, float sps, float max_offset);
+
+class noaa_hrpt_sync_fb : public gr_sync_block
+{
+private:
+  noaa_hrpt_sync_fb();
+
+public:
+  void set_alpha(float alpha);
+  void set_beta(float beta);
+  void set_max_offset(float min_freq);
+};
diff --git a/gr-noaa/swig/noaa_swig.i b/gr-noaa/swig/noaa_swig.i
new file mode 100644 (file)
index 0000000..e6497bc
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+%include "gnuradio.i"
+
+%{
+#include <noaa_hrpt_decoder.h>
+#include <noaa_hrpt_deframer.h>
+#include <noaa_hrpt_pll_cf.h>
+#include <noaa_hrpt_sync_fb.h>
+%}
+
+%include "noaa_hrpt_decoder.i"
+%include "noaa_hrpt_deframer.i"
+%include "noaa_hrpt_pll_cf.i"
+%include "noaa_hrpt_sync_fb.i"
index 59ca215a764a920392979754e8b5e46b715601fb..fb21e4f449b8eb817a34c792209f1bc2da1029bc 100644 (file)
@@ -50,17 +50,15 @@ bin_SCRIPTS = \
     gr_plot_qt.py \
     gr_filter_design.py \
     lsusrp \
-    qr_fft.py \
     usrp_fft.py \
     usrp_oscope.py \
     usrp_print_db.py \
     usrp_rx_cfile.py \
     usrp_rx_nogui.py \
     usrp_siggen.py \
+    usrp_siggen_gui.py \
     usrp_test_counting.py \
     usrp_test_loopback.py \
     usrp2_fft.py \
-    usrp2_rx_cfile.py \
-    usrp2_siggen.py \
-    usrp2_siggen_gui.py
+    usrp2_rx_cfile.py
 
index a5e3463c8e75dc523025cec9f1473c0e4e6a8c37..f3dc472f5d4f7ed7434bf7d2e7f3f59b969c219f 100755 (executable)
@@ -7,14 +7,36 @@ except ImportError:
     print "Please install SciPy to run this script (http://www.scipy.org/)"
     raise SystemExit, 1
 
+try:
+    from matplotlib import mlab
+except ImportError:
+    print "Please install Matplotlib to run this script (http://matplotlib.sourceforge.net)"
+    raise SystemExit, 1
+
+try:
+    from PyQt4 import Qt, QtCore, QtGui
+except ImportError:
+    print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)"
+    raise SystemExit, 1
+
+try:
+    import PyQt4.Qwt5 as Qwt
+except ImportError:
+    print "Please install PyQwt5 to run this script (http://pyqwt.sourceforge.net/)"
+    raise SystemExit, 1
+
+try:
+    # FIXME: reenable this before committing
+    #from gnuradio.pyqt_plot import Ui_MainWindow
+    from pyqt_plot import Ui_MainWindow
+except ImportError:
+    print "Could not import from pyqt_plot. Please build with \"pyuic4 pyqt_plot.ui -o pyqt_plot.py\""
+    raise SystemExit, 1
+
 import sys, os
-from PyQt4 import Qt, QtCore, QtGui
-import PyQt4.Qwt5 as Qwt
-from matplotlib import mlab
 from optparse import OptionParser
 from gnuradio import eng_notation
 
-from pyqt_plot import Ui_MainWindow
 
 class SpectrogramData(Qwt.QwtRasterData):
 
@@ -42,9 +64,12 @@ class SpectrogramData(Qwt.QwtRasterData):
         return Qwt.QwtDoubleInterval(self.sp.min(), self.sp.max())
 
     def value(self, x, y):
-        f = int(self.freq.searchsorted(x))
-        t = int(self.time.searchsorted(y))
-        return self.sp[f][t-1]
+        try:
+            f = int(self.freq.searchsorted(x))
+            t = int(self.time.searchsorted(y))
+            return self.sp[f][t-1]
+        except AttributeError: # if no file loaded yet
+            return 0
 
 
 class gr_plot_qt(QtGui.QMainWindow):
@@ -53,6 +78,7 @@ class gr_plot_qt(QtGui.QMainWindow):
         self.gui = Ui_MainWindow()
         self.gui.setupUi(self)
                        
+        self.filename = None
         self.block_length = options.block_length
         self.start = options.start
         self.sample_rate = options.sample_rate
@@ -61,6 +87,7 @@ class gr_plot_qt(QtGui.QMainWindow):
         self.winfunc = scipy.blackman
         self.sizeof_data = 8
         self.datatype = scipy.complex64
+        self.pen_width = 1
         self.iq = list()
         self.time = list()
 
@@ -102,6 +129,18 @@ class gr_plot_qt(QtGui.QMainWindow):
                      self.colorComboBoxEdit)
         
         
+        # Set up line style combo box
+        self.line_styles = {"None" : Qwt.QwtSymbol.NoSymbol,
+                            "Circle" : Qwt.QwtSymbol.Ellipse,
+                            "Diamond"  : Qwt.QwtSymbol.Rect,
+                            "Triangle" : Qwt.QwtSymbol.Triangle}
+        self.gui.lineStyleComboBox.addItems(self.line_styles.keys())
+        pos = self.gui.lineStyleComboBox.findText("None")
+        self.gui.lineStyleComboBox.setCurrentIndex(pos)
+        self.connect(self.gui.lineStyleComboBox,
+                     Qt.SIGNAL("activated (const QString&)"),
+                     self.lineStyleComboBoxEdit)
+
         # Create zoom functionality for the plots
         self.timeZoomer = Qwt.QwtPlotZoomer(self.gui.timePlot.xBottom,
                                             self.gui.timePlot.yLeft,
@@ -121,16 +160,6 @@ class gr_plot_qt(QtGui.QMainWindow):
                                             Qwt.QwtPicker.AlwaysOn,
                                             self.gui.specPlot.canvas())
 
-        self.picker = Qwt.QwtPlotPicker(self.gui.timePlot.xBottom,
-                                        self.gui.timePlot.yLeft,
-                                        Qwt.QwtPicker.PointSelection,
-                                        Qwt.QwtPlotPicker.CrossRubberBand,
-                                        Qwt.QwtPicker.AlwaysOn,
-                                        self.gui.timePlot.canvas())
-        self.picker.connect(self.picker,
-                            Qt.SIGNAL('selected(const QwtDoublePoint&)'),
-                            self.clickMe)
-
         # Set up action when tab is changed
         self.connect(self.gui.tabGroup,
                      Qt.SIGNAL("currentChanged (int)"),
@@ -153,7 +182,14 @@ class gr_plot_qt(QtGui.QMainWindow):
         self.connect(self.gui.action_open,
                      Qt.SIGNAL("activated()"),
                      self.open_file)
-        
+
+        # Connect Reload action to reload the file
+        self.connect(self.gui.action_reload,
+                     Qt.SIGNAL("activated()"),
+                     self.reload_file)
+        self.gui.action_reload.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+R",
+                                                                        None, QtGui.QApplication.UnicodeUTF8))
+
         # Set up file position boxes to update current figure
         self.connect(self.gui.filePosStartLineEdit,
                      Qt.SIGNAL("editingFinished()"),
@@ -175,8 +211,20 @@ class gr_plot_qt(QtGui.QMainWindow):
                      Qt.SIGNAL("editingFinished()"),
                      self.file_time_length_changed)
 
+        stylestr = str(self.gui.lineStyleComboBox.currentText().toAscii())
+        style = self.line_styles[stylestr]
+
         self.rcurve = Qwt.QwtPlotCurve("Real")
         self.icurve = Qwt.QwtPlotCurve("Imaginary")
+        self.rsym = Qwt.QwtSymbol()
+        self.rsym.setStyle(style)
+        self.rsym.setSize(10)
+        self.isym = Qwt.QwtSymbol()
+        self.isym.setStyle(style)
+        self.isym.setSize(10)
+        self.rcurve.setSymbol(self.rsym)
+        self.icurve.setSymbol(self.isym)
+
 
         self.icurve.attach(self.gui.timePlot)
         self.rcurve.attach(self.gui.timePlot)
@@ -208,6 +256,20 @@ class gr_plot_qt(QtGui.QMainWindow):
         # Set up initial color scheme
         self.color_modes["Blue on Black"]()
 
+        # When line width spin box changes, update the pen size
+        self.connect(self.gui.lineWidthSpinBox,
+                     Qt.SIGNAL("valueChanged(int)"),
+                     self.change_pen_width)
+        self.gui.lineWidthSpinBox.setRange(1, 10)
+
+        # When style size spin box changes, update the pen size
+        self.connect(self.gui.styleSizeSpinBox,
+                     Qt.SIGNAL("valueChanged(int)"),
+                     self.change_style_size)
+        self.gui.styleSizeSpinBox.setRange(1, 20)
+        self.gui.styleSizeSpinBox.setValue(5)
+
+
         # Connect a signal for when the sample rate changes
         self.set_sample_rate(self.sample_rate)
         self.connect(self.gui.sampleRateLineEdit,
@@ -222,10 +284,15 @@ class gr_plot_qt(QtGui.QMainWindow):
     def open_file(self):
         filename = Qt.QFileDialog.getOpenFileName(self, "Open", ".")
         if(filename != ""):
-            print filename
+            #print filename
             self.initialize(filename)
 
+    def reload_file(self):
+        if(self.filename):
+            self.initialize(self.filename)
+        
     def initialize(self, filename):
+        self.filename = filename
         self.hfile = open(filename, "r")
 
         self.setWindowTitle(("GNU Radio File Plot Utility: %s" % filename))
@@ -243,7 +310,7 @@ class gr_plot_qt(QtGui.QMainWindow):
         self.get_psd()
         self.get_specgram() 
         self.gui.plotHBar.setSliderPosition(0)
-        self.gui.plotHBar.setMaximum(self.signal_size)
+        self.gui.plotHBar.setMaximum(self.signal_size-self.block_length)
 
 
         self.update_time_curves()
@@ -253,7 +320,7 @@ class gr_plot_qt(QtGui.QMainWindow):
     def init_data_input(self):
         self.hfile.seek(0, os.SEEK_END)
         self.signal_size = self.hfile.tell()/self.sizeof_data
-        print "Sizeof File: ", self.signal_size
+        #print "Sizeof File: ", self.signal_size
         self.hfile.seek(0, os.SEEK_SET)
         
     def get_data(self, start, end):
@@ -265,10 +332,8 @@ class gr_plot_qt(QtGui.QMainWindow):
                                     count=end-start)
 
                 if(len(iq) < (end-start)):
-                    end = len(iq)
-                    self.gui.filePosLengthLineEdit.setText(Qt.QString("%1").arg(end))
-                    self.gui.plotHBar.setMaximum(end)
-                    self.gui.plotHBar.setSingleStep(end)
+                    end = start + len(iq)
+                    self.gui.filePosLengthLineEdit.setText(Qt.QString("%1").arg(len(iq)))
                     self.file_length_changed()
 
                 tstep = 1.0 / self.sample_rate
@@ -305,9 +370,6 @@ class gr_plot_qt(QtGui.QMainWindow):
         self.spec_f = f
         self.spec_t = t
 
-    def clickMe(self, qPoint):
-        print qPoint.x()
-
     def psdFFTComboBoxEdit(self, fftSize):
         self.psdfftsize = fftSize.toInt()[0]
         self.get_psd()
@@ -323,6 +385,14 @@ class gr_plot_qt(QtGui.QMainWindow):
         color_func = self.color_modes[colorstr]
         color_func()
 
+    def lineStyleComboBoxEdit(self, styleSelection):
+        stylestr = str(styleSelection.toAscii())
+        self.rsym.setStyle(self.line_styles[stylestr])
+        self.isym.setStyle(self.line_styles[stylestr])
+        self.rcurve.setSymbol(self.rsym)
+        self.icurve.setSymbol(self.isym)
+        self.gui.timePlot.replot()
+
     def sliderMoved(self, value):
         pos_start = value
         pos_end = value + self.gui.plotHBar.pageStep()
@@ -382,7 +452,11 @@ class gr_plot_qt(QtGui.QMainWindow):
 
         # If there's a non-digit character, reset box
         else:
-            self.set_file_pos_box(self.cur_start, self.cur_stop)
+            try:
+                self.set_file_pos_box(self.cur_start, self.cur_stop)
+            except AttributeError:
+                pass
+            
 
     def file_time_changed(self):
         tstart = self.gui.fileTimeStartLineEdit.text().toDouble()
@@ -517,25 +591,40 @@ class gr_plot_qt(QtGui.QMainWindow):
     def tabChanged(self, index):
         self.gui.timePlot.replot()
         self.gui.freqPlot.replot()
+        self.gui.specPlot.replot()
+
+    def change_pen_width(self, width):
+        self.pen_width = width
+        colormode = str(self.gui.colorComboBox.currentText().toAscii())
+        color_func = self.color_modes[colormode]()
 
+    def change_style_size(self, size):
+        self.rsym.setSize(size)
+        self.isym.setSize(size)
+        self.rcurve.setSymbol(self.rsym)
+        self.icurve.setSymbol(self.isym)
+        self.gui.timePlot.replot()
+    
     def color_black_on_white(self):
         blue = QtGui.qRgb(0x00, 0x00, 0xFF)
         red = QtGui.qRgb(0xFF, 0x00, 0x00)
 
-        blackBrush = Qt.QBrush(Qt.QColor("black"))
-        blueBrush = Qt.QBrush(Qt.QColor(blue))
-        redBrush = Qt.QBrush(Qt.QColor(red))
+        blackPen = Qt.QPen(Qt.QBrush(Qt.QColor("black")), self.pen_width)
+        bluePen = Qt.QPen(Qt.QBrush(Qt.QColor(blue)), self.pen_width)
+        redPen = Qt.QPen(Qt.QBrush(Qt.QColor(red)), self.pen_width)
 
         self.gui.timePlot.setCanvasBackground(Qt.QColor("white"))
         self.gui.freqPlot.setCanvasBackground(Qt.QColor("white"))
-        self.picker.setTrackerPen(Qt.QPen(blackBrush, 2))
-        self.timeZoomer.setTrackerPen(Qt.QPen(blackBrush, 2))
-        self.timeZoomer.setRubberBandPen(Qt.QPen(blackBrush, 2))
-        self.freqZoomer.setTrackerPen(Qt.QPen(blackBrush, 2))
-        self.freqZoomer.setRubberBandPen(Qt.QPen(blackBrush, 2))
-        self.psdcurve.setPen(Qt.QPen(blueBrush, 1))
-        self.rcurve.setPen(Qt.QPen(blueBrush, 2))
-        self.icurve.setPen(Qt.QPen(redBrush, 2))
+        self.timeZoomer.setTrackerPen(blackPen)
+        self.timeZoomer.setRubberBandPen(blackPen)
+        self.freqZoomer.setTrackerPen(blackPen)
+        self.freqZoomer.setRubberBandPen(blackPen)
+        self.psdcurve.setPen(bluePen)
+        self.rcurve.setPen(bluePen)
+        self.icurve.setPen(redPen)
+
+        self.rsym.setPen(bluePen)
+        self.isym.setPen(redPen)
 
         self.gui.timePlot.replot()
         self.gui.freqPlot.replot()
@@ -550,14 +639,13 @@ class gr_plot_qt(QtGui.QMainWindow):
         
         self.gui.timePlot.setCanvasBackground(QtGui.QColor("black"))
         self.gui.freqPlot.setCanvasBackground(QtGui.QColor("black"))
-        self.picker.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.timeZoomer.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.timeZoomer.setRubberBandPen(Qt.QPen(whiteBrush, 2))
-        self.freqZoomer.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.freqZoomer.setRubberBandPen(Qt.QPen(whiteBrush, 2))
-        self.psdcurve.setPen(Qt.QPen(whiteBrush, 1))
-        self.rcurve.setPen(Qt.QPen(whiteBrush, 2))
-        self.icurve.setPen(Qt.QPen(redBrush, 2))
+        self.timeZoomer.setTrackerPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.timeZoomer.setRubberBandPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.freqZoomer.setTrackerPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.freqZoomer.setRubberBandPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.psdcurve.setPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.rcurve.setPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.icurve.setPen(Qt.QPen(redBrush, self.pen_width))
 
         self.gui.timePlot.replot()
         self.gui.freqPlot.replot()
@@ -573,14 +661,13 @@ class gr_plot_qt(QtGui.QMainWindow):
         
         self.gui.timePlot.setCanvasBackground(QtGui.QColor("black"))
         self.gui.freqPlot.setCanvasBackground(QtGui.QColor("black"))
-        self.picker.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.timeZoomer.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.timeZoomer.setRubberBandPen(Qt.QPen(whiteBrush, 2))
-        self.freqZoomer.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.freqZoomer.setRubberBandPen(Qt.QPen(whiteBrush, 2))
-        self.psdcurve.setPen(Qt.QPen(greenBrush, 1))
-        self.rcurve.setPen(Qt.QPen(greenBrush, 2))
-        self.icurve.setPen(Qt.QPen(redBrush, 2))
+        self.timeZoomer.setTrackerPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.timeZoomer.setRubberBandPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.freqZoomer.setTrackerPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.freqZoomer.setRubberBandPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.psdcurve.setPen(Qt.QPen(greenBrush, self.pen_width))
+        self.rcurve.setPen(Qt.QPen(greenBrush, self.pen_width))
+        self.icurve.setPen(Qt.QPen(redBrush, self.pen_width))
 
         self.gui.timePlot.replot()
         self.gui.freqPlot.replot()
@@ -595,14 +682,13 @@ class gr_plot_qt(QtGui.QMainWindow):
         
         self.gui.timePlot.setCanvasBackground(QtGui.QColor("black"))
         self.gui.freqPlot.setCanvasBackground(QtGui.QColor("black"))
-        self.picker.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.timeZoomer.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.timeZoomer.setRubberBandPen(Qt.QPen(whiteBrush, 2))
-        self.freqZoomer.setTrackerPen(Qt.QPen(whiteBrush, 2))
-        self.freqZoomer.setRubberBandPen(Qt.QPen(whiteBrush, 2))
-        self.psdcurve.setPen(Qt.QPen(blueBrush, 1))
-        self.rcurve.setPen(Qt.QPen(blueBrush, 2))
-        self.icurve.setPen(Qt.QPen(redBrush, 2))
+        self.timeZoomer.setTrackerPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.timeZoomer.setRubberBandPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.freqZoomer.setTrackerPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.freqZoomer.setRubberBandPen(Qt.QPen(whiteBrush, self.pen_width))
+        self.psdcurve.setPen(Qt.QPen(blueBrush, self.pen_width))
+        self.rcurve.setPen(Qt.QPen(blueBrush, self.pen_width))
+        self.icurve.setPen(Qt.QPen(redBrush, self.pen_width))
 
         self.gui.timePlot.replot()
         self.gui.freqPlot.replot()
index 74c43c3ebe5e39c13106ae759c2d39bba02d85d6..98977da975ae84e0e0ab1ce250f650b81b840f76 100644 (file)
@@ -2,7 +2,7 @@
 
 # Form implementation generated from reading ui file 'pyqt_plot.ui'
 #
-# Created: Tue Aug 25 18:18:14 2009
+# Created: Tue Sep  1 23:02:36 2009
 #      by: PyQt4 UI code generator 4.4.3
 #
 # WARNING! All changes made in this file will be lost!
@@ -12,7 +12,7 @@ from PyQt4 import QtCore, QtGui
 class Ui_MainWindow(object):
     def setupUi(self, MainWindow):
         MainWindow.setObjectName("MainWindow")
-        MainWindow.resize(927, 696)
+        MainWindow.resize(927, 718)
         self.centralwidget = QtGui.QWidget(MainWindow)
         self.centralwidget.setObjectName("centralwidget")
         self.gridLayout = QtGui.QGridLayout(self.centralwidget)
@@ -20,8 +20,123 @@ class Ui_MainWindow(object):
         self.plotHBar = QtGui.QScrollBar(self.centralwidget)
         self.plotHBar.setOrientation(QtCore.Qt.Horizontal)
         self.plotHBar.setObjectName("plotHBar")
-        self.gridLayout.addWidget(self.plotHBar, 2, 0, 1, 2)
-        self.tabGroup = QtGui.QTabWidget(self.centralwidget)
+        self.gridLayout.addWidget(self.plotHBar, 1, 0, 1, 3)
+        self.filePosBox = QtGui.QGroupBox(self.centralwidget)
+        self.filePosBox.setMinimumSize(QtCore.QSize(0, 120))
+        self.filePosBox.setObjectName("filePosBox")
+        self.gridLayout_4 = QtGui.QGridLayout(self.filePosBox)
+        self.gridLayout_4.setObjectName("gridLayout_4")
+        self.filePosLayout = QtGui.QFormLayout()
+        self.filePosLayout.setObjectName("filePosLayout")
+        self.filePosStartLineEdit = QtGui.QLineEdit(self.filePosBox)
+        self.filePosStartLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.filePosStartLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.filePosStartLineEdit.setObjectName("filePosStartLineEdit")
+        self.filePosLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.filePosStartLineEdit)
+        self.filePosStopLabel = QtGui.QLabel(self.filePosBox)
+        self.filePosStopLabel.setObjectName("filePosStopLabel")
+        self.filePosLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.filePosStopLabel)
+        self.filePosStopLineEdit = QtGui.QLineEdit(self.filePosBox)
+        self.filePosStopLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.filePosStopLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.filePosStopLineEdit.setObjectName("filePosStopLineEdit")
+        self.filePosLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.filePosStopLineEdit)
+        self.filePosLengthLabel = QtGui.QLabel(self.filePosBox)
+        self.filePosLengthLabel.setObjectName("filePosLengthLabel")
+        self.filePosLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.filePosLengthLabel)
+        self.filePosLengthLineEdit = QtGui.QLineEdit(self.filePosBox)
+        self.filePosLengthLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.filePosLengthLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.filePosLengthLineEdit.setObjectName("filePosLengthLineEdit")
+        self.filePosLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.filePosLengthLineEdit)
+        self.filePosStartLabel = QtGui.QLabel(self.filePosBox)
+        self.filePosStartLabel.setObjectName("filePosStartLabel")
+        self.filePosLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.filePosStartLabel)
+        self.gridLayout_4.addLayout(self.filePosLayout, 0, 0, 1, 1)
+        self.fileTimeLayout = QtGui.QFormLayout()
+        self.fileTimeLayout.setObjectName("fileTimeLayout")
+        self.fileTimeStartLabel = QtGui.QLabel(self.filePosBox)
+        self.fileTimeStartLabel.setObjectName("fileTimeStartLabel")
+        self.fileTimeLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.fileTimeStartLabel)
+        self.fileTimeStartLineEdit = QtGui.QLineEdit(self.filePosBox)
+        self.fileTimeStartLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.fileTimeStartLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.fileTimeStartLineEdit.setObjectName("fileTimeStartLineEdit")
+        self.fileTimeLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.fileTimeStartLineEdit)
+        self.fileTimeStopLabel = QtGui.QLabel(self.filePosBox)
+        self.fileTimeStopLabel.setObjectName("fileTimeStopLabel")
+        self.fileTimeLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.fileTimeStopLabel)
+        self.fileTimeStopLineEdit = QtGui.QLineEdit(self.filePosBox)
+        self.fileTimeStopLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.fileTimeStopLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.fileTimeStopLineEdit.setObjectName("fileTimeStopLineEdit")
+        self.fileTimeLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.fileTimeStopLineEdit)
+        self.fileTimeLengthLabel = QtGui.QLabel(self.filePosBox)
+        self.fileTimeLengthLabel.setObjectName("fileTimeLengthLabel")
+        self.fileTimeLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.fileTimeLengthLabel)
+        self.fileTimeLengthLineEdit = QtGui.QLineEdit(self.filePosBox)
+        self.fileTimeLengthLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.fileTimeLengthLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.fileTimeLengthLineEdit.setObjectName("fileTimeLengthLineEdit")
+        self.fileTimeLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.fileTimeLengthLineEdit)
+        self.gridLayout_4.addLayout(self.fileTimeLayout, 0, 1, 1, 1)
+        self.gridLayout.addWidget(self.filePosBox, 2, 0, 1, 1)
+        self.displayGroupBox = QtGui.QGroupBox(self.centralwidget)
+        self.displayGroupBox.setMinimumSize(QtCore.QSize(170, 0))
+        self.displayGroupBox.setObjectName("displayGroupBox")
+        self.gridLayout_2 = QtGui.QGridLayout(self.displayGroupBox)
+        self.gridLayout_2.setObjectName("gridLayout_2")
+        self.colorComboBox = QtGui.QComboBox(self.displayGroupBox)
+        self.colorComboBox.setObjectName("colorComboBox")
+        self.gridLayout_2.addWidget(self.colorComboBox, 0, 0, 1, 2)
+        self.lineWidthSpinBox = QtGui.QSpinBox(self.displayGroupBox)
+        self.lineWidthSpinBox.setMinimumSize(QtCore.QSize(100, 0))
+        self.lineWidthSpinBox.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.lineWidthSpinBox.setObjectName("lineWidthSpinBox")
+        self.gridLayout_2.addWidget(self.lineWidthSpinBox, 1, 1, 1, 1)
+        self.lineWidthLabel = QtGui.QLabel(self.displayGroupBox)
+        self.lineWidthLabel.setObjectName("lineWidthLabel")
+        self.gridLayout_2.addWidget(self.lineWidthLabel, 1, 0, 1, 1)
+        self.lineStyleLabel = QtGui.QLabel(self.displayGroupBox)
+        self.lineStyleLabel.setObjectName("lineStyleLabel")
+        self.gridLayout_2.addWidget(self.lineStyleLabel, 2, 0, 1, 1)
+        self.lineStyleComboBox = QtGui.QComboBox(self.displayGroupBox)
+        self.lineStyleComboBox.setMinimumSize(QtCore.QSize(100, 0))
+        self.lineStyleComboBox.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.lineStyleComboBox.setObjectName("lineStyleComboBox")
+        self.gridLayout_2.addWidget(self.lineStyleComboBox, 2, 1, 1, 1)
+        self.styleSizeLabel = QtGui.QLabel(self.displayGroupBox)
+        self.styleSizeLabel.setObjectName("styleSizeLabel")
+        self.gridLayout_2.addWidget(self.styleSizeLabel, 3, 0, 1, 1)
+        self.styleSizeSpinBox = QtGui.QSpinBox(self.displayGroupBox)
+        self.styleSizeSpinBox.setMinimumSize(QtCore.QSize(100, 0))
+        self.styleSizeSpinBox.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.styleSizeSpinBox.setObjectName("styleSizeSpinBox")
+        self.gridLayout_2.addWidget(self.styleSizeSpinBox, 3, 1, 1, 1)
+        self.gridLayout.addWidget(self.displayGroupBox, 2, 2, 1, 1)
+        self.sysGroupBox = QtGui.QGroupBox(self.centralwidget)
+        self.sysGroupBox.setMinimumSize(QtCore.QSize(200, 0))
+        self.sysGroupBox.setObjectName("sysGroupBox")
+        self.formLayout = QtGui.QFormLayout(self.sysGroupBox)
+        self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
+        self.formLayout.setObjectName("formLayout")
+        self.sampleRateLabel = QtGui.QLabel(self.sysGroupBox)
+        self.sampleRateLabel.setObjectName("sampleRateLabel")
+        self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.sampleRateLabel)
+        self.sampleRateLineEdit = QtGui.QLineEdit(self.sysGroupBox)
+        self.sampleRateLineEdit.setMinimumSize(QtCore.QSize(50, 0))
+        self.sampleRateLineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
+        self.sampleRateLineEdit.setObjectName("sampleRateLineEdit")
+        self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.sampleRateLineEdit)
+        self.gridLayout.addWidget(self.sysGroupBox, 2, 1, 1, 1)
+        self.frame = QtGui.QFrame(self.centralwidget)
+        self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
+        self.frame.setFrameShadow(QtGui.QFrame.Raised)
+        self.frame.setObjectName("frame")
+        self.gridLayout_3 = QtGui.QGridLayout(self.frame)
+        self.gridLayout_3.setObjectName("gridLayout_3")
+        self.tabGroup = QtGui.QTabWidget(self.frame)
+        self.tabGroup.setMinimumSize(QtCore.QSize(0, 0))
         self.tabGroup.setObjectName("tabGroup")
         self.timeTab = QtGui.QWidget()
         self.timeTab.setObjectName("timeTab")
@@ -41,14 +156,14 @@ class Ui_MainWindow(object):
         self.formLayout_4 = QtGui.QFormLayout(self.fftPropBox)
         self.formLayout_4.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
         self.formLayout_4.setObjectName("formLayout_4")
+        self.psdFFTSizeLabel = QtGui.QLabel(self.fftPropBox)
+        self.psdFFTSizeLabel.setObjectName("psdFFTSizeLabel")
+        self.formLayout_4.setWidget(0, QtGui.QFormLayout.LabelRole, self.psdFFTSizeLabel)
         self.psdFFTComboBox = QtGui.QComboBox(self.fftPropBox)
         self.psdFFTComboBox.setMinimumSize(QtCore.QSize(96, 0))
         self.psdFFTComboBox.setMaximumSize(QtCore.QSize(96, 16777215))
         self.psdFFTComboBox.setObjectName("psdFFTComboBox")
         self.formLayout_4.setWidget(0, QtGui.QFormLayout.FieldRole, self.psdFFTComboBox)
-        self.psdFFTSizeLabel = QtGui.QLabel(self.fftPropBox)
-        self.psdFFTSizeLabel.setObjectName("psdFFTSizeLabel")
-        self.formLayout_4.setWidget(0, QtGui.QFormLayout.LabelRole, self.psdFFTSizeLabel)
         self.horizontalLayout_2.addWidget(self.fftPropBox)
         self.freqPlot = Qwt5.QwtPlot(self.freqTab)
         self.freqPlot.setObjectName("freqPlot")
@@ -75,87 +190,8 @@ class Ui_MainWindow(object):
         self.specPlot.setObjectName("specPlot")
         self.horizontalLayout_3.addWidget(self.specPlot)
         self.tabGroup.addTab(self.specTab, "")
-        self.gridLayout.addWidget(self.tabGroup, 1, 0, 1, 1)
-        self.filePosBox = QtGui.QGroupBox(self.centralwidget)
-        self.filePosBox.setMinimumSize(QtCore.QSize(0, 120))
-        self.filePosBox.setObjectName("filePosBox")
-        self.formLayoutWidget_2 = QtGui.QWidget(self.filePosBox)
-        self.formLayoutWidget_2.setGeometry(QtCore.QRect(0, 20, 160, 92))
-        self.formLayoutWidget_2.setObjectName("formLayoutWidget_2")
-        self.filePosLayout = QtGui.QFormLayout(self.formLayoutWidget_2)
-        self.filePosLayout.setObjectName("filePosLayout")
-        self.filePosStartLabel = QtGui.QLabel(self.formLayoutWidget_2)
-        self.filePosStartLabel.setObjectName("filePosStartLabel")
-        self.filePosLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.filePosStartLabel)
-        self.filePosStartLineEdit = QtGui.QLineEdit(self.formLayoutWidget_2)
-        self.filePosStartLineEdit.setObjectName("filePosStartLineEdit")
-        self.filePosLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.filePosStartLineEdit)
-        self.filePosStopLabel = QtGui.QLabel(self.formLayoutWidget_2)
-        self.filePosStopLabel.setObjectName("filePosStopLabel")
-        self.filePosLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.filePosStopLabel)
-        self.filePosStopLineEdit = QtGui.QLineEdit(self.formLayoutWidget_2)
-        self.filePosStopLineEdit.setObjectName("filePosStopLineEdit")
-        self.filePosLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.filePosStopLineEdit)
-        self.filePosLengthLabel = QtGui.QLabel(self.formLayoutWidget_2)
-        self.filePosLengthLabel.setObjectName("filePosLengthLabel")
-        self.filePosLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.filePosLengthLabel)
-        self.filePosLengthLineEdit = QtGui.QLineEdit(self.formLayoutWidget_2)
-        self.filePosLengthLineEdit.setObjectName("filePosLengthLineEdit")
-        self.filePosLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.filePosLengthLineEdit)
-        self.formLayoutWidget_4 = QtGui.QWidget(self.filePosBox)
-        self.formLayoutWidget_4.setGeometry(QtCore.QRect(180, 20, 231, 92))
-        self.formLayoutWidget_4.setObjectName("formLayoutWidget_4")
-        self.fileTimeLayout = QtGui.QFormLayout(self.formLayoutWidget_4)
-        self.fileTimeLayout.setObjectName("fileTimeLayout")
-        self.fileTimeStartLabel = QtGui.QLabel(self.formLayoutWidget_4)
-        self.fileTimeStartLabel.setObjectName("fileTimeStartLabel")
-        self.fileTimeLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.fileTimeStartLabel)
-        self.fileTimeStartLineEdit = QtGui.QLineEdit(self.formLayoutWidget_4)
-        self.fileTimeStartLineEdit.setObjectName("fileTimeStartLineEdit")
-        self.fileTimeLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.fileTimeStartLineEdit)
-        self.fileTimeStopLabel = QtGui.QLabel(self.formLayoutWidget_4)
-        self.fileTimeStopLabel.setObjectName("fileTimeStopLabel")
-        self.fileTimeLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.fileTimeStopLabel)
-        self.fileTimeStopLineEdit = QtGui.QLineEdit(self.formLayoutWidget_4)
-        self.fileTimeStopLineEdit.setObjectName("fileTimeStopLineEdit")
-        self.fileTimeLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.fileTimeStopLineEdit)
-        self.fileTimeLengthLabel = QtGui.QLabel(self.formLayoutWidget_4)
-        self.fileTimeLengthLabel.setObjectName("fileTimeLengthLabel")
-        self.fileTimeLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.fileTimeLengthLabel)
-        self.fileTimeLengthLineEdit = QtGui.QLineEdit(self.formLayoutWidget_4)
-        self.fileTimeLengthLineEdit.setObjectName("fileTimeLengthLineEdit")
-        self.fileTimeLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.fileTimeLengthLineEdit)
-        self.sysGroupBox = QtGui.QGroupBox(self.filePosBox)
-        self.sysGroupBox.setGeometry(QtCore.QRect(530, 0, 200, 120))
-        self.sysGroupBox.setMinimumSize(QtCore.QSize(200, 0))
-        self.sysGroupBox.setObjectName("sysGroupBox")
-        self.formLayoutWidget_3 = QtGui.QWidget(self.sysGroupBox)
-        self.formLayoutWidget_3.setGeometry(QtCore.QRect(0, 20, 191, 91))
-        self.formLayoutWidget_3.setObjectName("formLayoutWidget_3")
-        self.formLayout_2 = QtGui.QFormLayout(self.formLayoutWidget_3)
-        self.formLayout_2.setObjectName("formLayout_2")
-        self.sampleRateLabel = QtGui.QLabel(self.formLayoutWidget_3)
-        self.sampleRateLabel.setObjectName("sampleRateLabel")
-        self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.sampleRateLabel)
-        self.sampleRateLineEdit = QtGui.QLineEdit(self.formLayoutWidget_3)
-        self.sampleRateLineEdit.setMinimumSize(QtCore.QSize(0, 0))
-        self.sampleRateLineEdit.setObjectName("sampleRateLineEdit")
-        self.formLayout_2.setWidget(0, QtGui.QFormLayout.FieldRole, self.sampleRateLineEdit)
-        self.displayGroupBox = QtGui.QGroupBox(self.filePosBox)
-        self.displayGroupBox.setGeometry(QtCore.QRect(730, 0, 170, 120))
-        self.displayGroupBox.setMinimumSize(QtCore.QSize(170, 0))
-        self.displayGroupBox.setObjectName("displayGroupBox")
-        self.verticalLayoutWidget = QtGui.QWidget(self.displayGroupBox)
-        self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 20, 160, 91))
-        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
-        self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget)
-        self.verticalLayout.setObjectName("verticalLayout")
-        self.colorComboBox = QtGui.QComboBox(self.verticalLayoutWidget)
-        self.colorComboBox.setObjectName("colorComboBox")
-        self.verticalLayout.addWidget(self.colorComboBox)
-        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
-        self.verticalLayout.addItem(spacerItem)
-        self.gridLayout.addWidget(self.filePosBox, 3, 0, 1, 1)
+        self.gridLayout_3.addWidget(self.tabGroup, 0, 0, 1, 1)
+        self.gridLayout.addWidget(self.frame, 0, 0, 1, 3)
         MainWindow.setCentralWidget(self.centralwidget)
         self.menubar = QtGui.QMenuBar(MainWindow)
         self.menubar.setGeometry(QtCore.QRect(0, 0, 927, 24))
@@ -170,7 +206,10 @@ class Ui_MainWindow(object):
         self.action_open.setObjectName("action_open")
         self.action_exit = QtGui.QAction(MainWindow)
         self.action_exit.setObjectName("action_exit")
+        self.action_reload = QtGui.QAction(MainWindow)
+        self.action_reload.setObjectName("action_reload")
         self.menu_File.addAction(self.action_open)
+        self.menu_File.addAction(self.action_reload)
         self.menu_File.addAction(self.action_exit)
         self.menubar.addAction(self.menu_File.menuAction())
 
@@ -181,26 +220,30 @@ class Ui_MainWindow(object):
 
     def retranslateUi(self, MainWindow):
         MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
-        self.tabGroup.setTabText(self.tabGroup.indexOf(self.timeTab), QtGui.QApplication.translate("MainWindow", "Time Domain", None, QtGui.QApplication.UnicodeUTF8))
-        self.fftPropBox.setTitle(QtGui.QApplication.translate("MainWindow", "FFT Properties", None, QtGui.QApplication.UnicodeUTF8))
-        self.psdFFTSizeLabel.setText(QtGui.QApplication.translate("MainWindow", "FFT Size", None, QtGui.QApplication.UnicodeUTF8))
-        self.tabGroup.setTabText(self.tabGroup.indexOf(self.freqTab), QtGui.QApplication.translate("MainWindow", "Frequency Domain", None, QtGui.QApplication.UnicodeUTF8))
-        self.groupBox.setTitle(QtGui.QApplication.translate("MainWindow", "Spectrogram Properties", None, QtGui.QApplication.UnicodeUTF8))
-        self.specFFTLabel.setText(QtGui.QApplication.translate("MainWindow", "FFT Size", None, QtGui.QApplication.UnicodeUTF8))
-        self.tabGroup.setTabText(self.tabGroup.indexOf(self.specTab), QtGui.QApplication.translate("MainWindow", "Spectrogram", None, QtGui.QApplication.UnicodeUTF8))
         self.filePosBox.setTitle(QtGui.QApplication.translate("MainWindow", "File Position", None, QtGui.QApplication.UnicodeUTF8))
-        self.filePosStartLabel.setText(QtGui.QApplication.translate("MainWindow", "Start", None, QtGui.QApplication.UnicodeUTF8))
         self.filePosStopLabel.setText(QtGui.QApplication.translate("MainWindow", "Stop", None, QtGui.QApplication.UnicodeUTF8))
         self.filePosLengthLabel.setText(QtGui.QApplication.translate("MainWindow", "Length", None, QtGui.QApplication.UnicodeUTF8))
+        self.filePosStartLabel.setText(QtGui.QApplication.translate("MainWindow", "Start", None, QtGui.QApplication.UnicodeUTF8))
         self.fileTimeStartLabel.setText(QtGui.QApplication.translate("MainWindow", "time start (sec)", None, QtGui.QApplication.UnicodeUTF8))
         self.fileTimeStopLabel.setText(QtGui.QApplication.translate("MainWindow", "time stop (sec)", None, QtGui.QApplication.UnicodeUTF8))
         self.fileTimeLengthLabel.setText(QtGui.QApplication.translate("MainWindow", "time length (sec)", None, QtGui.QApplication.UnicodeUTF8))
+        self.displayGroupBox.setTitle(QtGui.QApplication.translate("MainWindow", "Display Properties", None, QtGui.QApplication.UnicodeUTF8))
+        self.lineWidthLabel.setText(QtGui.QApplication.translate("MainWindow", "Line Width", None, QtGui.QApplication.UnicodeUTF8))
+        self.lineStyleLabel.setText(QtGui.QApplication.translate("MainWindow", "Line Style", None, QtGui.QApplication.UnicodeUTF8))
+        self.styleSizeLabel.setText(QtGui.QApplication.translate("MainWindow", "Style Size", None, QtGui.QApplication.UnicodeUTF8))
         self.sysGroupBox.setTitle(QtGui.QApplication.translate("MainWindow", "System Properties", None, QtGui.QApplication.UnicodeUTF8))
         self.sampleRateLabel.setText(QtGui.QApplication.translate("MainWindow", "Sample Rate", None, QtGui.QApplication.UnicodeUTF8))
-        self.displayGroupBox.setTitle(QtGui.QApplication.translate("MainWindow", "Display Properties", None, QtGui.QApplication.UnicodeUTF8))
+        self.tabGroup.setTabText(self.tabGroup.indexOf(self.timeTab), QtGui.QApplication.translate("MainWindow", "Time Domain", None, QtGui.QApplication.UnicodeUTF8))
+        self.fftPropBox.setTitle(QtGui.QApplication.translate("MainWindow", "FFT Properties", None, QtGui.QApplication.UnicodeUTF8))
+        self.psdFFTSizeLabel.setText(QtGui.QApplication.translate("MainWindow", "FFT Size", None, QtGui.QApplication.UnicodeUTF8))
+        self.tabGroup.setTabText(self.tabGroup.indexOf(self.freqTab), QtGui.QApplication.translate("MainWindow", "Frequency Domain", None, QtGui.QApplication.UnicodeUTF8))
+        self.groupBox.setTitle(QtGui.QApplication.translate("MainWindow", "Spectrogram Properties", None, QtGui.QApplication.UnicodeUTF8))
+        self.specFFTLabel.setText(QtGui.QApplication.translate("MainWindow", "FFT Size", None, QtGui.QApplication.UnicodeUTF8))
+        self.tabGroup.setTabText(self.tabGroup.indexOf(self.specTab), QtGui.QApplication.translate("MainWindow", "Spectrogram", None, QtGui.QApplication.UnicodeUTF8))
         self.menu_File.setTitle(QtGui.QApplication.translate("MainWindow", "&File", None, QtGui.QApplication.UnicodeUTF8))
         self.action_open.setText(QtGui.QApplication.translate("MainWindow", "&Open", None, QtGui.QApplication.UnicodeUTF8))
         self.action_open.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+O", None, QtGui.QApplication.UnicodeUTF8))
         self.action_exit.setText(QtGui.QApplication.translate("MainWindow", "E&xit", None, QtGui.QApplication.UnicodeUTF8))
+        self.action_reload.setText(QtGui.QApplication.translate("MainWindow", "&Reload", None, QtGui.QApplication.UnicodeUTF8))
 
 from PyQt4 import Qwt5
index 19a62adf549e6111d871ca049fa7842336a92dd2..7244d24c9d2d878191e02e0b2f599ea229fd0ca8 100644 (file)
@@ -6,7 +6,7 @@
     <x>0</x>
     <y>0</y>
     <width>927</width>
-    <height>696</height>
+    <height>718</height>
    </rect>
   </property>
   <property name="windowTitle" >
   </property>
   <widget class="QWidget" name="centralwidget" >
    <layout class="QGridLayout" name="gridLayout" >
-    <item row="2" column="0" colspan="2" >
+    <item row="1" column="0" colspan="3" >
      <widget class="QScrollBar" name="plotHBar" >
       <property name="orientation" >
        <enum>Qt::Horizontal</enum>
       </property>
      </widget>
     </item>
-    <item row="1" column="0" >
-     <widget class="QTabWidget" name="tabGroup" >
-      <property name="currentIndex" >
-       <number>0</number>
-      </property>
-      <widget class="QWidget" name="timeTab" >
-       <attribute name="title" >
-        <string>Time Domain</string>
-       </attribute>
-       <layout class="QHBoxLayout" name="horizontalLayout" >
-        <item>
-         <widget class="QwtPlot" name="timePlot" />
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="freqTab" >
-       <attribute name="title" >
-        <string>Frequency Domain</string>
-       </attribute>
-       <layout class="QHBoxLayout" name="horizontalLayout_2" >
-        <item>
-         <widget class="QGroupBox" name="fftPropBox" >
-          <property name="minimumSize" >
-           <size>
-            <width>160</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="title" >
-           <string>FFT Properties</string>
-          </property>
-          <layout class="QFormLayout" name="formLayout_4" >
-           <property name="fieldGrowthPolicy" >
-            <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
-           </property>
-           <item row="0" column="1" >
-            <widget class="QComboBox" name="psdFFTComboBox" >
-             <property name="minimumSize" >
-              <size>
-               <width>96</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize" >
-              <size>
-               <width>96</width>
-               <height>16777215</height>
-              </size>
-             </property>
-            </widget>
-           </item>
-           <item row="0" column="0" >
-            <widget class="QLabel" name="psdFFTSizeLabel" >
-             <property name="text" >
-              <string>FFT Size</string>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-        </item>
-        <item>
-         <widget class="QwtPlot" name="freqPlot" />
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="specTab" >
-       <attribute name="title" >
-        <string>Spectrogram</string>
-       </attribute>
-       <layout class="QHBoxLayout" name="horizontalLayout_3" >
-        <item>
-         <widget class="QGroupBox" name="groupBox" >
-          <property name="title" >
-           <string>Spectrogram Properties</string>
-          </property>
-          <layout class="QFormLayout" name="formLayout_3" >
-           <item row="1" column="0" >
-            <widget class="QLabel" name="specFFTLabel" >
-             <property name="text" >
-              <string>FFT Size</string>
-             </property>
-            </widget>
-           </item>
-           <item row="1" column="1" >
-            <widget class="QComboBox" name="specFFTComboBox" >
-             <property name="minimumSize" >
-              <size>
-               <width>96</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize" >
-              <size>
-               <width>96</width>
-               <height>16777215</height>
-              </size>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-        </item>
-        <item>
-         <widget class="QwtPlot" name="specPlot" />
-        </item>
-       </layout>
-       <zorder>specPlot</zorder>
-       <zorder>groupBox</zorder>
-      </widget>
-     </widget>
-    </item>
-    <item row="3" column="0" >
+    <item row="2" column="0" >
      <widget class="QGroupBox" name="filePosBox" >
       <property name="minimumSize" >
        <size>
       <property name="title" >
        <string>File Position</string>
       </property>
-      <widget class="QWidget" name="formLayoutWidget_2" >
-       <property name="geometry" >
-        <rect>
-         <x>0</x>
-         <y>20</y>
-         <width>160</width>
-         <height>92</height>
-        </rect>
-       </property>
-       <layout class="QFormLayout" name="filePosLayout" >
-        <item row="0" column="0" >
-         <widget class="QLabel" name="filePosStartLabel" >
-          <property name="text" >
-           <string>Start</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="1" >
-         <widget class="QLineEdit" name="filePosStartLineEdit" />
-        </item>
-        <item row="1" column="0" >
-         <widget class="QLabel" name="filePosStopLabel" >
-          <property name="text" >
-           <string>Stop</string>
-          </property>
-         </widget>
-        </item>
-        <item row="1" column="1" >
-         <widget class="QLineEdit" name="filePosStopLineEdit" />
-        </item>
-        <item row="2" column="0" >
-         <widget class="QLabel" name="filePosLengthLabel" >
-          <property name="text" >
-           <string>Length</string>
-          </property>
-         </widget>
-        </item>
-        <item row="2" column="1" >
-         <widget class="QLineEdit" name="filePosLengthLineEdit" />
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="formLayoutWidget_4" >
-       <property name="geometry" >
-        <rect>
-         <x>180</x>
-         <y>20</y>
-         <width>231</width>
-         <height>92</height>
-        </rect>
-       </property>
-       <layout class="QFormLayout" name="fileTimeLayout" >
-        <item row="0" column="0" >
-         <widget class="QLabel" name="fileTimeStartLabel" >
-          <property name="text" >
-           <string>time start (sec)</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="1" >
-         <widget class="QLineEdit" name="fileTimeStartLineEdit" />
-        </item>
-        <item row="1" column="0" >
-         <widget class="QLabel" name="fileTimeStopLabel" >
-          <property name="text" >
-           <string>time stop (sec)</string>
-          </property>
-         </widget>
-        </item>
-        <item row="1" column="1" >
-         <widget class="QLineEdit" name="fileTimeStopLineEdit" />
-        </item>
-        <item row="2" column="0" >
-         <widget class="QLabel" name="fileTimeLengthLabel" >
-          <property name="text" >
-           <string>time length (sec)</string>
-          </property>
-         </widget>
-        </item>
-        <item row="2" column="1" >
-         <widget class="QLineEdit" name="fileTimeLengthLineEdit" />
-        </item>
-       </layout>
-      </widget>
-      <widget class="QGroupBox" name="sysGroupBox" >
-       <property name="geometry" >
-        <rect>
-         <x>530</x>
-         <y>0</y>
-         <width>200</width>
-         <height>120</height>
-        </rect>
-       </property>
-       <property name="minimumSize" >
-        <size>
-         <width>200</width>
-         <height>0</height>
-        </size>
-       </property>
-       <property name="title" >
-        <string>System Properties</string>
-       </property>
-       <widget class="QWidget" name="formLayoutWidget_3" >
-        <property name="geometry" >
-         <rect>
-          <x>0</x>
-          <y>20</y>
-          <width>191</width>
-          <height>91</height>
-         </rect>
-        </property>
-        <layout class="QFormLayout" name="formLayout_2" >
+      <layout class="QGridLayout" name="gridLayout_4" >
+       <item row="0" column="0" >
+        <layout class="QFormLayout" name="filePosLayout" >
+         <item row="0" column="1" >
+          <widget class="QLineEdit" name="filePosStartLineEdit" >
+           <property name="minimumSize" >
+            <size>
+             <width>50</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="maximumSize" >
+            <size>
+             <width>100</width>
+             <height>16777215</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0" >
+          <widget class="QLabel" name="filePosStopLabel" >
+           <property name="text" >
+            <string>Stop</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1" >
+          <widget class="QLineEdit" name="filePosStopLineEdit" >
+           <property name="minimumSize" >
+            <size>
+             <width>50</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="maximumSize" >
+            <size>
+             <width>100</width>
+             <height>16777215</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="0" >
+          <widget class="QLabel" name="filePosLengthLabel" >
+           <property name="text" >
+            <string>Length</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1" >
+          <widget class="QLineEdit" name="filePosLengthLineEdit" >
+           <property name="minimumSize" >
+            <size>
+             <width>50</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="maximumSize" >
+            <size>
+             <width>100</width>
+             <height>16777215</height>
+            </size>
+           </property>
+          </widget>
+         </item>
          <item row="0" column="0" >
-          <widget class="QLabel" name="sampleRateLabel" >
+          <widget class="QLabel" name="filePosStartLabel" >
            <property name="text" >
-            <string>Sample Rate</string>
+            <string>Start</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="1" >
+        <layout class="QFormLayout" name="fileTimeLayout" >
+         <item row="0" column="0" >
+          <widget class="QLabel" name="fileTimeStartLabel" >
+           <property name="text" >
+            <string>time start (sec)</string>
            </property>
           </widget>
          </item>
          <item row="0" column="1" >
-          <widget class="QLineEdit" name="sampleRateLineEdit" >
+          <widget class="QLineEdit" name="fileTimeStartLineEdit" >
            <property name="minimumSize" >
             <size>
-             <width>0</width>
+             <width>50</width>
              <height>0</height>
             </size>
            </property>
+           <property name="maximumSize" >
+            <size>
+             <width>100</width>
+             <height>16777215</height>
+            </size>
+           </property>
           </widget>
          </item>
-        </layout>
-       </widget>
-      </widget>
-      <widget class="QGroupBox" name="displayGroupBox" >
-       <property name="geometry" >
-        <rect>
-         <x>730</x>
-         <y>0</y>
-         <width>170</width>
-         <height>120</height>
-        </rect>
-       </property>
-       <property name="minimumSize" >
-        <size>
-         <width>170</width>
-         <height>0</height>
-        </size>
-       </property>
-       <property name="title" >
-        <string>Display Properties</string>
-       </property>
-       <widget class="QWidget" name="verticalLayoutWidget" >
-        <property name="geometry" >
-         <rect>
-          <x>0</x>
-          <y>20</y>
-          <width>160</width>
-          <height>91</height>
-         </rect>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout" >
-         <item>
-          <widget class="QComboBox" name="colorComboBox" />
+         <item row="1" column="0" >
+          <widget class="QLabel" name="fileTimeStopLabel" >
+           <property name="text" >
+            <string>time stop (sec)</string>
+           </property>
+          </widget>
          </item>
-         <item>
-          <spacer name="verticalSpacer" >
-           <property name="orientation" >
-            <enum>Qt::Vertical</enum>
+         <item row="1" column="1" >
+          <widget class="QLineEdit" name="fileTimeStopLineEdit" >
+           <property name="minimumSize" >
+            <size>
+             <width>50</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="maximumSize" >
+            <size>
+             <width>100</width>
+             <height>16777215</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="0" >
+          <widget class="QLabel" name="fileTimeLengthLabel" >
+           <property name="text" >
+            <string>time length (sec)</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1" >
+          <widget class="QLineEdit" name="fileTimeLengthLineEdit" >
+           <property name="minimumSize" >
+            <size>
+             <width>50</width>
+             <height>0</height>
+            </size>
            </property>
-           <property name="sizeHint" stdset="0" >
+           <property name="maximumSize" >
             <size>
-             <width>20</width>
-             <height>40</height>
+             <width>100</width>
+             <height>16777215</height>
             </size>
            </property>
-          </spacer>
+          </widget>
          </item>
         </layout>
-       </widget>
-      </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="2" column="2" >
+     <widget class="QGroupBox" name="displayGroupBox" >
+      <property name="minimumSize" >
+       <size>
+        <width>170</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="title" >
+       <string>Display Properties</string>
+      </property>
+      <layout class="QGridLayout" name="gridLayout_2" >
+       <item row="0" column="0" colspan="2" >
+        <widget class="QComboBox" name="colorComboBox" />
+       </item>
+       <item row="1" column="1" >
+        <widget class="QSpinBox" name="lineWidthSpinBox" >
+         <property name="minimumSize" >
+          <size>
+           <width>100</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>100</width>
+           <height>16777215</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0" >
+        <widget class="QLabel" name="lineWidthLabel" >
+         <property name="text" >
+          <string>Line Width</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0" >
+        <widget class="QLabel" name="lineStyleLabel" >
+         <property name="text" >
+          <string>Line Style</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1" >
+        <widget class="QComboBox" name="lineStyleComboBox" >
+         <property name="minimumSize" >
+          <size>
+           <width>100</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>100</width>
+           <height>16777215</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0" >
+        <widget class="QLabel" name="styleSizeLabel" >
+         <property name="text" >
+          <string>Style Size</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="1" >
+        <widget class="QSpinBox" name="styleSizeSpinBox" >
+         <property name="minimumSize" >
+          <size>
+           <width>100</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>100</width>
+           <height>16777215</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="2" column="1" >
+     <widget class="QGroupBox" name="sysGroupBox" >
+      <property name="minimumSize" >
+       <size>
+        <width>200</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="title" >
+       <string>System Properties</string>
+      </property>
+      <layout class="QFormLayout" name="formLayout" >
+       <property name="fieldGrowthPolicy" >
+        <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+       </property>
+       <item row="0" column="0" >
+        <widget class="QLabel" name="sampleRateLabel" >
+         <property name="text" >
+          <string>Sample Rate</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1" >
+        <widget class="QLineEdit" name="sampleRateLineEdit" >
+         <property name="minimumSize" >
+          <size>
+           <width>50</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>100</width>
+           <height>16777215</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="0" column="0" colspan="3" >
+     <widget class="QFrame" name="frame" >
+      <property name="frameShape" >
+       <enum>QFrame::StyledPanel</enum>
+      </property>
+      <property name="frameShadow" >
+       <enum>QFrame::Raised</enum>
+      </property>
+      <layout class="QGridLayout" name="gridLayout_3" >
+       <item row="0" column="0" >
+        <widget class="QTabWidget" name="tabGroup" >
+         <property name="minimumSize" >
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="currentIndex" >
+          <number>0</number>
+         </property>
+         <widget class="QWidget" name="timeTab" >
+          <attribute name="title" >
+           <string>Time Domain</string>
+          </attribute>
+          <layout class="QHBoxLayout" name="horizontalLayout" >
+           <item>
+            <widget class="QwtPlot" name="timePlot" />
+           </item>
+          </layout>
+          <zorder>timePlot</zorder>
+         </widget>
+         <widget class="QWidget" name="freqTab" >
+          <attribute name="title" >
+           <string>Frequency Domain</string>
+          </attribute>
+          <layout class="QHBoxLayout" name="horizontalLayout_2" >
+           <item>
+            <widget class="QGroupBox" name="fftPropBox" >
+             <property name="minimumSize" >
+              <size>
+               <width>160</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="title" >
+              <string>FFT Properties</string>
+             </property>
+             <layout class="QFormLayout" name="formLayout_4" >
+              <property name="fieldGrowthPolicy" >
+               <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+              </property>
+              <item row="0" column="0" >
+               <widget class="QLabel" name="psdFFTSizeLabel" >
+                <property name="text" >
+                 <string>FFT Size</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1" >
+               <widget class="QComboBox" name="psdFFTComboBox" >
+                <property name="minimumSize" >
+                 <size>
+                  <width>96</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize" >
+                 <size>
+                  <width>96</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+               </widget>
+              </item>
+             </layout>
+             <zorder>psdFFTSizeLabel</zorder>
+             <zorder>psdFFTComboBox</zorder>
+            </widget>
+           </item>
+           <item>
+            <widget class="QwtPlot" name="freqPlot" />
+           </item>
+          </layout>
+         </widget>
+         <widget class="QWidget" name="specTab" >
+          <attribute name="title" >
+           <string>Spectrogram</string>
+          </attribute>
+          <layout class="QHBoxLayout" name="horizontalLayout_3" >
+           <item>
+            <widget class="QGroupBox" name="groupBox" >
+             <property name="title" >
+              <string>Spectrogram Properties</string>
+             </property>
+             <layout class="QFormLayout" name="formLayout_3" >
+              <item row="1" column="0" >
+               <widget class="QLabel" name="specFFTLabel" >
+                <property name="text" >
+                 <string>FFT Size</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="1" >
+               <widget class="QComboBox" name="specFFTComboBox" >
+                <property name="minimumSize" >
+                 <size>
+                  <width>96</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize" >
+                 <size>
+                  <width>96</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </item>
+           <item>
+            <widget class="QwtPlot" name="specPlot" />
+           </item>
+          </layout>
+          <zorder>specPlot</zorder>
+          <zorder>groupBox</zorder>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+      <zorder>tabGroup</zorder>
      </widget>
     </item>
    </layout>
      <string>&amp;File</string>
     </property>
     <addaction name="action_open" />
+    <addaction name="action_reload" />
     <addaction name="action_exit" />
    </widget>
    <addaction name="menu_File" />
     <string>E&amp;xit</string>
    </property>
   </action>
+  <action name="action_reload" >
+   <property name="text" >
+    <string>&amp;Reload</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
diff --git a/gr-utils/src/python/qr_fft.py b/gr-utils/src/python/qr_fft.py
deleted file mode 100755 (executable)
index c2f06d7..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2004,2005,2007,2008,2009 Free Software Foundation, Inc.
-# 
-# This file is part of GNU Radio
-# 
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-# 
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING.  If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-# 
-
-from gnuradio.wxgui import forms
-from gnuradio import gr, gru
-from gnuradio import vrt
-from gnuradio import eng_notation
-from gnuradio.eng_option import eng_option
-from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider
-from gnuradio.gr import pubsub
-from optparse import OptionParser
-import wx
-import sys
-import numpy
-import time
-
-class app_top_block(stdgui2.std_top_block, pubsub.pubsub):
-    def __init__(self, frame, panel, vbox, argv):
-        stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
-        pubsub.pubsub.__init__(self)
-        self.frame = frame
-        self.panel = panel
-        
-        parser = OptionParser(option_class=eng_option)
-        #parser.add_option("-e", "--interface", type="string", default="eth0",
-        #                  help="select Ethernet interface, default is eth0")
-        #parser.add_option("-m", "--mac-addr", type="string", default="",
-        #                  help="select USRP by MAC address, default is auto-select")
-        #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("-W", "--waterfall", action="store_true", default=False,
-                          help="Enable waterfall display")
-        parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
-                          help="Enable oscilloscope display")
-       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=1.0,
-                         help="Set dBFS=0dB input value, default=[%default]")
-        parser.add_option("--fft-size", type="int", default=1024,
-                          help="Set number of FFT bins [default=%default]")
-        parser.add_option("--samples-per-pkt", type="int", default=0,
-                          help="Set number of SAMPLES-PER-PKT [default=%default]")
-        parser.add_option("", "--ip-addr", type="string", default="192.168.10.2",
-                          help="IP address default=[%default]")
-        (options, args) = parser.parse_args()
-        if len(args) != 0:
-            parser.print_help()
-            sys.exit(1)
-       self.options = options
-        self.show_debug_info = True
-        
-        self.u = vrt.quadradio_source_32fc(options.ip_addr,
-                                           int(62.5e6), options.samples_per_pkt)
-        #self.u.set_decim(options.decim)
-        
-        #input_rate = self.u.adc_rate() / self.u.decim()
-        input_rate = int(120e6/4)
-        
-        if options.waterfall:
-            self.scope = \
-              waterfallsink2.waterfall_sink_c (panel, fft_size=1024, sample_rate=input_rate)
-        elif options.oscilloscope:
-            self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate)
-        else:
-            self.scope = fftsink2.fft_sink_c (panel,
-                                              fft_size=options.fft_size,
-                                              sample_rate=input_rate, 
-                                             ref_scale=options.ref_scale,
-                                              ref_level=20.0,
-                                              y_divs = 12,
-                                             avg_alpha=options.avg_alpha)
-
-        self.connect(self.u, self.scope)
-
-        self._build_gui(vbox)
-       self._setup_events()
-       
-        # set initial values
-
-        #if options.gain is None:
-        #    # if no gain was specified, use the mid-point in dB
-        #    g = self.u.gain_range()
-        #    options.gain = float(g[0]+g[1])/2
-
-        #if options.freq is None:
-        #    # if no freq was specified, use the mid-point
-        #    r = self.u.freq_range()
-        #    options.freq = float(r[0]+r[1])/2
-            
-        #self.set_gain(options.gain)
-
-       #if options.antenna is not None:
-        #    print "Selecting antenna %s" % (options.antenna,)
-        #    self.subdev.select_rx_antenna(options.antenna)
-
-        if self.show_debug_info:
-        #    self.myform['decim'].set_value(self.u.decim())
-            self.myform['fs@gbe'].set_value(input_rate)
-        #    self.myform['dbname'].set_value("0x%04X" % (self.u.daughterboard_id(),)) # FIXME: add text name
-            self.myform['baseband'].set_value(0)
-            self.myform['ddc'].set_value(0)
-
-        #if not(self.set_freq(options.freq)):
-        #    self._set_status_msg("Failed to set initial frequency")
-
-    def _set_status_msg(self, msg):
-        self.frame.GetStatusBar().SetStatusText(msg, 0)
-
-    def _build_gui(self, vbox):
-
-        def _form_set_freq(kv):
-            return self.set_freq(kv['freq'])
-            
-        vbox.Add(self.scope.win, 10, wx.EXPAND)
-        
-        # add control area at the bottom
-        self.myform = myform = form.form()
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add((5,0), 0, 0)
-        myform['freq'] = form.float_field(
-            parent=self.panel, sizer=hbox, label="Center freq", weight=1,
-            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
-
-        hbox.Add((5,0), 0, 0)
-        #g = self.u.gain_range()
-
-       # some configurations don't have gain control
-       if 0 and g[1] > g[0]:
-           myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain",
-                                           weight=3,
-                                           min=int(g[0]), max=int(g[1]),
-                                           callback=self.set_gain)
-
-        hbox.Add((5,0), 0, 0)
-        vbox.Add(hbox, 0, wx.EXPAND)
-
-        self._build_subpanel(vbox)
-
-    def _build_subpanel(self, vbox_arg):
-        # build a secondary information panel (sometimes hidden)
-
-        # FIXME figure out how to have this be a subpanel that is always
-        # created, but has its visibility controlled by foo.Show(True/False)
-        
-        def _form_set_decim(kv):
-            return self.set_decim(kv['decim'])
-
-        if not(self.show_debug_info):
-            return
-
-        panel = self.panel
-        vbox = vbox_arg
-        myform = self.myform
-
-        #panel = wx.Panel(self.panel, -1)
-        #vbox = wx.BoxSizer(wx.VERTICAL)
-
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add((5,0), 0)
-
-        myform['decim'] = form.int_field(
-            parent=panel, sizer=hbox, label="Decim",
-            callback=myform.check_input_and_call(_form_set_decim, self._set_status_msg))
-
-        hbox.Add((5,0), 1)
-        myform['fs@gbe'] = form.static_float_field(
-            parent=panel, sizer=hbox, label="Fs@GbE")
-
-        hbox.Add((5,0), 1)
-        myform['dbname'] = form.static_text_field(
-            parent=panel, sizer=hbox)
-
-        hbox.Add((5,0), 1)
-        myform['baseband'] = form.static_float_field(
-            parent=panel, sizer=hbox, label="Analog BB")
-
-        hbox.Add((5,0), 1)
-        myform['ddc'] = form.static_float_field(
-            parent=panel, sizer=hbox, label="DDC")
-
-        hbox.Add((5,0), 0)
-        vbox.Add(hbox, 0, wx.EXPAND)
-        ##### db control stuff #####
-        self.subscribe('cal_div_lo_freq', lambda x: self.u.set_lo_freq(x) and time.sleep(0.01))
-        self.subscribe('cal_div_lo_freq', self.u.set_center_freq) #TODO should be combined with set lo freq
-        self.subscribe('cal_div_cal_freq', lambda x: self.u.set_cal_freq(x) and time.sleep(0.01))
-        self.subscribe('db_ctrl_atten0', self.u.set_attenuation0)
-        self.subscribe('db_ctrl_atten1', self.u.set_attenuation1)
-        self.subscribe('sys_beaming', self.u.set_beamforming)
-        #self.subscribe('db_ctrl_10db', self.u.set_10dB_atten)
-        self.subscribe('db_ctrl_adcgain', self.u.set_adc_gain)
-        self.subscribe('db_ctrl_diggain', self.u.set_digital_gain)
-        self.subscribe('db_ctrl_dcoffset', self.u.set_dc_offset_comp)
-        self.subscribe('db_ctrl_bandsel', self.u.set_band_select)
-        self.subscribe('db_ctrl_type', self.u.select_rx_antenna)
-        self.subscribe('db_test_signal', self.u.set_test_signal)
-        self['db_ctrl_bandsel'] = 'A'
-        self['cal_div_lo_freq'] = 2.1e9
-        self['cal_div_cal_freq'] = 2.102e9
-        self['db_ctrl_atten0'] = 0
-        self['db_ctrl_atten1'] = 0
-        #self['db_ctrl_10db'] = False
-        self['db_ctrl_adcgain'] = False
-        self['db_ctrl_dcoffset'] = False
-        self['db_ctrl_diggain'] = 0.0
-        self['db_ctrl_type'] = 'rf'
-        self['db_test_signal'] = vrt.VRT_TEST_SIG_NORMAL
-       self['sys_beaming'] = [16.7e6, 0, 0, 0]
-        #slider and box for freqs
-        for key, name in (('cal_div_lo_freq', 'LO Freq'), ('cal_div_cal_freq', 'Cal Freq')):
-            hbox = wx.BoxSizer(wx.HORIZONTAL)
-            hbox.AddSpacer(10)
-            forms.text_box(
-                label=name,
-                ps=self,
-                key=key,
-                sizer=hbox,
-                parent=panel,
-                proportion=0,
-                converter=forms.float_converter()
-            )
-            hbox.AddSpacer(20)
-            forms.slider(
-                ps=self,
-                key=key,
-                minimum=0,   #TODO get bounds from cal_div, from vrt...
-                maximum=int(3.5e9),
-                step_size=int(5e6),
-                cast=float,
-                sizer=hbox,
-                parent=panel,
-                proportion=2,
-            )
-            hbox.AddSpacer(10)
-            vbox.Add(hbox, 0, wx.EXPAND)
-        ############################################
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.AddSpacer(10)
-        #create slider for atten
-        atten0_txt_box = forms.static_text(
-            label='Attenuation (0)',
-            ps=self,
-            key='db_ctrl_atten0',
-            sizer=hbox,
-            parent=panel,
-            proportion=0,
-            converter=forms.int_converter()
-        )
-        hbox.AddSpacer(20)
-        atten0_slider = forms.slider(
-            ps=self,
-            key='db_ctrl_atten0',
-            minimum=0,
-            maximum=31,
-            step_size=1,
-            cast=int,
-            sizer=hbox,
-            parent=panel,
-            proportion=2,
-        )
-        hbox.AddSpacer(10)
-        #create slider for atten
-        forms.static_text(
-            label='Attenuation (1)',
-            ps=self,
-            key='db_ctrl_atten1',
-            sizer=hbox,
-            parent=panel,
-            proportion=0,
-            converter=forms.int_converter()
-        )
-        hbox.AddSpacer(20)
-        forms.slider(
-            ps=self,
-            key='db_ctrl_atten1',
-            minimum=0,
-            maximum=31,
-            step_size=1,
-            cast=int,
-            sizer=hbox,
-            parent=panel,
-            proportion=2,
-        )
-        hbox.AddSpacer(10)
-        def update_atten0(*args):
-            for form_obj in (atten0_txt_box, atten0_slider): form_obj.Enable(self['db_ctrl_bandsel'] > 'B')
-        update_atten0()
-        self.subscribe('db_ctrl_bandsel', update_atten0)
-        #create checkbox for 10dB att
-        #forms.check_box(
-        #    label='10dB Attenuation',
-        #    ps=self,
-        #    key='db_ctrl_10db',
-        #    sizer=hbox,
-        #    parent=panel,
-        #    proportion=1,
-        #)
-        #hbox.AddSpacer(10)
-        vbox.Add(hbox, 0, wx.EXPAND)
-        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
-        hbox2.AddSpacer(10)
-        forms.static_text(
-            label='ADC Controls',
-            ps=self,
-            key='db_ctrl_diggain',
-            sizer=hbox2,
-            parent=panel,
-            proportion=0,
-            converter=forms.float_converter()
-        )
-        hbox2.AddSpacer(20)
-        #create checkbox for ADC digital gain
-        forms.slider(
-            #label='ADC Digital Gain',
-            ps=self,
-            minimum=0,
-            maximum=6,
-            step_size=0.5,
-            key='db_ctrl_diggain',
-            sizer=hbox2,
-            parent=panel,
-            proportion=2,
-        )
-        hbox2.AddSpacer(10)
-        #create checkbox for 3.5dB ADC gain
-        forms.check_box(
-            label='3.5dB ADC Gain',
-            ps=self,
-            key='db_ctrl_adcgain',
-            sizer=hbox2,
-            parent=panel,
-            proportion=1,
-        )
-        hbox2.AddSpacer(10)
-        #create checkbox for DC Offset Correction in ADC
-        forms.check_box(
-            label='DC Offset Correction',
-            ps=self,
-            key='db_ctrl_dcoffset',
-            sizer=hbox2,
-            parent=panel,
-            proportion=2,
-        )
-        hbox2.AddSpacer(10)
-        vbox.Add(hbox2, 0, wx.EXPAND)
-        hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.AddSpacer(10)
-        #create radio buttons for band sel
-        forms.radio_buttons(
-            label='Band Select',
-            ps=self,
-            key='db_ctrl_bandsel',
-            choices=['A', 'B', 'C', 'D'],
-            labels=['A', 'B', 'C', 'D'],
-            sizer=hbox,
-            parent=panel,
-            proportion=0,
-        )
-        hbox.AddSpacer(10)
-        forms.radio_buttons(
-            label='RF Input',
-            ps=self,
-            key='db_ctrl_type',
-            choices=['rf', 'cal'],
-            labels=['Main RF', 'Calibrator'],
-            sizer=hbox,
-            parent=panel,
-            proportion=0,
-        )
-        hbox.AddSpacer(10)
-        #create radio buttons for band sel
-        types = sorted(
-            filter(lambda x: x.startswith('VRT_TEST_SIG_'), dir(vrt)),
-            lambda x, y: cmp(getattr(vrt, x), getattr(vrt, y)),
-        )
-        forms.drop_down(
-            label='Test Signal',
-            ps=self,
-            key='db_test_signal',
-            choices=map(lambda a: getattr(vrt, a), types),
-            labels=types,
-            sizer=hbox,
-            parent=panel,
-            proportion=0,
-        )
-        hbox.AddSpacer(10)
-        #create radio buttons for type
-        forms.drop_down(
-            label='Beamformer',
-            ps=self,
-            key='sys_beaming',
-            choices=[[16.7e6, 0, 0, 0], [0, 16.7e6, 0, 0], [0, 0, 16.7e6, 0], [0, 0, 0, 16.7e6], [4.19e6]*4],
-            labels=['Ant0', 'Ant1', 'Ant2', 'Ant3', 'Equal Gain'],
-            sizer=hbox,
-            parent=panel,
-            proportion=0,
-        )
-        hbox.AddSpacer(10)
-        vbox.Add(hbox, 0, wx.EXPAND)
-            
-    def set_freq(self, target_freq):
-        """
-        Set the center frequency we're interested in.
-
-        @param target_freq: frequency in Hz
-        @rypte: bool
-
-        Tuning is a two step process.  First we ask the front-end to
-        tune as close to the desired frequency as it can.  Then we use
-        the result of that operation and our target_frequency to
-        determine the value for the digital down converter.
-        """
-        return True
-    
-        r = self.u.set_center_freq(target_freq)
-        
-        if r:
-            self.myform['freq'].set_value(target_freq)     # update displayed value
-            if self.show_debug_info:
-                self.myform['baseband'].set_value(r.baseband_freq)
-                self.myform['ddc'].set_value(r.dxc_freq)
-           if not self.options.oscilloscope:
-               self.scope.win.set_baseband_freq(target_freq)
-           return True
-
-        return False
-
-    def set_gain(self, gain):
-        return True
-    
-       if self.myform.has_key('gain'):
-           self.myform['gain'].set_value(gain)     # update displayed value
-        self.u.set_gain(gain)
-
-    def set_decim(self, decim):
-        return True
-    
-        ok = self.u.set_decim(decim)
-        if not ok:
-            print "set_decim failed"
-        #input_rate = self.u.adc_rate() / self.u.decim()
-        input_rate = 120e6/4
-        self.scope.set_sample_rate(input_rate)
-        if self.show_debug_info:  # update displayed values
-            self.myform['decim'].set_value(self.u.decim())
-            self.myform['fs@gbe'].set_value(input_rate)
-        return ok
-
-    def _setup_events(self):
-       if not self.options.waterfall and not self.options.oscilloscope:
-           self.scope.win.Bind(wx.EVT_LEFT_DCLICK, self.evt_left_dclick)
-           
-    def evt_left_dclick(self, event):
-       (ux, uy) = self.scope.win.GetXY(event)
-       if event.CmdDown():
-           # Re-center on maximum power
-           points = self.scope.win._points
-           if self.scope.win.peak_hold:
-               if self.scope.win.peak_vals is not None:
-                   ind = numpy.argmax(self.scope.win.peak_vals)
-               else:
-                   ind = int(points.shape()[0]/2)
-           else:
-               ind = numpy.argmax(points[:,1])
-            (freq, pwr) = points[ind]
-           target_freq = freq/self.scope.win._scale_factor
-           print ind, freq, pwr
-            self.set_freq(target_freq)            
-       else:
-           # Re-center on clicked frequency
-           target_freq = ux/self.scope.win._scale_factor
-           self.set_freq(target_freq)
-           
-       
-def main ():
-    app = stdgui2.stdapp(app_top_block, "QuadRadio FFT", nstatus=1)
-    app.MainLoop()
-
-if __name__ == '__main__':
-    main ()
diff --git a/gr-utils/src/python/usrp2_siggen.py b/gr-utils/src/python/usrp2_siggen.py
deleted file mode 100755 (executable)
index 9ade933..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008,2009 Free Software Foundation, Inc.
-# 
-# This file is part of GNU Radio
-# 
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-# 
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING.  If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-# 
-
-from gnuradio import gr, eng_notation, usrp2
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-import sys
-import math
-
-n2s = eng_notation.num_to_str
-
-waveforms = { gr.GR_SIN_WAVE   : "Complex Sinusoid",
-              gr.GR_CONST_WAVE : "Constant",
-              gr.GR_GAUSSIAN   : "Gaussian Noise",
-              gr.GR_UNIFORM    : "Uniform Noise",
-              "2tone"          : "Two Tone",
-              "sweep"          : "Sweep" }
-
-#
-# GUI-unaware GNU Radio flowgraph.  This may be used either with command
-# line applications or GUI applications.
-#
-class top_block(gr.top_block):
-    def __init__(self, options, args):
-        gr.top_block.__init__(self)
-        self._verbose = options.verbose
-
-        self._interp = 0 
-        self._gain = 0
-        self._freq = None       # Indicates frequency hasn't been successfully set yet
-        self._bb_freq = 0
-        self._ddc_freq = 0
-        self._amplitude = 0
-        self._type = None       # Indicates waveform flowgraph not created yet
-        self._offset = options.offset
-
-        self.set_usrp2(options.interface, options.mac_addr)
-        self.set_interp(options.interp)
-        self.set_gain(options.gain)
-        self.set_freq(options.tx_freq, options.lo_offset)
-        self.set_amplitude(options.amplitude)
-
-        self.set_waveform_freq(options.waveform_freq)
-        self.set_waveform2_freq(options.waveform2_freq)
-        self.set_waveform(options.type)
-
-    def set_usrp2(self, interface, mac_addr):
-        self._u = usrp2.sink_32fc(interface, mac_addr)
-        self._dac_rate = self._u.dac_rate()
-        if self._verbose:
-            print "Network interface:", interface
-            print "Network address:", self._u.mac_addr()
-            print "Daughterboard ID:", hex(self._u.daughterboard_id())
-
-    def set_interp(self, interp):
-        if interp < 4 or interp > 512: # FIXME get from flowgraph
-            if self._verbose: print "Interpolation rate out of range:", interp
-            return False
-
-        if not self._u.set_interp(interp):
-            raise RuntimeError("Failed to set interpolation rate %i" % (interp,))
-
-        self._interp = interp
-        self._eth_rate = self._dac_rate/self._interp
-        if self._verbose:
-            print "USRP2 interpolation rate:", self._interp
-            print "USRP2 IF bandwidth: %sHz" % (n2s(self._eth_rate),)
-
-        if (self._type == gr.GR_SIN_WAVE or 
-            self._type == gr.GR_CONST_WAVE):
-            self._src.set_sampling_freq(self._eth_rate)
-        elif self._type == "2tone":
-            self._src1.set_sampling_freq(self._eth_rate)
-            self._src1.set_sampling_freq(self._eth_rate)
-        elif self._type == "sweep":
-            self._src1.set_sampling_freq(self._eth_rate)
-            self._src1.set_sampling_freq(self._waveform_freq*2*math.pi/self._eth_rate)
-        else:
-            return True # Waveform not yet set
-        
-        if self._verbose: print "Set interpolation rate to:", interp
-        return True
-
-    def set_gain(self, gain):
-        if gain is None:
-            g = self._u.gain_range()
-            gain = float(g[0]+g[1])/2
-            if self._verbose:
-                print "Using auto-calculated mid-point TX gain"
-        self._u.set_gain(gain)
-        self._gain = gain
-        if self._verbose:
-            print "Set TX gain to:", self._gain
-
-    def set_freq(self, target_freq, lo_offset=None):
-        if lo_offset is not None:
-            self._lo_offset = lo_offset
-            self._u.set_lo_offset(self._lo_offset)
-            if self._verbose:
-                print "Set LO offset frequency to: %sHz" % (n2s(lo_offset),)
-
-        if target_freq is None:
-            f = self._u.freq_range()
-            target_freq = float(f[0]+f[1])/2.0
-            if self._verbose:
-                print "Using auto-calculated mid-point frequency"
-
-        tr = self._u.set_center_freq(target_freq)
-        fs = "%sHz" % (n2s(target_freq),)
-        if tr is not None:
-            self._freq = target_freq
-
-        else:
-            return True # Waveform not yet set
-        
-        if self._verbose: print "Set amplitude to:", amplitude
-        return True
-
-    def set_gain(self, gain):
-        if gain is None:
-            g = self._u.gain_range()
-            gain = float(g[0]+g[1])/2
-            if self._verbose:
-                print "Using auto-calculated mid-point TX gain"
-        self._u.set_gain(gain)
-        self._gain = gain
-        if self._verbose:
-            print "Set TX gain to:", self._gain
-
-    def set_freq(self, target_freq, lo_offset=None):
-        if lo_offset is not None:
-            self._lo_offset = lo_offset
-            self._u.set_lo_offset(self._lo_offset)
-            if self._verbose:
-                print "Set LO offset frequency to: %sHz" % (n2s(lo_offset),)
-
-        if target_freq is None:
-            f = self._u.freq_range()
-            target_freq = float(f[0]+f[1])/2.0
-            if self._verbose:
-                print "Using auto-calculated mid-point frequency"
-
-        tr = self._u.set_center_freq(target_freq)
-        fs = "%sHz" % (n2s(target_freq),)
-        if tr is not None:
-            self._freq = target_freq
-            self._ddc_freq = tr.dxc_freq
-            self._bb_freq = tr.baseband_freq
-            if self._verbose:
-                print "Set center frequency to", fs
-                print "Tx baseband frequency: %sHz" % (n2s(tr.baseband_freq),)
-                print "Tx DDC frequency: %sHz" % (n2s(tr.dxc_freq),)
-                print "Tx residual frequency: %sHz" % (n2s(tr.residual_freq),)
-                
-        return tr
-
-    def set_waveform_freq(self, freq):
-        self._waveform_freq = freq
-        if self._type == gr.GR_SIN_WAVE:
-            self._src.set_frequency(freq)
-        elif self._type == "2tone" or self._type == "sweep":
-            self._src1.set_frequency(freq)
-        return True
-
-    def set_waveform2_freq(self, freq):
-        self._waveform2_freq = freq
-        if self._type == "2tone":
-            self._src2.set_frequency(freq)
-        elif self._type == "sweep":
-            self._src1.set_frequency(freq)
-        return True
-
-    def set_waveform(self, type):
-        self.lock()
-        self.disconnect_all()
-
-        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
-            self._src = gr.sig_source_c(self._eth_rate,      # Sample rate
-                                        type,                # Waveform type
-                                        self._waveform_freq, # Waveform frequency
-                                        self._amplitude,     # Waveform amplitude
-                                        self._offset)        # Waveform offset
-        elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
-            self._src = gr.noise_source_c(type, self._amplitude)
-        elif type == "2tone":
-            self._src1 = gr.sig_source_c(self._eth_rate,
-                                         gr.GR_SIN_WAVE,
-                                         self._waveform_freq,
-                                         self._amplitude/2.0,
-                                         0)
-            if(self._waveform2_freq is None):
-                self._waveform2_freq = -self._waveform_freq
-
-            self._src2 = gr.sig_source_c(self._eth_rate,
-                                         gr.GR_SIN_WAVE,
-                                         self._waveform2_freq,
-                                         self._amplitude/2.0,
-                                         0)
-            self._src = gr.add_cc()
-            self.connect(self._src1,(self._src,0))
-            self.connect(self._src2,(self._src,1))
-        elif type == "sweep":
-            # rf freq is center frequency
-            # waveform_freq is total swept width
-            # waveform2_freq is sweep rate
-            # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
-            if self._waveform2_freq is None:
-                self._waveform2_freq = 0.1
-
-            self._src1 = gr.sig_source_f(self._eth_rate,
-                                         gr.GR_TRI_WAVE,
-                                         self._waveform2_freq,
-                                         1.0,
-                                         -0.5)
-            self._src2 = gr.frequency_modulator_fc(self._waveform_freq*2*math.pi/self._eth_rate)
-            self._src = gr.multiply_const_cc(self._amplitude)
-            self.connect(self._src1,self._src2,self._src)
-        else:
-            raise RuntimeError("Unknown waveform type")
-
-        self.connect(self._src, self._u)
-        self._type = type
-        self.unlock()
-
-        if self._verbose:
-            print "Set baseband modulation to:", waveforms[self._type]
-            if type == gr.GR_SIN_WAVE:
-                print "Modulation frequency: %sHz" % (n2s(self._waveform_freq),)
-                print "Initial phase:", self._offset
-            elif type == "2tone":
-                print "Tone 1: %sHz" % (n2s(self._waveform_freq),)
-                print "Tone 2: %sHz" % (n2s(self._waveform2_freq),)
-            elif type == "sweep":
-                print "Sweeping across %sHz to %sHz" % (n2s(-self._waveform_freq/2.0),n2s(self._waveform_freq/2.0))
-                print "Sweep rate: %sHz" % (n2s(self._waveform2_freq),)
-            print "TX amplitude:", self._amplitude
-
-
-    def set_amplitude(self, amplitude):
-        if amplitude < 0.0 or amplitude > 1.0:
-            if self._verbose: print "Amplitude out of range:", amplitude
-            return False
-
-        self._amplitude = amplitude
-
-        if (self._type == gr.GR_SIN_WAVE or 
-            self._type == gr.GR_CONST_WAVE or
-            self._type == gr.GR_GAUSSIAN or
-            self._type == gr.GR_UNIFORM):
-            self._src.set_amplitude(amplitude)
-        elif self._type == "2tone":
-            self._src1.set_amplitude(amplitude/2.0)
-            self._src2.set_amplitude(amplitude/2.0)
-        elif self._type == "sweep":
-            self._src.set_k(amplitude)
-        else:
-            return True # Waveform not yet set
-        
-        if self._verbose: print "Set amplitude to:", amplitude
-        return True
-
-
-    # Property getters
-
-    def mac_addr(self):
-        return self._u.mac_addr()
-
-    def interface_name(self):
-        return self._u.interface_name()
-
-    def daughterboard_id(self):
-        return self._u.daughterboard_id()
-
-    def interp_rate(self):
-        return self._interp
-
-    def eth_rate(self):
-        return self._eth_rate
-
-    def freq(self):
-        return self._freq
-
-    def freq_range(self):
-        return self._u.freq_range()
-
-    def ddc_freq(self):
-        return self._ddc_freq
-
-    def baseband_freq(self):
-        return self._bb_freq
-
-    def amplitude(self):
-        return self._amplitude
-
-    def waveform_type(self):
-        return self._type
-
-    def waveform_freq(self):
-        return self._waveform_freq
-
-    def waveform2_freq(self):
-        if self._waveform2_freq is None:
-            return -self._waveform_freq
-        else:
-            return self._waveform2_freq
-
-def get_options():
-    usage="%prog: [options]"
-
-    parser = OptionParser(option_class=eng_option, usage=usage)
-
-    parser.add_option("-e", "--interface", type="string", default="eth0",
-                      help="Use specified Ethernet interface [default=%default]")
-    parser.add_option("-m", "--mac-addr", type="string", default="",
-                      help="Use USRP2 at specified MAC address [default=None]")  
-    parser.add_option("-i", "--interp", type="int", default=16, metavar="INTERP",
-                      help="Set FPGA interpolation rate of INTERP [default=%default]")
-    parser.add_option("-f", "--tx-freq", type="eng_float", default=None,
-                      help="Set carrier frequency to FREQ [default=mid-point]", metavar="FREQ")
-    parser.add_option("--lo-offset", type="eng_float", default=None,
-                      help="set daughterboard LO offset to OFFSET [default=hw default]")
-    parser.add_option("-g", "--gain", type="eng_float", default=None,
-                      help="Set TX gain to GAIN [default=mid-point]")
-    parser.add_option("-w", "--waveform-freq", type="eng_float", default=0,
-                      help="Set baseband waveform frequency to FREQ [default=%default]")
-    parser.add_option("-x", "--waveform2-freq", type="eng_float", default=None,
-                      help="Set 2nd waveform frequency to FREQ [default=%default]")
-    parser.add_option("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
-                      help="Generate a carrier modulated by a complex sine wave", default=gr.GR_SIN_WAVE)
-    parser.add_option("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, 
-                      help="Generate a constant carrier")
-    parser.add_option("--offset", type="eng_float", default=0,
-                      help="Set waveform phase offset to OFFSET [default=%default]")
-    parser.add_option("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
-                      help="Generate Gaussian random output")
-    parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
-                      help="Generate Uniform random output")
-    parser.add_option("--2tone", dest="type", action="store_const", const="2tone",
-                      help="Generate Two Tone signal for IMD testing")
-    parser.add_option("--sweep", dest="type", action="store_const", const="sweep",
-                      help="Generate a swept sine wave")
-    parser.add_option("-a", "--amplitude", type="eng_float", default=0.1,
-                      help="Set output amplitude to AMPL (0.0-1.0) [default=%default]", metavar="AMPL")
-    parser.add_option("-v", "--verbose", action="store_true", default=False,
-                      help="Use verbose console output [default=%default]")
-
-    (options, args) = parser.parse_args()
-
-    return (options, args)
-
-# If this script is executed, the following runs. If it is imported, the below does not run.
-if __name__ == "__main__":
-    if gr.enable_realtime_scheduling() != gr.RT_OK:
-        print "Note: failed to enable realtime scheduling, continuing"
-    
-    # Grab command line options and create top block
-    try:
-        (options, args) = get_options()
-        tb = top_block(options, args)
-
-    except RuntimeError, e:
-        print e
-        sys.exit(1)
-
-    # Run it
-    try:
-        tb.run()
-
-    except KeyboardInterrupt:
-        pass
diff --git a/gr-utils/src/python/usrp2_siggen_gui.py b/gr-utils/src/python/usrp2_siggen_gui.py
deleted file mode 100755 (executable)
index 89bc6e5..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009 Free Software Foundation, Inc.
-# 
-# This file is part of GNU Radio
-# 
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-# 
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING.  If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-# 
-
-import wx
-from gnuradio.wxgui import form, slider, gui
-import usrp2_siggen
-import sys, math
-
-class app_gui(object):
-    def __init__(self, frame, panel, vbox, top_block, options, args):
-        self.frame = frame      # Use for top-level application window frame
-        self.panel = panel      # Use as parent class for created windows
-        self.vbox = vbox        # Use as sizer for created windows
-        self.tb = top_block     # GUI-unaware flowgraph class
-        self.options = options  # Supplied command-line options
-        self.args = args        # Supplied command-line arguments
-
-        freq_range = self.tb.freq_range()
-        self.min_freq = freq_range[0]
-        self.max_freq = freq_range[1]
-        self.freq_step = (self.max_freq-self.min_freq)/100.0
-        self._types = dict([v, k] for k, v in usrp2_siggen.waveforms.items())
-
-        self.build_gui()
-
-        # TODO: turn these into listeners
-        self.myform['ifc'].set_value(self.tb.interface_name())
-        self.myform['mac'].set_value(self.tb.mac_addr())
-        dbid = self.tb.daughterboard_id()
-        self.myform['dbid'].set_value("%04x" % (dbid,))
-
-        w = usrp2_siggen.waveforms[self.tb.waveform_type()]
-        self.myform['type'].set_value(w)
-        self.myform['w1freq'].set_value(self.tb.waveform_freq())
-        self.myform['w2freq'].set_value(self.tb.waveform2_freq())
-
-        freq = self.tb.freq()
-        if freq is None:
-            self.evt_set_status_msg("Failed to set initial frequency")
-        else:
-            self.myform['freq'].set_value(freq)
-            self.myform['freq_slider'].set_value(self.tb.freq())
-
-        amp = self.tb.amplitude()
-        if (amp > 0.0):
-            db = 20*math.log10(amp)
-        else:
-            db = -100.0
-        self.myform['amp'].set_value(amp)
-        self.myform['amp_slider'].set_value(db)
-        self.myform['eth'].set_value(self.tb.eth_rate())
-        self.myform['gbe'].set_value(self.tb.eth_rate()*32)
-        self.myform['interp'].set_value(self.tb.interp_rate())
-        self.myform['DDC'].set_value(self.tb.ddc_freq())
-        self.myform['analog'].set_value(self.tb.baseband_freq())
-
-    # Event response handlers
-    def evt_set_status_msg(self, msg):
-        self.frame.SetStatusText(msg, 0)
-
-    def evt_set_freq1(self, kv):
-        return self.tb.set_waveform_freq(kv['w1freq'])
-
-    def evt_set_freq2(self, kv):
-        return self.tb.set_waveform2_freq(kv['w2freq'])
-
-    def evt_set_freq(self, kv):
-        if type(kv) == type(0.0):              # Set from slider
-            tr = self.tb.set_freq(kv)
-            if tr is not None:
-                self.myform['freq'].set_value(kv)
-        else:                                  # Set from edit box
-            f = kv['freq']
-            tr = self.tb.set_freq(f)
-            if tr is not None:
-                self.myform['freq_slider'].set_value(f)
-
-        if tr is not None:
-            self.myform['DDC'].set_value(tr.dxc_freq)
-            self.myform['analog'].set_value(tr.baseband_freq)
-
-        return (tr is not None)
-
-    def evt_set_amplitude(self, kv):
-        if type(kv) == type(0.0):              # Set from slider
-            amp = math.pow(10, kv/20.0)
-            self.myform['amp'].set_value(amp)
-            return self.tb.set_amplitude(amp)
-        else:                                  # Set from edit box
-            amp = kv['amp']
-            if amp < 0.0 or amp > 1.0:
-                return False
-            if amp == 0.0:
-                db = -100.0
-            else:
-                db = 20*math.log10(amp)
-            self.myform['amp_slider'].set_value(db)
-            return self.tb.set_amplitude(amp)
-
-    def evt_set_interp(self):
-        interp = self.myform['interp'].get_value()
-        if self.tb.set_interp(interp):
-            eth_rate = self.tb.eth_rate()
-            self.myform['eth'].set_value(eth_rate)
-            self.myform['gbe'].set_value(eth_rate*32)
-            return True
-        return False
-
-    def evt_set_waveform_type(self, type):
-        # TODO: update frequency labels
-        return self.tb.set_waveform(self._types[type])
-
-    # GUI construction
-    def build_gui(self):
-        self.myform = myform = form.form()
-
-        # Baseband controls
-        bb_sbox = wx.StaticBox(parent=self.panel, label="Baseband Modulation")
-        bb_vbox = wx.StaticBoxSizer(bb_sbox, wx.VERTICAL) # Holds all baseband controls as unit
-
-        # First row of baseband controls (modulation type)
-        mod_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        mod_hbox.Add((10,0), 0, 0)
-        myform['type'] = form.radiobox_field(
-            parent=self.panel, label="Type", sizer=mod_hbox, value=None,
-            callback=self.evt_set_waveform_type, weight=1, major_dimension=0,
-            choices=usrp2_siggen.waveforms.values() )
-        bb_vbox.Add((0,10), 0, 0)
-        bb_vbox.Add(mod_hbox, 0, wx.EXPAND)
-
-        # Second row of baseband controls (frequencies)
-        bbf_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        bbf_hbox.Add((10,0), 0, 0)
-        myform['w1freq'] = form.float_field(
-            parent=self.panel, sizer=bbf_hbox, label="Frequency 1 (Hz)", weight=1,
-            callback=myform.check_input_and_call(self.evt_set_freq1, self.evt_set_status_msg) )
-        bbf_hbox.Add((10,0), 0, 0)
-        myform['w2freq'] = form.float_field(
-            parent=self.panel, sizer=bbf_hbox, label="Frequency 2 (Hz)", weight=1,
-            callback=myform.check_input_and_call(self.evt_set_freq2, self.evt_set_status_msg) )
-        bbf_hbox.Add((10,0), 0, 0)
-        
-        bb_vbox.Add((0,10), 0, 0)
-        bb_vbox.Add(bbf_hbox, 0, wx.EXPAND)
-
-        # Add baseband controls to top window sizer
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(bb_vbox, 0, wx.EXPAND)
-
-        # Frequency controls
-        fc_sbox = wx.StaticBox(parent=self.panel, label="Center Frequency")
-        fc_vbox = wx.StaticBoxSizer(fc_sbox, wx.VERTICAL) # Holds all frequency controls as unit
-
-        # First row of frequency controls (center frequency)
-        freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        freq_hbox.Add((10,0), 0, 0)
-        myform['freq'] = form.float_field(
-            parent=self.panel, sizer=freq_hbox, label=None, weight=1,
-            callback=myform.check_input_and_call(self.evt_set_freq, self.evt_set_status_msg) )
-        freq_hbox.Add((10,0), 0, 0)
-        myform['freq_slider'] = form.quantized_slider_field(
-            parent=self.panel, sizer=freq_hbox, label="Min-Max", weight=4,
-            range = (self.min_freq, self.max_freq, self.freq_step),
-            callback=self.evt_set_freq)
-        freq_hbox.Add((10,0), 0, 0)
-
-        fc_vbox.Add((10,0), 0, 0)
-        fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
-
-        # Second row of frequency controls (results)
-        tr_hbox = wx.BoxSizer(wx.HORIZONTAL)
-        tr_hbox.Add((10,0), 0, 0)
-        myform['analog'] = form.static_float_field(
-            parent=self.panel, sizer=tr_hbox, label="Daughterboard: (Hz)", weight=1)
-        tr_hbox.Add((10,0), 0, 0)
-        myform['DDC'] = form.static_float_field(
-            parent=self.panel, sizer=tr_hbox, label="USRP2 DDC (Hz)", weight=1)
-        tr_hbox.Add((10,0), 0, 0)
-        fc_vbox.Add(tr_hbox, 0, wx.EXPAND)
-
-        # Add frequency controls to top window sizer
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(fc_vbox, 0, wx.EXPAND)
-
-        # Amplitude row
-        amp_sbox = wx.StaticBox(parent=self.panel, label="Amplitude")
-        amp_hbox = wx.StaticBoxSizer(amp_sbox, wx.HORIZONTAL)
-        amp_hbox.Add((10,0), 0, 0)
-        myform['amp'] = form.float_field(
-            parent=self.panel, sizer=amp_hbox, label="Linear\n(0.0-1.0)", weight=1,
-            callback=myform.check_input_and_call(self.evt_set_amplitude, self.evt_set_status_msg) )
-        amp_hbox.Add((10,0), 0, 0)
-        myform['amp_slider'] = form.quantized_slider_field(
-            parent=self.panel, sizer=amp_hbox, label="dB Full Scale\n(-100-0)", weight=4,
-            range=(-100.0, 0.0, 1), callback=self.evt_set_amplitude)
-        amp_hbox.Add((10,0), 0, 0)
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(amp_hbox, 0, wx.EXPAND)
-
-        # Sample rate row
-        sam_sbox = wx.StaticBox(parent=self.panel, label="Sample Rate")
-        sam_hbox = wx.StaticBoxSizer(sam_sbox, wx.HORIZONTAL)
-        sam_hbox.Add((10,0), 0, 0)
-        myform['interp'] = form.int_field(
-            parent=self.panel, sizer=sam_hbox, label="Interpolation", weight=1,
-            callback=self.evt_set_interp)
-        sam_hbox.Add((10,0), 0, 0)
-        myform['eth'] = form.static_float_field(
-            parent=self.panel, sizer=sam_hbox, label="Sample Rate (sps)", weight=1)
-        sam_hbox.Add((10,0), 0, 0)
-        myform['gbe'] = form.static_float_field(
-            parent=self.panel, sizer=sam_hbox, label="GbE Rate (bits/sec)", weight=1)
-        sam_hbox.Add((10,0), 0, 0)
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(sam_hbox, 0, wx.EXPAND)
-
-        # USRP2 row
-        u2_sbox = wx.StaticBox(parent=self.panel, label="USRP2 Hardware")
-        u2_hbox = wx.StaticBoxSizer(u2_sbox, wx.HORIZONTAL)
-        u2_hbox.Add((10,0), 0, 0)
-        myform['ifc'] = form.static_text_field(parent=self.panel, sizer=u2_hbox, 
-                                               label="Interface", weight=2)
-        u2_hbox.Add((10,0), 0, 0)
-        myform['mac'] = form.static_text_field(parent=self.panel, sizer=u2_hbox, 
-                                               label="MAC Address", weight=2)
-        u2_hbox.Add((10,0), 0, 0)
-        myform['dbid'] = form.static_text_field(parent=self.panel, sizer=u2_hbox, 
-                                                label="Daughterboard ID", weight=1)
-        self.vbox.Add((0,10), 0, 0)
-        self.vbox.Add(u2_hbox, 0, wx.EXPAND)
-        self.vbox.Add((0,20), 0, 0)
-
-if __name__ == "__main__":
-    try:
-        # Get command line parameters
-        (options, args) = usrp2_siggen.get_options()
-
-        # Create the top block using these
-        tb = usrp2_siggen.top_block(options, args)
-
-        # Create the GUI application
-        app = gui.app(top_block=tb,                    # Constructed top block
-                      gui=app_gui,                     # User interface class
-                      options=options,                 # Command line options
-                      args=args,                       # Command line args
-                      title="USRP2 Signal Generator",  # Top window title
-                      nstatus=1,                       # Number of status lines
-                      start=True,                      # Whether to start flowgraph
-                      realtime=True)                   # Whether to set realtime priority
-
-        # And run it
-        app.MainLoop()
-
-    except RuntimeError, e:
-        print e
-        sys.exit(1)
index 8ae2fbfbfd93ade4518cff28311ab3ba946108d6..8ee8cfd2ad4696d9fd1ba586dc8d62e8c96da9c3 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2004,2005,2007,2008 Free Software Foundation, Inc.
+# Copyright 2008,2009 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, gru
-from gnuradio import usrp
+DESC_KEY = 'desc'
+SAMP_RATE_KEY = 'samp_rate'
+LINK_RATE_KEY = 'link_rate'
+DAC_RATE_KEY = 'dac_rate'
+INTERP_KEY = 'interp'
+GAIN_KEY = 'gain'
+TX_FREQ_KEY = 'tx_freq'
+DDC_FREQ_KEY = 'ddc_freq'
+BB_FREQ_KEY = 'bb_freq'
+AMPLITUDE_KEY = 'amplitude'
+AMPL_RANGE_KEY = 'ampl_range'
+WAVEFORM_FREQ_KEY = 'waveform_freq'
+WAVEFORM_OFFSET_KEY = 'waveform_offset'
+WAVEFORM2_FREQ_KEY = 'waveform2_freq'
+FREQ_RANGE_KEY = 'freq_range'
+GAIN_RANGE_KEY = 'gain_range'
+TYPE_KEY = 'type'
+
+def setter(ps, key, val): ps[key] = val
+
+from gnuradio import gr, eng_notation
+from gnuradio.gr.pubsub import pubsub
 from gnuradio.eng_option import eng_option
-from gnuradio import eng_notation
+from gnuradio import usrp_options
 from optparse import OptionParser
 import sys
+import math
 
+n2s = eng_notation.num_to_str
 
-class my_top_block(gr.top_block):
-    def __init__ (self, nsamples):
+waveforms = { gr.GR_SIN_WAVE   : "Complex Sinusoid",
+              gr.GR_CONST_WAVE : "Constant",
+              gr.GR_GAUSSIAN   : "Gaussian Noise",
+              gr.GR_UNIFORM    : "Uniform Noise",
+              "2tone"          : "Two Tone",
+              "sweep"          : "Sweep" }
+
+#
+# GUI-unaware GNU Radio flowgraph.  This may be used either with command
+# line applications or GUI applications.
+#
+class top_block(gr.top_block, pubsub):
+    def __init__(self, options, args):
         gr.top_block.__init__(self)
+        pubsub.__init__(self)
+        self._verbose = options.verbose
+        #initialize values from options
+        self._setup_usrpx(options)
+        self.subscribe(INTERP_KEY, lambda i: setter(self, SAMP_RATE_KEY, self[DAC_RATE_KEY]/i))
+        self.subscribe(SAMP_RATE_KEY, lambda e: setter(self, LINK_RATE_KEY, e*32))
+        self[INTERP_KEY] = options.interp or 16
+        self[TX_FREQ_KEY] = options.tx_freq
+        self[AMPLITUDE_KEY] = options.amplitude
+        self[WAVEFORM_FREQ_KEY] = options.waveform_freq
+        self[WAVEFORM_OFFSET_KEY] = options.offset
+        self[WAVEFORM2_FREQ_KEY] = options.waveform2_freq
+        self[BB_FREQ_KEY] = 0
+        self[DDC_FREQ_KEY] = 0
+        #subscribe set methods
+        self.subscribe(INTERP_KEY, self.set_interp)
+        self.subscribe(GAIN_KEY, self.set_gain)
+        self.subscribe(TX_FREQ_KEY, self.set_freq)
+        self.subscribe(AMPLITUDE_KEY, self.set_amplitude)
+        self.subscribe(WAVEFORM_FREQ_KEY, self.set_waveform_freq)
+        self.subscribe(WAVEFORM2_FREQ_KEY, self.set_waveform2_freq)
+        self.subscribe(TYPE_KEY, self.set_waveform)
+        #force update on pubsub keys
+        for key in (INTERP_KEY, GAIN_KEY, TX_FREQ_KEY,
+            AMPLITUDE_KEY, WAVEFORM_FREQ_KEY, WAVEFORM_OFFSET_KEY, WAVEFORM2_FREQ_KEY):
+            self[key] = self[key]
+        self[TYPE_KEY] = options.type #set type last
+
+    def _setup_usrpx(self, options):
+        self._u = usrp_options.create_usrp_sink(options)
+        self.publish(DESC_KEY, lambda: str(self._u))
+        self.publish(DAC_RATE_KEY, self._u.dac_rate)
+        self.publish(FREQ_RANGE_KEY, self._u.freq_range)
+        self.publish(GAIN_RANGE_KEY, self._u.gain_range)
+        self.publish(GAIN_KEY, self._u.gain)
+        if self._verbose: print str(self._u)
+
+    def _set_tx_amplitude(self, ampl):
+        """
+        Sets the transmit amplitude sent to the USRP
+        @param ampl the amplitude or None for automatic
+        """
+        ampl_range = self[AMPL_RANGE_KEY]
+        if ampl is None: ampl = (ampl_range[1] - ampl_range[0])*0.15 + ampl_range[0]
+        self[AMPLITUDE_KEY] = max(ampl_range[0], min(ampl, ampl_range[1]))
+
+    def set_interp(self, interp):
+        if not self._u.set_interp(interp):
+            raise RuntimeError("Failed to set interpolation rate %i" % (interp,))
+
+        if self._verbose:
+            print "USRP interpolation rate:", interp
+            print "USRP IF bandwidth: %sHz" % (n2s(self[SAMP_RATE_KEY]),)
+
+        if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE):
+            self._src.set_sampling_freq(self[SAMP_RATE_KEY])
+        elif self[TYPE_KEY] == "2tone":
+            self._src1.set_sampling_freq(self[SAMP_RATE_KEY])
+            self._src2.set_sampling_freq(self[SAMP_RATE_KEY])
+        elif self[TYPE_KEY] == "sweep":
+            self._src1.set_sampling_freq(self[SAMP_RATE_KEY])
+            self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
+        else:
+            return True # Waveform not yet set
         
-        # controllable values
-        self.interp = 64
-        self.waveform_type = gr.GR_SIN_WAVE
-        self.waveform_ampl = 16000
-        self.waveform_freq = 100.12345e3
-        self.waveform_offset = 0
-        self.nsamples = nsamples
-        self._instantiate_blocks ()
-        self.set_waveform_type (self.waveform_type)
-
-    def usb_freq (self):
-        return self.u.dac_freq() / self.interp
-
-    def usb_throughput (self):
-        return self.usb_freq () * 4
-        
-    def set_waveform_type (self, type):
-        '''
-        valid waveform types are: gr.GR_SIN_WAVE, gr.GR_CONST_WAVE,
-        gr.GR_UNIFORM and gr.GR_GAUSSIAN
-        '''
-        self._configure_graph (type)
-        self.waveform_type = type
-
-    def set_waveform_ampl (self, ampl):
-        self.waveform_ampl = ampl
-        self.siggen.set_amplitude (ampl)
-        self.noisegen.set_amplitude (ampl)
-
-    def set_waveform_freq (self, freq):
-        self.waveform_freq = freq
-        self.siggen.set_frequency (freq)
-        
-    def set_waveform_offset (self, offset):
-        self.waveform_offset = offset
-        self.siggen.set_offset (offset)
-
-    def set_interpolator (self, interp):
-        self.interp = interp
-        self.siggen.set_sampling_freq (self.usb_freq ())
-        self.u.set_interp_rate (interp)
-
-    def _instantiate_blocks (self):
-        self.src = None
-        self.u = usrp.sink_c (0, self.interp)
-        
-        self.siggen = gr.sig_source_c (self.usb_freq (),
-                                       gr.GR_SIN_WAVE,
-                                       self.waveform_freq,
-                                       self.waveform_ampl,
-                                       self.waveform_offset)
-
-        self.noisegen = gr.noise_source_c (gr.GR_UNIFORM,
-                                           self.waveform_ampl)
-
-        self.head = None
-        if self.nsamples > 0:
-            self.head = gr.head(gr.sizeof_gr_complex, int(self.nsamples))
-
-        # self.file_sink = gr.file_sink (gr.sizeof_gr_complex, "siggen.dat")
-
-    def _configure_graph (self, type):
-        try:
-            self.lock()
-            self.disconnect_all ()
-
-            if self.head:
-                self.connect(self.head, self.u)
-                tail = self.head
-            else:
-                tail = self.u
-                
-            if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
-                self.connect (self.siggen, tail)
-                # self.connect (self.siggen, self.file_sink)
-                self.siggen.set_waveform (type)
-                self.src = self.siggen
-            elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN:
-                self.connect (self.noisegen, tail)
-                self.noisegen.set_type (type)
-                self.src = self.noisegen
-            else:
-                raise ValueError, type
-        finally:
-            self.unlock()
+        if self._verbose: print "Set interpolation rate to:", interp
+        return True
+
+    def set_gain(self, gain):
+        if gain is None:
+            g = self[GAIN_RANGE_KEY]
+            gain = float(g[0]+g[1])/2
+            if self._verbose:
+                print "Using auto-calculated mid-point TX gain"
+            self[GAIN_KEY] = gain
+            return
+        self._u.set_gain(gain)
+        if self._verbose:
+            print "Set TX gain to:", gain
 
     def set_freq(self, target_freq):
-        """
-        Set the center frequency we're interested in.
 
-        @param target_freq: frequency in Hz
-        @rypte: bool
-
-        Tuning is a two step process.  First we ask the front-end to
-        tune as close to the desired frequency as it can.  Then we use
-        the result of that operation and our target_frequency to
-        determine the value for the digital up converter.
-        """
-        r = self.u.tune(self.subdev.which(), self.subdev, target_freq)
-        if r:
-            #print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq)
-            #print "r.dxc_freq      =", eng_notation.num_to_str(r.dxc_freq)
-            #print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq)
-            #print "r.inverted      =", r.inverted
-            return True
-
-        return False
-
-
-
-def main ():
-    parser = OptionParser (option_class=eng_option)
-    parser.add_option ("-T", "--tx-subdev-spec", type="subdev", default=(0, 0),
-                       help="select USRP Tx side A or B")
-    parser.add_option ("-f", "--rf-freq", type="eng_float", default=None,
-                       help="set RF center frequency to FREQ")
-    parser.add_option ("-i", "--interp", type="int", default=64,
-                       help="set fgpa interpolation rate to INTERP [default=%default]")
-
-    parser.add_option ("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
-                       help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE)
-    parser.add_option ("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, 
-                       help="generate a constant output")
-    parser.add_option ("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
-                       help="generate Gaussian random output")
-    parser.add_option ("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
-                       help="generate Uniform random output")
-
-    parser.add_option ("-w", "--waveform-freq", type="eng_float", default=0,
-                       help="set waveform frequency to FREQ [default=%default]")
-    parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3,
-                       help="set waveform amplitude to AMPLITUDE [default=%default]", metavar="AMPL")
-    parser.add_option ("-g", "--gain", type="eng_float", default=None,
-                       help="set output gain to GAIN [default=%default]")
-    parser.add_option ("-o", "--offset", type="eng_float", default=0,
-                       help="set waveform offset to OFFSET [default=%default]")
-    parser.add_option ("-N", "--nsamples", type="eng_float", default=0,
-                       help="set number of samples to transmit [default=+inf]")
-    (options, args) = parser.parse_args ()
-
-    if len(args) != 0:
-        parser.print_help()
-        raise SystemExit
-
-    if options.rf_freq is None:
-        sys.stderr.write("usrp_siggen: must specify RF center frequency with -f RF_FREQ\n")
-        parser.print_help()
-        raise SystemExit
-
-    tb = my_top_block(options.nsamples)
-    tb.set_interpolator (options.interp)
-    tb.set_waveform_type (options.type)
-    tb.set_waveform_freq (options.waveform_freq)
-    tb.set_waveform_ampl (options.amplitude)
-    tb.set_waveform_offset (options.offset)
-
-    # determine the daughterboard subdevice we're using
-    if options.tx_subdev_spec is None:
-        options.tx_subdev_spec = usrp.pick_tx_subdevice(tb.u)
-
-    m = usrp.determine_tx_mux_value(tb.u, options.tx_subdev_spec)
-    #print "mux = %#04x" % (m,)
-    tb.u.set_mux(m)
-    tb.subdev = usrp.selected_subdev(tb.u, options.tx_subdev_spec)
-    print "Using TX d'board %s" % (tb.subdev.side_and_name(),)
-    
-    if options.gain is None:
-        tb.subdev.set_gain(tb.subdev.gain_range()[1])    # set max Tx gain
-    else:
-        tb.subdev.set_gain(options.gain)    # set max Tx gain
-
-    if not tb.set_freq(options.rf_freq):
-        sys.stderr.write('Failed to set RF frequency\n')
-        raise SystemExit
+        if target_freq is None:
+            f = self[FREQ_RANGE_KEY]
+            target_freq = float(f[0]+f[1])/2.0
+            if self._verbose:
+                print "Using auto-calculated mid-point frequency"
+            self[TX_FREQ_KEY] = target_freq
+            return
+
+        tr = self._u.set_center_freq(target_freq)
+        fs = "%sHz" % (n2s(target_freq),)
+        if tr is not None:
+            self._freq = target_freq
+            self[DDC_FREQ_KEY] = tr.dxc_freq
+            self[BB_FREQ_KEY] = tr.baseband_freq
+            if self._verbose:
+                print "Set center frequency to", fs
+                print "Tx baseband frequency: %sHz" % (n2s(tr.baseband_freq),)
+                print "Tx DDC frequency: %sHz" % (n2s(tr.dxc_freq),)
+                print "Tx residual frequency: %sHz" % (n2s(tr.residual_freq),)
+        elif self._verbose: print "Failed to set freq." 
+        return tr
+
+    def set_waveform_freq(self, freq):
+        if self[TYPE_KEY] == gr.GR_SIN_WAVE:
+            self._src.set_frequency(freq)
+        elif self[TYPE_KEY] == "2tone":
+            self._src1.set_frequency(freq)
+        elif self[TYPE_KEY] == 'sweep':
+            #there is no set sensitivity, redo fg
+            self[TYPE_KEY] = self[TYPE_KEY]
+        return True
+
+    def set_waveform2_freq(self, freq):
+        if freq is None:
+            self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY]
+            return
+        if self[TYPE_KEY] == "2tone":
+            self._src2.set_frequency(freq)
+        elif self[TYPE_KEY] == "sweep":
+            self._src1.set_frequency(freq)
+        return True
+
+    def set_waveform(self, type):
+        self.lock()
+        self.disconnect_all()
+        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
+            self._src = gr.sig_source_c(self[SAMP_RATE_KEY],      # Sample rate
+                                        type,                # Waveform type
+                                        self[WAVEFORM_FREQ_KEY], # Waveform frequency
+                                        self[AMPLITUDE_KEY],     # Waveform amplitude
+                                        self[WAVEFORM_OFFSET_KEY])        # Waveform offset
+        elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
+            self._src = gr.noise_source_c(type, self[AMPLITUDE_KEY])
+        elif type == "2tone":
+            self._src1 = gr.sig_source_c(self[SAMP_RATE_KEY],
+                                         gr.GR_SIN_WAVE,
+                                         self[WAVEFORM_FREQ_KEY],
+                                         self[AMPLITUDE_KEY]/2.0,
+                                         0)
+            if(self[WAVEFORM2_FREQ_KEY] is None):
+                self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY]
+
+            self._src2 = gr.sig_source_c(self[SAMP_RATE_KEY],
+                                         gr.GR_SIN_WAVE,
+                                         self[WAVEFORM2_FREQ_KEY],
+                                         self[AMPLITUDE_KEY]/2.0,
+                                         0)
+            self._src = gr.add_cc()
+            self.connect(self._src1,(self._src,0))
+            self.connect(self._src2,(self._src,1))
+        elif type == "sweep":
+            # rf freq is center frequency
+            # waveform_freq is total swept width
+            # waveform2_freq is sweep rate
+            # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
+            if self[WAVEFORM2_FREQ_KEY] is None:
+                self[WAVEFORM2_FREQ_KEY] = 0.1
+
+            self._src1 = gr.sig_source_f(self[SAMP_RATE_KEY],
+                                         gr.GR_TRI_WAVE,
+                                         self[WAVEFORM2_FREQ_KEY],
+                                         1.0,
+                                         -0.5)
+            self._src2 = gr.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
+            self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY])
+            self.connect(self._src1,self._src2,self._src)
+        else:
+            raise RuntimeError("Unknown waveform type")
+
+        self.connect(self._src, self._u)
+        self.unlock()
+
+        if self._verbose:
+            print "Set baseband modulation to:", waveforms[type]
+            if type == gr.GR_SIN_WAVE:
+                print "Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)
+                print "Initial phase:", self[WAVEFORM_OFFSET_KEY]
+            elif type == "2tone":
+                print "Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)
+                print "Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)
+            elif type == "sweep":
+                print "Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0))
+                print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)
+            print "TX amplitude:", self[AMPLITUDE_KEY]
+
+
+    def set_amplitude(self, amplitude):
+        if amplitude < 0.0 or amplitude > 1.0:
+            if self._verbose: print "Amplitude out of range:", amplitude
+            return False
+
+        if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE, gr.GR_GAUSSIAN, gr.GR_UNIFORM):
+            self._src.set_amplitude(amplitude)
+        elif self[TYPE_KEY] == "2tone":
+            self._src1.set_amplitude(amplitude/2.0)
+            self._src2.set_amplitude(amplitude/2.0)
+        elif self[TYPE_KEY] == "sweep":
+            self._src.set_k(amplitude)
+        else:
+            return True # Waveform not yet set
+        
+        if self._verbose: print "Set amplitude to:", amplitude
+        return True
+
+def get_options():
+    usage="%prog: [options]"
+
+    parser = OptionParser(option_class=eng_option, usage=usage)
+    usrp_options.add_tx_options(parser)
+    parser.add_option("-f", "--tx-freq", type="eng_float", default=None,
+                      help="Set carrier frequency to FREQ [default=mid-point]", metavar="FREQ")
+    parser.add_option("-x", "--waveform-freq", type="eng_float", default=0,
+                      help="Set baseband waveform frequency to FREQ [default=%default]")
+    parser.add_option("-y", "--waveform2-freq", type="eng_float", default=None,
+                      help="Set 2nd waveform frequency to FREQ [default=%default]")
+    parser.add_option("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
+                      help="Generate a carrier modulated by a complex sine wave", default=gr.GR_SIN_WAVE)
+    parser.add_option("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, 
+                      help="Generate a constant carrier")
+    parser.add_option("--offset", type="eng_float", default=0,
+                      help="Set waveform phase offset to OFFSET [default=%default]")
+    parser.add_option("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
+                      help="Generate Gaussian random output")
+    parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
+                      help="Generate Uniform random output")
+    parser.add_option("--2tone", dest="type", action="store_const", const="2tone",
+                      help="Generate Two Tone signal for IMD testing")
+    parser.add_option("--sweep", dest="type", action="store_const", const="sweep",
+                      help="Generate a swept sine wave")
+    parser.add_option("-A", "--amplitude", type="eng_float", default=0.15,
+                      help="Set output amplitude to AMPL (0.0-1.0) [default=%default]", metavar="AMPL")
+    parser.add_option("-v", "--verbose", action="store_true", default=False,
+                      help="Use verbose console output [default=%default]")
+
+    (options, args) = parser.parse_args()
+
+    return (options, args)
+
+# If this script is executed, the following runs. If it is imported, the below does not run.
+if __name__ == "__main__":
+    if gr.enable_realtime_scheduling() != gr.RT_OK:
+        print "Note: failed to enable realtime scheduling, continuing"
     
-    tb.subdev.set_enable(True)                       # enable transmitter
+    # Grab command line options and create top block
+    try:
+        (options, args) = get_options()
+        tb = top_block(options, args)
 
+    except RuntimeError, e:
+        print e
+        sys.exit(1)
+
+    # Run it
     try:
         tb.run()
+
     except KeyboardInterrupt:
         pass
-
-
-if __name__ == '__main__':
-    main ()
diff --git a/gr-utils/src/python/usrp_siggen_gui.py b/gr-utils/src/python/usrp_siggen_gui.py
new file mode 100755 (executable)
index 0000000..40848fb
--- /dev/null
@@ -0,0 +1,310 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import wx
+from gnuradio import gr
+from gnuradio.gr.pubsub import pubsub
+from gnuradio.wxgui import gui, forms
+import usrp_siggen
+import sys, math
+
+class app_gui(pubsub):
+    def __init__(self, frame, panel, vbox, top_block, options, args):
+        pubsub.__init__(self)
+        self.frame = frame      # Use for top-level application window frame
+        self.panel = panel      # Use as parent class for created windows
+        self.vbox = vbox        # Use as sizer for created windows
+        self.tb = top_block     # GUI-unaware flowgraph class
+        self.options = options  # Supplied command-line options
+        self.args = args        # Supplied command-line arguments
+        self.build_gui()
+
+    # Event response handlers
+    def evt_set_status_msg(self, msg):
+        self.frame.SetStatusText(msg, 0)
+
+    # GUI construction
+    def build_gui(self):
+        self.vbox.AddSpacer(5)
+        self.vbox.AddStretchSpacer()
+        ##################################################
+        # Baseband controls
+        ##################################################
+        bb_vbox = forms.static_box_sizer(parent=self.panel, label="Baseband Modulation", orient=wx.VERTICAL, bold=True)
+        self.vbox.Add(bb_vbox, 0, wx.EXPAND)
+        sine_bb_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        sweep_bb_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        tone_bb_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        self.vbox.AddSpacer(10)
+        self.vbox.AddStretchSpacer()
+        #callback to show/hide forms
+        def set_type(type):
+            sine_bb_hbox.ShowItems(type == gr.GR_SIN_WAVE)
+            sweep_bb_hbox.ShowItems(type == 'sweep')
+            tone_bb_hbox.ShowItems(type == '2tone')
+            self.vbox.Layout()
+        self.tb.subscribe(usrp_siggen.TYPE_KEY, set_type)
+        #create sine forms
+        sine_bb_hbox.AddSpacer(10)
+        forms.text_box(
+            parent=self.panel, sizer=sine_bb_hbox,
+            label='Frequency (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        sine_bb_hbox.AddStretchSpacer()
+        #create sweep forms
+        sweep_bb_hbox.AddSpacer(10)
+        forms.text_box(
+            parent=self.panel, sizer=sweep_bb_hbox,
+            label='Sweep Width (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        sweep_bb_hbox.AddStretchSpacer()
+        forms.text_box(
+            parent=self.panel, sizer=sweep_bb_hbox,
+            label='Sweep Rate (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM2_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        sweep_bb_hbox.AddStretchSpacer()
+        #create 2tone forms
+        tone_bb_hbox.AddSpacer(10)
+        forms.text_box(
+            parent=self.panel, sizer=tone_bb_hbox,
+            label='Tone 1 (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        tone_bb_hbox.AddStretchSpacer()
+        forms.text_box(
+            parent=self.panel, sizer=tone_bb_hbox,
+            label='Tone 2 (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.WAVEFORM2_FREQ_KEY,
+            converter=forms.float_converter(),
+        )
+        tone_bb_hbox.AddStretchSpacer()
+        forms.radio_buttons(
+            parent=self.panel, sizer=bb_vbox,
+            choices=usrp_siggen.waveforms.keys(),
+            labels=usrp_siggen.waveforms.values(),
+            ps=self.tb,
+            key=usrp_siggen.TYPE_KEY,
+            style=wx.NO_BORDER | wx.RA_HORIZONTAL,
+        )
+        bb_vbox.AddSpacer(10)
+        bb_vbox.Add(sine_bb_hbox, 0, wx.EXPAND)
+        bb_vbox.Add(sweep_bb_hbox, 0, wx.EXPAND)
+        bb_vbox.Add(tone_bb_hbox, 0, wx.EXPAND)
+        set_type(self.tb[usrp_siggen.TYPE_KEY])
+        ##################################################
+        # Frequency controls
+        ##################################################
+        fc_vbox = forms.static_box_sizer(parent=self.panel, label="Center Frequency", orient=wx.VERTICAL, bold=True)
+        fc_vbox.AddSpacer(5)
+        # First row of frequency controls (center frequency)
+        freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
+        fc_vbox.AddSpacer(10)
+        # Second row of frequency controls (results)
+        tr_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        fc_vbox.Add(tr_hbox, 0, wx.EXPAND)
+        fc_vbox.AddSpacer(5)
+        # Add frequency controls to top window sizer
+        self.vbox.Add(fc_vbox, 0, wx.EXPAND)
+        self.vbox.AddSpacer(10)
+        self.vbox.AddStretchSpacer()
+        freq_hbox.AddSpacer(5)
+        forms.text_box(
+            parent=self.panel, sizer=freq_hbox,
+            proportion=1,
+            converter=forms.float_converter(),
+            ps=self.tb,
+            key=usrp_siggen.TX_FREQ_KEY,
+        )
+        freq_hbox.AddSpacer(10)
+        forms.slider(
+            parent=self.panel, sizer=freq_hbox,
+            proportion=2,
+            ps=self.tb,
+            key=usrp_siggen.TX_FREQ_KEY,
+            minimum=self.tb[usrp_siggen.FREQ_RANGE_KEY][0],
+            maximum=self.tb[usrp_siggen.FREQ_RANGE_KEY][1],
+            num_steps=100,
+        )
+        freq_hbox.AddSpacer(5)
+        tr_hbox.AddSpacer(5)
+        forms.static_text(
+            parent=self.panel, sizer=tr_hbox,
+            label='Daughterboard (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.BB_FREQ_KEY,
+            converter=forms.float_converter(),
+            proportion=1,
+        )
+        tr_hbox.AddSpacer(10)
+        forms.static_text(
+            parent=self.panel, sizer=tr_hbox,
+            label='USRP DDC (Hz)',
+            ps=self.tb,
+            key=usrp_siggen.DDC_FREQ_KEY,
+            converter=forms.float_converter(),
+            proportion=1,
+        )
+        tr_hbox.AddSpacer(5)
+        ##################################################
+        # Amplitude controls
+        ##################################################
+        amp_hbox = forms.static_box_sizer(parent=self.panel, label="Amplitude", orient=wx.VERTICAL, bold=True)
+        amp_hbox.AddSpacer(5)
+        # First row of amp controls (ampl)
+        lvl_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        amp_hbox.Add(lvl_hbox, 0, wx.EXPAND)
+        amp_hbox.AddSpacer(10)
+        # Second row of amp controls (tx gain)
+        gain_hbox = wx.BoxSizer(wx.HORIZONTAL)
+        amp_hbox.Add(gain_hbox, 0, wx.EXPAND)
+        amp_hbox.AddSpacer(5)
+        self.vbox.Add(amp_hbox, 0, wx.EXPAND)
+        self.vbox.AddSpacer(10)
+        self.vbox.AddStretchSpacer()
+        lvl_hbox.AddSpacer(5)
+        forms.text_box(
+            parent=self.panel, sizer=lvl_hbox,
+            proportion=1,
+            converter=forms.float_converter(),
+            ps=self.tb,
+            key=usrp_siggen.AMPLITUDE_KEY,
+            label="Level (0.0-1.0)",
+        )
+        lvl_hbox.AddSpacer(10)
+        forms.log_slider(
+            parent=self.panel, sizer=lvl_hbox,
+            proportion=2,
+            ps=self.tb,
+            key=usrp_siggen.AMPLITUDE_KEY,
+            min_exp=-6,
+            max_exp=0,
+            base=10,
+            num_steps=100,
+        )
+        lvl_hbox.AddSpacer(5)
+        if self.tb[usrp_siggen.GAIN_RANGE_KEY][0] < self.tb[usrp_siggen.GAIN_RANGE_KEY][1]:
+            gain_hbox.AddSpacer(5)
+            forms.text_box(
+                parent=self.panel, sizer=gain_hbox,
+                proportion=1,
+                converter=forms.float_converter(),
+                ps=self.tb,
+                key=usrp_siggen.GAIN_KEY,
+                label="TX Gain (dB)",
+            )
+            gain_hbox.AddSpacer(10)
+            forms.slider(
+                parent=self.panel, sizer=gain_hbox,
+                proportion=2,
+                ps=self.tb,
+                key=usrp_siggen.GAIN_KEY,
+                minimum=self.tb[usrp_siggen.GAIN_RANGE_KEY][0],
+                maximum=self.tb[usrp_siggen.GAIN_RANGE_KEY][1],
+                step_size=self.tb[usrp_siggen.GAIN_RANGE_KEY][2],
+            )
+            gain_hbox.AddSpacer(5)
+        ##################################################
+        # Sample Rate controls
+        ##################################################
+        sam_hbox = forms.static_box_sizer(parent=self.panel, label="Sample Rate", orient=wx.HORIZONTAL, bold=True)
+        self.vbox.Add(sam_hbox, 0, wx.EXPAND)
+        self.vbox.AddSpacer(10)
+        self.vbox.AddStretchSpacer()
+        sam_hbox.AddSpacer(5)
+        forms.text_box(
+            parent=self.panel, sizer=sam_hbox,
+            converter=forms.int_converter(),
+            ps=self.tb,
+            key=usrp_siggen.INTERP_KEY,
+            label="Interpolation",
+        )
+        sam_hbox.AddStretchSpacer(20)
+        forms.static_text(
+            parent=self.panel, sizer=sam_hbox,
+            label='Sample Rate (sps)',
+            ps=self.tb,
+            key=usrp_siggen.SAMP_RATE_KEY,
+            converter=forms.float_converter(),
+        )
+        sam_hbox.AddStretchSpacer(20)
+        forms.static_text(
+            parent=self.panel, sizer=sam_hbox,
+            label='Link Rate (bits/sec)',
+            ps=self.tb,
+            key=usrp_siggen.LINK_RATE_KEY,
+            converter=forms.float_converter(),
+        )
+        sam_hbox.AddSpacer(5)
+        ##################################################
+        # USRP status
+        ##################################################
+        u2_hbox = forms.static_box_sizer(parent=self.panel, label="USRP Status", orient=wx.HORIZONTAL, bold=True)
+        self.vbox.Add(u2_hbox, 0, wx.EXPAND)
+        self.vbox.AddSpacer(10)
+        self.vbox.AddStretchSpacer()
+        u2_hbox.AddSpacer(10)
+        forms.static_text(
+            parent=self.panel, sizer=u2_hbox,
+            ps=self.tb,
+            key=usrp_siggen.DESC_KEY,
+            converter=forms.str_converter(),
+        )
+        self.vbox.AddSpacer(5)
+        self.vbox.AddStretchSpacer()
+
+if __name__ == "__main__":
+    try:
+        # Get command line parameters
+        (options, args) = usrp_siggen.get_options()
+
+        # Create the top block using these
+        tb = usrp_siggen.top_block(options, args)
+
+        # Create the GUI application
+        app = gui.app(top_block=tb,                    # Constructed top block
+                      gui=app_gui,                     # User interface class
+                      options=options,                 # Command line options
+                      args=args,                       # Command line args
+                      title="USRP Signal Generator",  # Top window title
+                      nstatus=1,                       # Number of status lines
+                      start=True,                      # Whether to start flowgraph
+                      realtime=True)                   # Whether to set realtime priority
+
+        # And run it
+        app.MainLoop()
+
+    except RuntimeError, e:
+        print e
+        sys.exit(1)
index 237c8940c2bc389b293637d3d64a23fa0d257f69..e025c28dd71872679776064878c26be1970a03e7 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2008, 2009 Free Software Foundation, Inc.
 #
 # This file is part of GNU Radio
 #
@@ -156,9 +156,9 @@ class control_panel(wx.Panel):
        def _on_decr_ref_level(self, event):
                self.parent[REF_LEVEL_KEY] = self.parent[REF_LEVEL_KEY] - self.parent[Y_PER_DIV_KEY]
        def _on_incr_db_div(self, event):
-               self.parent[Y_PER_DIV_KEY] = min(DB_DIV_MAX, self.parent[Y_PER_DIV_KEY]*2)
+               self.parent[Y_PER_DIV_KEY] = min(DB_DIV_MAX, common.get_clean_incr(self.parent[Y_PER_DIV_KEY]))
        def _on_decr_db_div(self, event):
-               self.parent[Y_PER_DIV_KEY] = max(DB_DIV_MIN, self.parent[Y_PER_DIV_KEY]/2)
+               self.parent[Y_PER_DIV_KEY] = max(DB_DIV_MIN, common.get_clean_decr(self.parent[Y_PER_DIV_KEY]))
 
 ##################################################
 # FFT window with plotter and control panel
index 9f757aa8410eb24b7d226e9c828da4caa8a2fd6c..db14d2752c19ba6f3fa891129e86dc71407607bf 100644 (file)
@@ -72,12 +72,14 @@ class bool_converter(abstract_converter):
                self._true = true
                self._false = false
        def external_to_internal(self, v):
-               return bool(v)
+               if v == self._true: return True
+               if v == self._false: return False
+               raise Exception, 'Value "%s" is not a possible option.'%v
        def internal_to_external(self, v):
                if v: return self._true
                else: return self._false
        def help(self):
-               return "Value must be cast-able to type bool."
+               return "Value must be in (%s, %s)."%(self._true, self._false)
 
 class eval_converter(abstract_converter):
        """
@@ -134,8 +136,7 @@ class slider_converter(abstract_converter):
                self._scaler = float(maximum - minimum)/num_steps
                self._cast = cast
        def external_to_internal(self, v):
-               #slider's internal representation is an integer
-               return int(round((v - self._offset)/self._scaler))
+               return (v - self._offset)/self._scaler
        def internal_to_external(self, v):
                return self._cast(v*self._scaler + self._offset)
        def help(self):
index c69315b0358906c531bd1ceaeaeb23defe9237e1..8dc58367d9deac34251467061d307388b816945e 100644 (file)
@@ -176,7 +176,7 @@ class _slider_base(_form_base):
                self._add_widget(self._slider, label, flag=wx.EXPAND)
 
        def _handle(self, event): self[INT_KEY] = self._slider.GetValue()
-       def _update(self, value): self._slider.SetValue(value)
+       def _update(self, value): self._slider.SetValue(int(round(value)))
 
 ########################################################################
 # Static Text Form
@@ -224,11 +224,18 @@ class text_box(_form_base):
        def __init__(self, label='', width=-1, converter=converters.eval_converter(), **kwargs):
                _form_base.__init__(self, converter=converter, **kwargs)
                self._text_box = wx.TextCtrl(self._parent, size=wx.Size(width, -1), style=wx.TE_PROCESS_ENTER)
+               self._default_bg_colour = self._text_box.GetBackgroundColour()
                self._text_box.Bind(wx.EVT_TEXT_ENTER, self._handle)
+               self._text_box.Bind(wx.EVT_TEXT, self._update_color)
                self._add_widget(self._text_box, label)
 
+       def _update_color(self, *args):
+               if self._text_box.GetValue() == self[INT_KEY]:
+                       self._text_box.SetBackgroundColour(self._default_bg_colour)
+               else: self._text_box.SetBackgroundColour('#EEDDDD')
+
        def _handle(self, event): self[INT_KEY] = self._text_box.GetValue()
-       def _update(self, value): self._text_box.SetValue(value)
+       def _update(self, value): self._text_box.SetValue(value); self._update_color()
 
 ########################################################################
 # Slider Form
index 96ee11b67e721d44581a5c1d296ae6f287ca497c..c45d1ce1f33bee6cd49262aa8016f43a25447d0f 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2008, 2009 Free Software Foundation, Inc.
 #
 # This file is part of GNU Radio
 #
@@ -20,5 +20,5 @@
 #
 
 include $(top_srcdir)/Makefile.common
-grc_src_prefix = $(pythondir)/gnuradio/grc
+grc_src_prefix = $(pkgpythondir)/grc
 grc_blocksdir = $(pkgdatadir)/grc/blocks
index d5e1047852b7df5bfcd71b89135483debc183f18..203e878e400650105806d155ec243483c3cacd4c 100644 (file)
@@ -47,7 +47,9 @@ class TemplateArg(UserDict):
                return self._param.get_evaluated()
 
 def _get_keys(lst): return [elem.get_key() for elem in lst]
-def _get_elem(lst, key): return lst[_get_keys(lst).index(key)]
+def _get_elem(lst, key):
+       try: return lst[_get_keys(lst).index(key)]
+       except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
 
 class Block(Element):
 
@@ -72,16 +74,16 @@ class Block(Element):
                self._params = list()
                #add the id param
                self.get_params().append(self.get_parent().get_parent().Param(
-                       self,
-                       odict({
+                       block=self,
+                       n=odict({
                                'name': 'ID',
                                'key': 'id',
                                'type': 'id',
                        })
                ))
                self.get_params().append(self.get_parent().get_parent().Param(
-                       self,
-                       odict({
+                       block=self,
+                       n=odict({
                                'name': 'Enabled',
                                'key': '_enabled',
                                'type': 'raw',
@@ -89,7 +91,7 @@ class Block(Element):
                                'hide': 'all',
                        })
                ))
-               for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params):
+               for param in map(lambda n: self.get_parent().get_parent().Param(block=self, n=n), params):
                        key = param.get_key()
                        #test against repeated keys
                        try: assert key not in self.get_param_keys()
@@ -98,7 +100,7 @@ class Block(Element):
                        self.get_params().append(param)
                #create the source objects
                self._sources = list()
-               for source in map(lambda n: self.get_parent().get_parent().Source(self, n), sources):
+               for source in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='source'), sources):
                        key = source.get_key()
                        #test against repeated keys
                        try: assert key not in self.get_source_keys()
@@ -107,21 +109,13 @@ class Block(Element):
                        self.get_sources().append(source)
                #create the sink objects
                self._sinks = list()
-               for sink in map(lambda n: self.get_parent().get_parent().Sink(self, n), sinks):
+               for sink in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='sink'), sinks):
                        key = sink.get_key()
                        #test against repeated keys
                        try: assert key not in self.get_sink_keys()
                        except AssertionError: raise Exception, 'Key "%s" already exists in sinks'%key
                        #store the port
                        self.get_sinks().append(sink)
-               #begin the testing
-               self.test()
-
-       def test(self):
-               """
-               Call test on all children.
-               """
-               map(lambda c: c.test(), self.get_params() + self.get_sinks() + self.get_sources())
 
        def get_enabled(self):
                """
@@ -138,21 +132,6 @@ class Block(Element):
                """
                self.get_param('_enabled').set_value(str(enabled))
 
-       def validate(self):
-               """
-               Validate the block.
-               All ports and params must be valid.
-               All checks must evaluate to true.
-               """
-               Element.validate(self)
-               for c in self.get_params() + self.get_ports() + self.get_connections():
-                       try:
-                               c.validate()
-                               assert c.is_valid()
-                       except AssertionError:
-                               for msg in c.get_error_messages():
-                                       self.add_error_message('>>> %s:\n\t%s'%(c, msg))
-
        def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
 
        def get_id(self): return self.get_param('id').get_value()
@@ -162,6 +141,7 @@ class Block(Element):
        def get_category(self): return self._category
        def get_doc(self): return ''
        def get_ports(self): return self.get_sources() + self.get_sinks()
+       def get_children(self): return self.get_ports() + self.get_params()
        def get_block_wrapper_path(self): return self._block_wrapper_path
 
        ##############################################
@@ -253,12 +233,22 @@ class Block(Element):
                """
                Import this block's params from nested data.
                Any param keys that do not exist will be ignored.
+               Since params can be dynamically created based another param,
+               call rewrite, and repeat the load until the params stick.
+               This call to rewrite will also create any dynamic ports
+               that are needed for the connections creation phase.
                @param n the nested data odict
                """
-               params_n = n.findall('param')
-               for param_n in params_n:
-                       key = param_n.find('key')
-                       value = param_n.find('value')
-                       #the key must exist in this block's params
-                       if key in self.get_param_keys():
-                               self.get_param(key).set_value(value)
+               get_hash = lambda: reduce(lambda x, y: x ^ y, [hash(param) for param in self.get_params()], 0)
+               my_hash = 0
+               while get_hash() != my_hash:
+                       params_n = n.findall('param')
+                       for param_n in params_n:
+                               key = param_n.find('key')
+                               value = param_n.find('value')
+                               #the key must exist in this block's params
+                               if key in self.get_param_keys():
+                                       self.get_param(key).set_value(value)
+                       #store hash and call rewrite
+                       my_hash = get_hash()
+                       self.rewrite()
index 16000c46c0a87068491da35f6228c58577c3be37..a57090f3b24a2f5928d3f7c6facb1bfee48b7969 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -21,37 +21,59 @@ class Element(object):
 
        def __init__(self, parent=None):
                self._parent = parent
-               self.flag()
-
-       def test(self):
-               """
-               Test the element against failures.
-               Overload this method in sub-classes.
-               """
-               pass
 
        ##################################################
        # Element Validation API
        ##################################################
-       def validate(self): self._error_messages = list()
-       def is_valid(self): return not self.get_error_messages() or not self.get_enabled()
-       def add_error_message(self, msg): self._error_messages.append(msg)
-       def get_error_messages(self): return self._error_messages
+       def validate(self):
+               """
+               Validate this element and call validate on all children.
+               Call this base method before adding error messages in the subclass.
+               """
+               self._error_messages = list()
+               for child in self.get_children(): child.validate()
 
-       def get_enabled(self): return True
+       def is_valid(self):
+               """
+               Is this element valid?
+               @return true when the element is enabled and has no error messages
+               """
+               return not self.get_error_messages() or not self.get_enabled()
 
-       def get_parent(self): return self._parent
+       def add_error_message(self, msg):
+               """
+               Add an error message to the list of errors.
+               @param msg the error message string
+               """
+               self._error_messages.append(msg)
+
+       def get_error_messages(self):
+               """
+               Get the list of error messages from this element and all of its children.
+               Do not include the error messages from disabled children.
+               Cleverly indent the children error messages for printing purposes.
+               @return a list of error message strings
+               """
+               error_messages = list(self._error_messages) #make a copy
+               for child in filter(lambda c: c.get_enabled(), self.get_children()):
+                       for msg in child.get_error_messages():
+                               error_messages.append("%s:\n\t%s"%(child, msg.replace("\n", "\n\t")))
+               return error_messages
+
+       def rewrite(self):
+               """
+               Rewrite this element and call rewrite on all children.
+               Call this base method before rewriting the element.
+               """
+               for child in self.get_children(): child.rewrite()
+
+       def get_enabled(self): return True
 
        ##############################################
-       ## Update flagging
+       ## Tree-like API
        ##############################################
-       def is_flagged(self): return self._flag
-       def flag(self):
-               self._flag = True
-               if self.get_parent(): self.get_parent().flag()
-       def deflag(self):
-               self._flag = False
-               if self.get_parent(): self.get_parent().deflag()
+       def get_parent(self): return self._parent
+       def get_children(self): return list()
 
        ##############################################
        ## Type testing methods
index ea489e948679b6106d9ea4d85b75534ca2627e0a..7c51ef42a475a7fb0ba6fceff4465c2131c079a3 100644 (file)
@@ -68,6 +68,7 @@ class FlowGraph(Element):
        def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0]
        def get_blocks(self): return filter(lambda e: e.is_block(), self.get_elements())
        def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements())
+       def get_children(self): return self.get_elements()
        def get_elements(self):
                """
                Get a list of all the elements.
@@ -102,7 +103,6 @@ class FlowGraph(Element):
                @param key the block key
                @return the new block or None if not found
                """
-               self.flag()
                if key not in self.get_parent().get_block_keys(): return None
                block = self.get_parent().get_new_block(self, key)
                self.get_elements().append(block)
@@ -116,8 +116,7 @@ class FlowGraph(Element):
                @throw Exception bad connection
                @return the new connection
                """
-               self.flag()
-               connection = self.get_parent().Connection(self, porta, portb)
+               connection = self.get_parent().Connection(flow_graph=self, porta=porta, portb=portb)
                self.get_elements().append(connection)
                return connection
 
@@ -128,7 +127,6 @@ class FlowGraph(Element):
                If the element is a block, remove its connections.
                If the element is a connection, just remove the connection.
                """
-               self.flag()
                if element not in self.get_elements(): return
                #found a port, set to parent signal block
                if element.is_port():
@@ -147,18 +145,6 @@ class FlowGraph(Element):
                """
                raise NotImplementedError
 
-       def validate(self):
-               """
-               Validate the flow graph.
-               All connections and blocks must be valid.
-               """
-               Element.validate(self)
-               for c in self.get_elements():
-                       try:
-                               c.validate()
-                               assert c.is_valid()
-                       except AssertionError: self.add_error_message('Element "%s" is not valid.'%c)
-
        ##############################################
        ## Import/Export Methods
        ##############################################
@@ -198,7 +184,6 @@ class FlowGraph(Element):
                        #only load the block when the block key was valid
                        if block: block.import_data(block_n)
                        else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent()))
-               self.validate() #validate all blocks before connections are made (in case of nports)
                #build the connections
                for connection_n in connections_n:
                        #try to make the connection
@@ -225,3 +210,4 @@ class FlowGraph(Element):
                                #build the connection
                                self.connect(source, sink)
                        except AssertionError: Messages.send_error_load('Connection between %s(%s) and %s(%s) could not be made.'%(source_block_id, source_key, sink_block_id, sink_key))
+               self.rewrite() #global rewrite
index 93c1c52bdef38114ccc948c9d08dfe1b5856e9dd..e56eac36e172a4185c2b6f0c2b3d17c10deef984 100644 (file)
@@ -19,74 +19,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 from . import odict
 from Element import Element
-import pygtk
-pygtk.require('2.0')
-import gtk
 
-class InputParam(gtk.HBox):
-       """The base class for an input parameter inside the input parameters dialog."""
-
-       def __init__(self, param, _handle_changed):
-               gtk.HBox.__init__(self)
-               self.param = param
-               self._handle_changed = _handle_changed
-               self.label = gtk.Label('') #no label, markup is added by set_markup
-               self.label.set_size_request(150, -1)
-               self.pack_start(self.label, False)
-               self.set_markup = lambda m: self.label.set_markup(m)
-               self.tp = None
-       def set_color(self, color): pass
-
-class EntryParam(InputParam):
-       """Provide an entry box for strings and numbers."""
-
-       def __init__(self, *args, **kwargs):
-               InputParam.__init__(self, *args, **kwargs)
-               self.entry = input = gtk.Entry()
-               input.set_text(self.param.get_value())
-               input.connect('changed', self._handle_changed)
-               self.pack_start(input, True)
-               self.get_text = input.get_text
-               #tool tip
-               self.tp = gtk.Tooltips()
-               self.tp.set_tip(self.entry, '')
-               self.tp.enable()
-       def set_color(self, color): self.entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
-
-class EnumParam(InputParam):
-       """Provide an entry box for Enum types with a drop down menu."""
-
-       def __init__(self, *args, **kwargs):
-               InputParam.__init__(self, *args, **kwargs)
-               self._input = gtk.combo_box_new_text()
-               for option in self.param.get_options(): self._input.append_text(option.get_name())
-               self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
-               self._input.connect('changed', self._handle_changed)
-               self.pack_start(self._input, False)
-       def get_text(self): return self.param.get_option_keys()[self._input.get_active()]
-
-class EnumEntryParam(InputParam):
-       """Provide an entry box and drop down menu for Raw Enum types."""
-
-       def __init__(self, *args, **kwargs):
-               InputParam.__init__(self, *args, **kwargs)
-               self._input = gtk.combo_box_entry_new_text()
-               for option in self.param.get_options(): self._input.append_text(option.get_name())
-               try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
-               except:
-                       self._input.set_active(-1)
-                       self._input.get_child().set_text(self.param.get_value())
-               self._input.connect('changed', self._handle_changed)
-               self._input.get_child().connect('changed', self._handle_changed)
-               self.pack_start(self._input, False)
-       def get_text(self):
-               if self._input.get_active() == -1: return self._input.get_child().get_text()
-               return self.param.get_option_keys()[self._input.get_active()]
-       def set_color(self, color):
-               if self._input.get_active() == -1: #custom entry, use color
-                       self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
-               else: #from enum, make white background
-                       self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff'))
+def _get_keys(lst): return [elem.get_key() for elem in lst]
+def _get_elem(lst, key):
+       try: return lst[_get_keys(lst).index(key)]
+       except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
 
 class Option(Element):
 
@@ -123,15 +60,11 @@ class Option(Element):
 
 class Param(Element):
 
-       ##possible param types
-       TYPES = ['enum', 'raw']
-
        def __init__(self, block, n):
                """
                Make a new param from nested data.
                @param block the parent element
                @param n the nested odict
-               @return a new param
                """
                #grab the data
                self._name = n.find('name')
@@ -142,22 +75,22 @@ class Param(Element):
                #build the param
                Element.__init__(self, block)
                #create the Option objects from the n data
-               self._options = odict()
-               for option in map(lambda o: Option(self, o), n.findall('option')):
+               self._options = list()
+               for option in map(lambda o: Option(param=self, n=o), n.findall('option')):
                        key = option.get_key()
                        #test against repeated keys
                        try: assert key not in self.get_option_keys()
                        except AssertionError: raise Exception, 'Key "%s" already exists in options'%key
                        #store the option
-                       self._options[key] = option
+                       self.get_options().append(option)
                #test the enum options
                if self.is_enum():
                        #test against options with identical keys
-                       try: assert len(set(self.get_option_keys())) == len(self._options)
+                       try: assert len(set(self.get_option_keys())) == len(self.get_options())
                        except AssertionError: raise Exception, 'Options keys "%s" are not unique.'%self.get_option_keys()
                        #test against inconsistent keys in options
-                       opt_keys = self._options.values()[0].get_opt_keys()
-                       for option in self._options.values():
+                       opt_keys = self.get_options()[0].get_opt_keys()
+                       for option in self.get_options():
                                try: assert set(opt_keys) == set(option.get_opt_keys())
                                except AssertionError: raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys
                        #if a value is specified, it must be in the options keys
@@ -165,14 +98,6 @@ class Param(Element):
                        try: assert self.get_value() in self.get_option_keys()
                        except AssertionError: raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())
                else: self._value = value or ''
-               #begin the testing
-               self.test()
-
-       def test(self):
-               """
-               call test on all children
-               """
-               map(lambda c: c.test(), self.get_options())
 
        def validate(self):
                """
@@ -180,7 +105,7 @@ class Param(Element):
                The value must be evaluated and type must a possible type.
                """
                Element.validate(self)
-               try: assert self.get_type() in self.TYPES
+               try: assert self.get_type() in self.get_types()
                except AssertionError: self.add_error_message('Type "%s" is not a possible type.'%self.get_type())
 
        def get_evaluated(self): raise NotImplementedError
@@ -192,12 +117,19 @@ class Param(Element):
                """
                raise NotImplementedError
 
+       def get_types(self):
+               """
+               Get a list of all possible param types.
+               @throw NotImplementedError
+               """
+               raise NotImplementedError
+
        def get_color(self): return '#FFFFFF'
        def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key())
        def is_param(self): return True
        def get_name(self): return self._name
        def get_key(self): return self._key
-       def get_hide(self): return self.get_parent().resolve_dependencies(self._hide)
+       def get_hide(self): return self.get_parent().resolve_dependencies(self._hide).strip()
 
        def get_value(self):
                value = self._value
@@ -206,9 +138,7 @@ class Param(Element):
                        self.set_value(value)
                return value
 
-       def set_value(self, value):
-               self.flag()
-               self._value = str(value) #must be a string
+       def set_value(self, value): self._value = str(value) #must be a string
 
        def get_type(self): return self.get_parent().resolve_dependencies(self._type)
        def is_enum(self): return self._type == 'enum'
@@ -223,31 +153,19 @@ class Param(Element):
                if self.is_enum(): return self.get_option(self.get_value()).get_name()
                return self.get_value()
 
-       def get_input_class(self):
-               """
-               Get the graphical gtk class to represent this parameter.
-               An enum requires and combo parameter.
-               A non-enum with options gets a combined entry/combo parameter.
-               All others get a standard entry parameter.
-               @return gtk input class
-               """
-               if self.is_enum(): return EnumParam
-               if self.get_options(): return EnumEntryParam
-               return EntryParam
-
        ##############################################
        # Access Options
        ##############################################
-       def get_option_keys(self): return self._options.keys()
-       def get_option(self, key): return self._options[key]
-       def get_options(self): return self._options.values()
+       def get_option_keys(self): return _get_keys(self.get_options())
+       def get_option(self, key): return _get_elem(self.get_options(), key)
+       def get_options(self): return self._options
 
        ##############################################
        # Access Opts
        ##############################################
-       def get_opt_keys(self): return self._options[self.get_value()].get_opt_keys()
-       def get_opt(self, key): return self._options[self.get_value()].get_opt(key)
-       def get_opts(self): return self._options[self.get_value()].get_opts()
+       def get_opt_keys(self): return self.get_option(self.get_value()).get_opt_keys()
+       def get_opt(self, key): return self.get_option(self.get_value()).get_opt(key)
+       def get_opts(self): return self.get_option(self.get_value()).get_opts()
 
        ##############################################
        ## Import/Export Methods
index 02d6d2319257e969c1b8b4f151b02556698df6ab..51a3b2f871eb824aea1fee2227201515a06e2dee 100644 (file)
@@ -146,7 +146,7 @@ class Platform(_Element):
 
        def is_platform(self): return True
 
-       def get_new_flow_graph(self): return self.FlowGraph(self)
+       def get_new_flow_graph(self): return self.FlowGraph(platform=self)
 
        def get_generator(self): return self._generator
 
@@ -171,6 +171,5 @@ class Platform(_Element):
        FlowGraph = _FlowGraph
        Connection = _Connection
        Block = _Block
-       Source = _Port
-       Sink = _Port
+       Port = _Port
        Param = _Param
index f4e8e5e1fb2a6f648aef6118b545b5a9e0d3354d..494ea894f7bdcf55551fc403845472b3aef1207d 100644 (file)
@@ -21,25 +21,20 @@ from Element import Element
 
 class Port(Element):
 
-       ##possible port types
-       TYPES = []
-
-       def __init__(self, block, n):
+       def __init__(self, block, n, dir):
                """
                Make a new port from nested data.
                @param block the parent element
                @param n the nested odict
-               @return a new port
+               @param dir the direction source or sink
                """
-               #grab the data
-               name = n['name']
-               key = n['key']
-               type = n['type']
                #build the port
                Element.__init__(self, block)
-               self._name = name
-               self._key = key
-               self._type = type
+               #grab the data
+               self._name = n['name']
+               self._key = n['key']
+               self._type = n['type']
+               self._dir = dir
 
        def validate(self):
                """
@@ -47,7 +42,7 @@ class Port(Element):
                The port must be non-empty and type must a possible type.
                """
                Element.validate(self)
-               try: assert self.get_type() in self.TYPES
+               try: assert self.get_type() in self.get_types()
                except AssertionError: self.add_error_message('Type "%s" is not a possible type.'%self.get_type())
 
        def __str__(self):
@@ -56,12 +51,19 @@ class Port(Element):
                if self.is_sink():
                        return 'Sink - %s(%s)'%(self.get_name(), self.get_key())
 
+       def get_types(self):
+               """
+               Get a list of all possible port types.
+               @throw NotImplementedError
+               """
+               raise NotImplementedError
+
        def is_port(self): return True
        def get_color(self): return '#FFFFFF'
        def get_name(self): return self._name
        def get_key(self): return self._key
-       def is_sink(self): return self in self.get_parent().get_sinks()
-       def is_source(self): return self in self.get_parent().get_sources()
+       def is_sink(self): return self._dir == 'sink'
+       def is_source(self): return self._dir == 'source'
        def get_type(self): return self.get_parent().resolve_dependencies(self._type)
 
        def get_connections(self):
index caae6ce7540e7c8465a91c94d4feb23ce8ab8376..617a3bf6085bd50f2f1b577d1c7fc404dd1fbe2d 100644 (file)
@@ -30,6 +30,8 @@ dist_ourdata_DATA = \
        band_reject_filter.xml \
        blks2_am_demod_cf.xml \
        blks2_analysis_filterbank.xml \
+       blks2_cvsd_encode.xml \
+       blks2_cvsd_decode.xml \
        blks2_dxpsk_demod.xml \
        blks2_dxpsk_mod.xml \
        blks2_error_rate.xml \
@@ -218,6 +220,8 @@ dist_ourdata_DATA = \
        variable_slider.xml \
        variable_static_text.xml \
        variable_text_box.xml \
+       virtual_sink.xml \
+       virtual_source.xml \
        wxgui_constellationsink2.xml \
        wxgui_fftsink2.xml \
        wxgui_histosink2.xml \
index e2e9acf4ebf9148fff3514ea0fdda93ba718bdd4..af083473d3a59f9a5fd3e76e6dc9b473973a5df1 100644 (file)
@@ -10,8 +10,8 @@
        <import>from gnuradio import gr</import>
        <import>from gnuradio.gr import firdes</import>
        <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.$(type.fcn)(
-       $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta))</make>
-       <callback>set_taps(firdes.$(type.fcn)($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta))</callback>
+       $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</make>
+       <callback>set_taps(firdes.$(type.fcn)($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</callback>
        <param>
                <name>FIR Type</name>
                <key>type</key>
        </param>
        <param>
                <name>Window</name>
-               <key>window</key>
-               <type>enum</type>
+               <key>win</key>
+               <value>firdes.WIN_HAMMING</value>
+               <type>int</type>
                <option>
                        <name>Hamming</name>
-                       <key>WIN_HAMMING</key>
+                       <key>firdes.WIN_HAMMING</key>
                </option>
                <option>
                        <name>Hann</name>
-                       <key>WIN_HANN</key>
+                       <key>firdes.WIN_HANN</key>
                </option>
                <option>
                        <name>Blackman</name>
-                       <key>WIN_BLACKMAN</key>
+                       <key>firdes.WIN_BLACKMAN</key>
                </option>
                <option>
                        <name>Rectangular</name>
-                       <key>WIN_RECTANGULAR</key>
+                       <key>firdes.WIN_RECTANGULAR</key>
                </option>
                <option>
                        <name>Kaiser</name>
-                       <key>WIN_KAISER</key>
+                       <key>firdes.WIN_KAISER</key>
                </option>
        </param>
        <param>
index 3b58f0b51431a1d555c650dcd0e6ddf9a2b6c7de..dd5e7a9d7664a814867dad3ab34b83b7aebabfa5 100644 (file)
@@ -10,8 +10,8 @@
        <import>from gnuradio import gr</import>
        <import>from gnuradio.gr import firdes</import>
        <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.band_reject(
-       $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta))</make>
-       <callback>set_taps(firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta))</callback>
+       $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</make>
+       <callback>set_taps(firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</callback>
        <param>
                <name>FIR Type</name>
                <key>type</key>
        </param>
        <param>
                <name>Window</name>
-               <key>window</key>
-               <type>enum</type>
+               <key>win</key>
+               <value>firdes.WIN_HAMMING</value>
+               <type>int</type>
                <option>
                        <name>Hamming</name>
-                       <key>WIN_HAMMING</key>
+                       <key>firdes.WIN_HAMMING</key>
                </option>
                <option>
                        <name>Hann</name>
-                       <key>WIN_HANN</key>
+                       <key>firdes.WIN_HANN</key>
                </option>
                <option>
                        <name>Blackman</name>
-                       <key>WIN_BLACKMAN</key>
+                       <key>firdes.WIN_BLACKMAN</key>
                </option>
                <option>
                        <name>Rectangular</name>
-                       <key>WIN_RECTANGULAR</key>
+                       <key>firdes.WIN_RECTANGULAR</key>
                </option>
                <option>
                        <name>Kaiser</name>
-                       <key>WIN_KAISER</key>
+                       <key>firdes.WIN_KAISER</key>
                </option>
        </param>
        <param>
diff --git a/grc/blocks/blks2_cvsd_decode.xml b/grc/blocks/blks2_cvsd_decode.xml
new file mode 100644 (file)
index 0000000..6be7daa
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## CVSD Encoder
+###################################################
+ -->
+<block>
+       <name>CVSD Decoder</name>
+       <key>blks2_cvsd_decode</key>
+       <import>from gnuradio import blks2</import>
+       <make>blks2.cvsd_decode($resample,$bw)</make>
+       <param>
+         <name>Resample</name>
+         <key>resample</key>
+         <value>8</value>
+         <type>int</type>
+       </param>
+       <param>
+         <name>Frac. Bandwidth</name>
+         <key>bw</key>
+         <value>0.5</value>
+         <type>real</type>
+       </param>
+       <sink>
+               <name>in</name>
+               <type>byte</type>
+       </sink>
+       <source>
+               <name>out</name>
+               <type>float</type>
+       </source>
+</block>
diff --git a/grc/blocks/blks2_cvsd_encode.xml b/grc/blocks/blks2_cvsd_encode.xml
new file mode 100644 (file)
index 0000000..3123b1a
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## CVSD Encoder
+###################################################
+ -->
+<block>
+       <name>CVSD Encoder</name>
+       <key>blks2_cvsd_encode</key>
+       <import>from gnuradio import blks2</import>
+       <make>blks2.cvsd_encode($resample,$bw)</make>
+       <param>
+         <name>Resample</name>
+         <key>resample</key>
+         <value>8</value>
+         <type>int</type>
+       </param>
+       <param>
+         <name>Frac. Bandwidth</name>
+         <key>bw</key>
+         <value>0.5</value>
+         <type>real</type>
+       </param>
+       <sink>
+               <name>in</name>
+               <type>float</type>
+       </sink>
+       <source>
+               <name>out</name>
+               <type>byte</type>
+       </source>
+</block>
index 5b45466f59289a25759b88bc5322debd24ca87e9..296f0ee911b505298cc893675656aa1cd88f74e1 100644 (file)
@@ -22,6 +22,7 @@
                <block>gr_wavfile_source</block>
                <block>gr_message_source</block>
                <block>pad_source</block>
+               <block>virtual_source</block>
        </cat>
        <cat>
                <name>Sinks</name>
@@ -35,6 +36,7 @@
                <block>gr_wavfile_sink</block>
                <block>gr_message_sink</block>
                <block>pad_sink</block>
+               <block>virtual_sink</block>
        </cat>
        <cat>
                <name>Graphical Sinks</name>
                <block>gr_scrambler_bb</block>
                <block>gr_descrambler_bb</block>
        </cat>
+       <cat>
+               <name>Vocoders</name>
+               <block>blks2_cvsd_encode</block>
+               <block>blks2_cvsd_decode</block>
+       </cat>
        <cat>
                <name>Probes</name>
                <block>gr_probe_avg_mag_sqrd_x</block>
index 4fcef5148d53e167627f2d76e5f892238d2426e5..4789b4400b8a71d3ca7b20ab74ebab56413e066b 100644 (file)
@@ -40,7 +40,7 @@
                <name>Noise Type</name>
                <key>noise_type</key>
                <value>gr.GR_GAUSSIAN</value>
-               <type>raw</type>
+               <type>int</type>
                <option>
                        <name>Uniform</name>
                        <key>gr.GR_UNIFORM</key>
index c329dba67fb0e34790fcc0fe93f44c4c5717f089..644cf52d0c7d50e4f5ea331e38584b190693c242 100644 (file)
@@ -53,7 +53,7 @@
                <name>Waveform</name>
                <key>waveform</key>
                <value>gr.GR_COS_WAVE</value>
-               <type>raw</type>
+               <type>int</type>
                <option>
                        <name>Constant</name>
                        <key>gr.GR_CONST_WAVE</key>
index 5be916fa97be3cfab26297f21926411d875d47fb..0e29cbb36f3a9ca8113786f5e5e80a5ac72e2061 100644 (file)
@@ -10,8 +10,8 @@
        <import>from gnuradio import gr</import>
        <import>from gnuradio.gr import firdes</import>
        <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.high_pass(
-       $gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta))</make>
-       <callback>set_taps(firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta))</callback>
+       $gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</make>
+       <callback>set_taps(firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</callback>
        <param>
                <name>FIR Type</name>
                <key>type</key>
        </param>
        <param>
                <name>Window</name>
-               <key>window</key>
-               <type>enum</type>
+               <key>win</key>
+               <value>firdes.WIN_HAMMING</value>
+               <type>int</type>
                <option>
                        <name>Hamming</name>
-                       <key>WIN_HAMMING</key>
+                       <key>firdes.WIN_HAMMING</key>
                </option>
                <option>
                        <name>Hann</name>
-                       <key>WIN_HANN</key>
+                       <key>firdes.WIN_HANN</key>
                </option>
                <option>
                        <name>Blackman</name>
-                       <key>WIN_BLACKMAN</key>
+                       <key>firdes.WIN_BLACKMAN</key>
                </option>
                <option>
                        <name>Rectangular</name>
-                       <key>WIN_RECTANGULAR</key>
+                       <key>firdes.WIN_RECTANGULAR</key>
                </option>
                <option>
                        <name>Kaiser</name>
-                       <key>WIN_KAISER</key>
+                       <key>firdes.WIN_KAISER</key>
                </option>
        </param>
        <param>
index 27120c0471d9120bea28748f3005c3a8563038f3..26435fd4d8f36dde9d6ae5f6f7b920fa5f766c85 100644 (file)
@@ -10,8 +10,8 @@
        <import>from gnuradio import gr</import>
        <import>from gnuradio.gr import firdes</import>
        <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.low_pass(
-       $gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta))</make>
-       <callback>set_taps(firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta))</callback>
+       $gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</make>
+       <callback>set_taps(firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</callback>
        <param>
                <name>FIR Type</name>
                <key>type</key>
        </param>
        <param>
                <name>Window</name>
-               <key>window</key>
-               <type>enum</type>
+               <key>win</key>
+               <value>firdes.WIN_HAMMING</value>
+               <type>int</type>
                <option>
                        <name>Hamming</name>
-                       <key>WIN_HAMMING</key>
+                       <key>firdes.WIN_HAMMING</key>
                </option>
                <option>
                        <name>Hann</name>
-                       <key>WIN_HANN</key>
+                       <key>firdes.WIN_HANN</key>
                </option>
                <option>
                        <name>Blackman</name>
-                       <key>WIN_BLACKMAN</key>
+                       <key>firdes.WIN_BLACKMAN</key>
                </option>
                <option>
                        <name>Rectangular</name>
-                       <key>WIN_RECTANGULAR</key>
+                       <key>firdes.WIN_RECTANGULAR</key>
                </option>
                <option>
                        <name>Kaiser</name>
-                       <key>WIN_KAISER</key>
+                       <key>firdes.WIN_KAISER</key>
                </option>
        </param>
        <param>
index 18d6e2f0c99fc0818a5177950cc438672e6f55d0..1798a69f88a834c9dccd6ad7e878198b2d147372 100644 (file)
@@ -9,16 +9,17 @@
 <block>
        <name>Options</name>
        <key>options</key>
-       <import>from gnuradio import gr
-#if $generate_options() == 'wx_gui'
+       <import>from gnuradio import gr</import>
+       <import>from gnuradio.gr import firdes</import>
+       <import>#if $generate_options() == 'wx_gui'
 from grc_gnuradio import wxgui as grc_wxgui
 import wx
 #end if
 #if $generate_options() != 'hb'
 from optparse import OptionParser
 from gnuradio.eng_option import eng_option
-#end if
-</import>
+from gnuradio import eng_notation
+#end if</import>
        <make></make>
        <callback>if $run: self.start()
 else: self.stop(); self.wait()</callback>
index 477f2ad13a044a8911bd2e8db37488fdb522059a..734526793fae96b1c1ef890faf61feeab0c3167b 100644 (file)
                <nports>$nports</nports>
        </sink>
        <doc>
-This is a sink pad block for creating hierarchical flow graphs. \
 The inputs of this block will become the outputs to this flow graph when it is instantiated as a hierarchical block. \
 Limit one sink pad block per flow graph.
-
-Remember to set the generate options to hier block.
        </doc>
 </block>
index b6ef2c55d1e2f2e6bbc3770ff066716d4da2b644..f44d9623879d77b1c35026b82eeddf745bdc3b3c 100644 (file)
                <nports>$nports</nports>
        </source>
        <doc>
-This is a source pad block for creating hierarchical flow graphs. \
 The outputs of this block will become the inputs to this flow graph when it is instantiated as a hierarchical block. \
-Limit one source pad block per flow graph.
-
-Remember to set the generate options to hier block.
+Limit one source pad block per flow graph. \
+The "pad sink id" will be ignored in this mode.
        </doc>
 </block>
index 5d08c4b394662f8824877f13ea2153cd559e1c86..e35b8f4d1d8bc7c7ac9bd14a06acf6cb6a1eb0ae 100644 (file)
@@ -45,7 +45,7 @@
                </option>
                <option>
                        <name>Int</name>
-                       <key>int</key>
+                       <key>intx</key>
                        <opt>type:int</opt>
                </option>
                <option>
                        <key>string</key>
                        <opt>type:string</opt>
                </option>
+               <!-- not supported yet in tmpl
+               <option>
+                       <name>Boolean</name>
+                       <key>bool</key>
+                       <opt>type:bool</opt>
+               </option>
+               -->
        </param>
        <param>
                <name>Short ID</name>
diff --git a/grc/blocks/virtual_sink.xml b/grc/blocks/virtual_sink.xml
new file mode 100644 (file)
index 0000000..35fb27e
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Virtual Sink
+###################################################
+ -->
+<block>
+       <name>Virtual Sink</name>
+       <key>virtual_sink</key>
+       <make></make>
+       <param>
+               <name>Stream ID</name>
+               <key>stream_id</key>
+               <value></value>
+               <type>stream_id</type>
+       </param>
+       <sink>
+               <name>in</name>
+               <type></type>
+       </sink>
+</block>
diff --git a/grc/blocks/virtual_source.xml b/grc/blocks/virtual_source.xml
new file mode 100644 (file)
index 0000000..e0c7754
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Virtual Source
+###################################################
+ -->
+<block>
+       <name>Virtual Source</name>
+       <key>virtual_source</key>
+       <make></make>
+       <param>
+               <name>Stream ID</name>
+               <key>stream_id</key>
+               <value></value>
+               <type>stream_id</type>
+       </param>
+       <source>
+               <name>out</name>
+               <type></type>
+       </source>
+</block>
index faeca37e3217bea7f8db5860e29ad5117693c1c5..6f19f1aa47d3e8c41725791a43da29db4d663006 100644 (file)
@@ -15,6 +15,7 @@ fftsink2.$(type.fcn)(
        y_per_div=$y_per_div,
        y_divs=$y_divs,
        ref_level=$ref_level,
+       ref_scale=$ref_scale,
        sample_rate=$samp_rate,
        fft_size=$fft_size,
        fft_rate=$fft_rate,
@@ -102,6 +103,12 @@ $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
                <value>50</value>
                <type>real</type>
        </param>
+       <param>
+               <name>Ref Scale (p2p)</name>
+               <key>ref_scale</key>
+               <value>2.0</value>
+               <type>real</type>
+       </param>
        <param>
                <name>FFT Size</name>
                <key>fft_size</key>
index 79ca356f704e6f92919c803b973f2a4d302bbeb0..35790f820b716b68de105d983bcf4b5521f213ba 100644 (file)
@@ -14,6 +14,7 @@ waterfallsink2.$(type.fcn)(
        baseband_freq=$baseband_freq,
        dynamic_range=$dynamic_range,
        ref_level=$ref_level,
+       ref_scale=$ref_scale,
        sample_rate=$samp_rate,
        fft_size=$fft_size,
        fft_rate=$fft_rate,
@@ -74,6 +75,12 @@ $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
                <value>50</value>
                <type>real</type>
        </param>
+       <param>
+               <name>Ref Scale (p2p)</name>
+               <key>ref_scale</key>
+               <value>2.0</value>
+               <type>real</type>
+       </param>
        <param>
                <name>FFT Size</name>
                <key>fft_size</key>
index 969485c0d5fa22c2c8934fdfca6ee50767bdee4a..78321ce0a8db288208c6dcee51335670dedf5963 100644 (file)
@@ -25,7 +25,8 @@ grc_examples_prefix = $(exampledir)/grc
 
 audiodatadir = $(grc_examples_prefix)/audio
 dist_audiodata_DATA = \
-       audio/dial_tone.grc
+       audio/dial_tone.grc \
+       audio/cvsd_sweep.grc
 
 simpledatadir = $(grc_examples_prefix)/simple
 dist_simpledata_DATA = \
diff --git a/grc/examples/audio/cvsd_sweep.grc b/grc/examples/audio/cvsd_sweep.grc
new file mode 100644 (file)
index 0000000..8d0b385
--- /dev/null
@@ -0,0 +1,918 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+  <timestamp>Sat Sep 19 20:30:08 2009</timestamp>
+  <block>
+    <key>import</key>
+    <param>
+      <key>id</key>
+      <value>import_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>import</key>
+      <value>import math</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(157, 11)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>blks2_cvsd_decode</key>
+    <param>
+      <key>id</key>
+      <value>blks2_cvsd_decode_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>resample</key>
+      <value>resample</value>
+    </param>
+    <param>
+      <key>bw</key>
+      <value>bw</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(887, 340)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_sig_source_x</key>
+    <param>
+      <key>id</key>
+      <value>tri_source</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>waveform</key>
+      <value>gr.GR_TRI_WAVE</value>
+    </param>
+    <param>
+      <key>freq</key>
+      <value>0.05</value>
+    </param>
+    <param>
+      <key>amp</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>offset</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(44, 316)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_throttle</key>
+    <param>
+      <key>id</key>
+      <value>throttle</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>samples_per_second</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(238, 348)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_vco_f</key>
+    <param>
+      <key>id</key>
+      <value>vco</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>sensitivity</key>
+      <value>audio_rate*2*math.pi</value>
+    </param>
+    <param>
+      <key>amplitude</key>
+      <value>0.9</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(427, 332)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>blks2_cvsd_encode</key>
+    <param>
+      <key>id</key>
+      <value>enc</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>resample</key>
+      <value>resample</value>
+    </param>
+    <param>
+      <key>bw</key>
+      <value>bw</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(655, 340)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_packed_to_unpacked_xx</key>
+    <param>
+      <key>id</key>
+      <value>p2u</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>byte</value>
+    </param>
+    <param>
+      <key>bits_per_chunk</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>endianness</key>
+      <value>gr.GR_MSB_FIRST</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(648, 415)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>gr_char_to_float</key>
+    <param>
+      <key>id</key>
+      <value>c2f</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(676, 483)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>audio_sink</key>
+    <param>
+      <key>id</key>
+      <value>audio_sink</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>device_name</key>
+      <value>plughw:0,0</value>
+    </param>
+    <param>
+      <key>ok_to_block</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1127, 340)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>8000</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(251, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>resample</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>8</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(344, 11)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable</key>
+    <param>
+      <key>id</key>
+      <value>bw</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(431, 11)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>notebook</key>
+    <param>
+      <key>id</key>
+      <value>displays</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.NB_TOP</value>
+    </param>
+    <param>
+      <key>labels</key>
+      <value>['Original','Encoded','Decoded']</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(12, 106)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_fftsink2</key>
+    <param>
+      <key>id</key>
+      <value>orig_fft</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Original Spectrum</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>baseband_freq</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>y_per_div</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>y_divs</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>ref_level</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>ref_scale</key>
+      <value>2.0</value>
+    </param>
+    <param>
+      <key>fft_size</key>
+      <value>1024</value>
+    </param>
+    <param>
+      <key>fft_rate</key>
+      <value>30</value>
+    </param>
+    <param>
+      <key>peak_hold</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>average</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>avg_alpha</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(415, 97)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>orig_scope</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Original Waveform</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(414, 425)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_fftsink2</key>
+    <param>
+      <key>id</key>
+      <value>enc_fft</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Encoded Spectrum</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate*resample</value>
+    </param>
+    <param>
+      <key>baseband_freq</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>y_per_div</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>y_divs</key>
+      <value>8</value>
+    </param>
+    <param>
+      <key>ref_level</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>ref_scale</key>
+      <value>2.0</value>
+    </param>
+    <param>
+      <key>fft_size</key>
+      <value>1024</value>
+    </param>
+    <param>
+      <key>fft_rate</key>
+      <value>30</value>
+    </param>
+    <param>
+      <key>peak_hold</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>average</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>avg_alpha</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(610, 551)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>enc_scope</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Encoded Waveform</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate*resample</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0.5</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>20.0/(audio_rate*resample)</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 1</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(858, 591)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_fftsink2</key>
+    <param>
+      <key>id</key>
+      <value>dec_fft</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Decoded Spectrum</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>baseband_freq</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>y_per_div</key>
+      <value>5</value>
+    </param>
+    <param>
+      <key>y_divs</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>ref_level</key>
+      <value>10</value>
+    </param>
+    <param>
+      <key>ref_scale</key>
+      <value>0.1</value>
+    </param>
+    <param>
+      <key>fft_size</key>
+      <value>1024</value>
+    </param>
+    <param>
+      <key>fft_rate</key>
+      <value>30</value>
+    </param>
+    <param>
+      <key>peak_hold</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>average</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>avg_alpha</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>0, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 2</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(891, 98)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>wxgui_scopesink2</key>
+    <param>
+      <key>id</key>
+      <value>dec_scope</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Decoded Waveform</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>audio_rate</value>
+    </param>
+    <param>
+      <key>v_scale</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>t_scale</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>ac_couple</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>xy_mode</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>num_inputs</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value>1, 0, 1, 1</value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value>displays, 2</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(889, 422)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
+  <block>
+    <key>options</key>
+    <param>
+      <key>id</key>
+      <value>cvsd_sweep</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>CVSD Vocoder Test</value>
+    </param>
+    <param>
+      <key>author</key>
+      <value></value>
+    </param>
+    <param>
+      <key>description</key>
+      <value></value>
+    </param>
+    <param>
+      <key>window_size</key>
+      <value>1280, 1024</value>
+    </param>
+    <param>
+      <key>generate_options</key>
+      <value>wx_gui</value>
+    </param>
+    <param>
+      <key>category</key>
+      <value>Custom</value>
+    </param>
+    <param>
+      <key>run</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(10, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <connection>
+    <source_block_id>vco</source_block_id>
+    <sink_block_id>orig_fft</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>tri_source</source_block_id>
+    <sink_block_id>throttle</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>throttle</source_block_id>
+    <sink_block_id>vco</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>vco</source_block_id>
+    <sink_block_id>enc</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>enc</source_block_id>
+    <sink_block_id>blks2_cvsd_decode_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>vco</source_block_id>
+    <sink_block_id>orig_scope</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blks2_cvsd_decode_0</source_block_id>
+    <sink_block_id>dec_fft</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blks2_cvsd_decode_0</source_block_id>
+    <sink_block_id>dec_scope</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blks2_cvsd_decode_0</source_block_id>
+    <sink_block_id>audio_sink</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>enc</source_block_id>
+    <sink_block_id>p2u</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>p2u</source_block_id>
+    <sink_block_id>c2f</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>c2f</source_block_id>
+    <sink_block_id>enc_fft</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>c2f</source_block_id>
+    <sink_block_id>enc_scope</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+</flow_graph>
index ff137f6697074b657ece3f5ab2d90ce6a2db2c50..ee3e19a6c6628db3d4e79ab1a4facd3e85bc8a8d 100644 (file)
@@ -30,9 +30,8 @@ from threading import Thread
 import Messages
 from .. base import ParseXML
 import random
-from Platform import Platform
 from MainWindow import MainWindow
-from ParamsDialog import ParamsDialog
+from PropsDialog import PropsDialog
 import Dialogs
 from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog
 
@@ -53,11 +52,10 @@ class ActionHandler:
                @param platform platform module
                """
                self.clipboard = None
-               platform = Platform(platform)
-               for action in Actions.get_all_actions(): action.connect('activate', self._handle_actions)
+               for action in Actions.get_all_actions(): action.connect('activate', self._handle_action)
                #setup the main window
-               self.main_window = MainWindow(self.handle_states, platform)
-               self.main_window.connect('delete_event', self._quit)
+               self.main_window = MainWindow(platform)
+               self.main_window.connect('delete-event', self._quit)
                self.main_window.connect('key-press-event', self._handle_key_press)
                self.get_page = self.main_window.get_page
                self.get_flow_graph = self.main_window.get_flow_graph
@@ -67,7 +65,7 @@ class ActionHandler:
                Messages.send_init(platform)
                #initialize
                self.init_file_paths = file_paths
-               self.handle_states(Actions.APPLICATION_INITIALIZE)
+               Actions.APPLICATION_INITIALIZE()
                #enter the mainloop
                gtk.main()
 
@@ -81,17 +79,9 @@ class ActionHandler:
                When not in focus, gtk and the accelerators handle the the key press.
                @return false to let gtk handle the key action
                """
-               #dont allow key presses to queue up
-               if gtk.events_pending(): return True
-               #extract action name from this key press
-               key_name = gtk.gdk.keyval_name(event.keyval)
-               mod_mask = event.state
-               action_name = Actions.get_action_name_from_key_name(key_name, mod_mask)
-               #handle the action if flow graph is in focus
-               if action_name and self.get_focus_flag():
-                       self.handle_states(action_name)
-                       return True #handled by this method
-               return False #let gtk handle the key press
+               try: assert self.get_focus_flag()
+               except AssertionError: return False
+               return Actions.handle_key_press(event)
 
        def _quit(self, window, event):
                """
@@ -100,41 +90,24 @@ class ActionHandler:
                This method in turns calls the state handler to quit.
                @return true
                """
-               self.handle_states(Actions.APPLICATION_QUIT)
+               Actions.APPLICATION_QUIT()
                return True
 
-       def _handle_actions(self, event):
-               """
-               Handle all of the activate signals from the gtk actions.
-               The action signals derive from clicking on a toolbar or menu bar button.
-               Forward the action to the state handler.
-               """
-               self.handle_states(event.get_name())
-
-       def handle_states(self, state=''):
-               """
-               Handle the state changes in the GUI.
-               Handle all of the state changes that arise from the action handler or other gui and
-               inputs in the application. The state passed to the handle_states method is a string descriping
-               the change. A series of if/elif statements handle the state by greying out action buttons, causing
-               changes in the flow graph, saving/opening files... The handle_states method is passed to the
-               contructors of many of the classes used in this application enabling them to report any state change.
-               @param state a string describing the state change
-               """
-               #print state
+       def _handle_action(self, action):
+               #print action
                ##################################################
                # Initalize/Quit
                ##################################################
-               if state == Actions.APPLICATION_INITIALIZE:
+               if action == Actions.APPLICATION_INITIALIZE:
                        for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled
-                       # enable a select few actions
+                       #enable a select few actions
                        for action in (
                                Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW,
                                Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS,
                                Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY,
                                Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY,
-                               Actions.COLORS_WINDOW_DISPLAY,
-                       ): Actions.get_action_from_name(action).set_sensitive(True)
+                               Actions.TYPES_WINDOW_DISPLAY,
+                       ): action.set_sensitive(True)
                        if not self.init_file_paths:
                                self.init_file_paths = Preferences.files_open()
                        if not self.init_file_paths: self.init_file_paths = ['']
@@ -143,26 +116,26 @@ class ActionHandler:
                        if Preferences.file_open() in self.init_file_paths:
                                self.main_window.new_page(Preferences.file_open(), show=True)
                        if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists
-               elif state == Actions.APPLICATION_QUIT:
+               elif action == Actions.APPLICATION_QUIT:
                        if self.main_window.close_pages():
                                gtk.main_quit()
                                exit(0)
                ##################################################
                # Selections
                ##################################################
-               elif state == Actions.ELEMENT_SELECT:
+               elif action == Actions.ELEMENT_SELECT:
                        pass #do nothing, update routines below
-               elif state == Actions.NOTHING_SELECT:
+               elif action == Actions.NOTHING_SELECT:
                        self.get_flow_graph().unselect()
                ##################################################
                # Enable/Disable
                ##################################################
-               elif state == Actions.BLOCK_ENABLE:
+               elif action == Actions.BLOCK_ENABLE:
                        if self.get_flow_graph().enable_selected(True):
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
-               elif state == Actions.BLOCK_DISABLE:
+               elif action == Actions.BLOCK_DISABLE:
                        if self.get_flow_graph().enable_selected(False):
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
@@ -170,12 +143,12 @@ class ActionHandler:
                ##################################################
                # Cut/Copy/Paste
                ##################################################
-               elif state == Actions.BLOCK_CUT:
-                       self.handle_states(Actions.BLOCK_COPY)
-                       self.handle_states(Actions.ELEMENT_DELETE)
-               elif state == Actions.BLOCK_COPY:
+               elif action == Actions.BLOCK_CUT:
+                       Actions.BLOCK_COPY()
+                       Actions.ELEMENT_DELETE()
+               elif action == Actions.BLOCK_COPY:
                        self.clipboard = self.get_flow_graph().copy_to_clipboard()
-               elif state == Actions.BLOCK_PASTE:
+               elif action == Actions.BLOCK_PASTE:
                        if self.clipboard:
                                self.get_flow_graph().paste_from_clipboard(self.clipboard)
                                self.get_flow_graph().update()
@@ -184,81 +157,88 @@ class ActionHandler:
                ##################################################
                # Move/Rotate/Delete/Create
                ##################################################
-               elif state == Actions.BLOCK_MOVE:
+               elif action == Actions.BLOCK_MOVE:
                        self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                        self.get_page().set_saved(False)
-               elif state == Actions.BLOCK_ROTATE_CCW:
+               elif action == Actions.BLOCK_ROTATE_CCW:
                        if self.get_flow_graph().rotate_selected(90):
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
-               elif state == Actions.BLOCK_ROTATE_CW:
+               elif action == Actions.BLOCK_ROTATE_CW:
                        if self.get_flow_graph().rotate_selected(-90):
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
-               elif state == Actions.ELEMENT_DELETE:
+               elif action == Actions.ELEMENT_DELETE:
                        if self.get_flow_graph().remove_selected():
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
-                               self.handle_states(Actions.NOTHING_SELECT)
+                               Actions.NOTHING_SELECT()
                                self.get_page().set_saved(False)
-               elif state == Actions.ELEMENT_CREATE:
+               elif action == Actions.ELEMENT_CREATE:
                        self.get_flow_graph().update()
                        self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
-                       self.handle_states(Actions.NOTHING_SELECT)
+                       Actions.NOTHING_SELECT()
                        self.get_page().set_saved(False)
-               elif state == Actions.BLOCK_INC_TYPE:
+               elif action == Actions.BLOCK_INC_TYPE:
                        if self.get_flow_graph().type_controller_modify_selected(1):
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
-               elif state == Actions.BLOCK_DEC_TYPE:
+               elif action == Actions.BLOCK_DEC_TYPE:
                        if self.get_flow_graph().type_controller_modify_selected(-1):
                                self.get_flow_graph().update()
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
-               elif state == Actions.PORT_CONTROLLER_INC:
+               elif action == Actions.PORT_CONTROLLER_INC:
                        if self.get_flow_graph().port_controller_modify_selected(1):
                                self.get_flow_graph().update()
-                               self.get_flow_graph().update() #2 times
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
-               elif state == Actions.PORT_CONTROLLER_DEC:
+               elif action == Actions.PORT_CONTROLLER_DEC:
                        if self.get_flow_graph().port_controller_modify_selected(-1):
                                self.get_flow_graph().update()
-                               self.get_flow_graph().update() #2 times
                                self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
                                self.get_page().set_saved(False)
                ##################################################
                # Window stuff
                ##################################################
-               elif state == Actions.ABOUT_WINDOW_DISPLAY:
+               elif action == Actions.ABOUT_WINDOW_DISPLAY:
                        Dialogs.AboutDialog(self.get_flow_graph().get_parent())
-               elif state == Actions.HELP_WINDOW_DISPLAY:
+               elif action == Actions.HELP_WINDOW_DISPLAY:
                        Dialogs.HelpDialog()
-               elif state == Actions.COLORS_WINDOW_DISPLAY:
-                       Dialogs.ColorsDialog(self.get_flow_graph().get_parent())
+               elif action == Actions.TYPES_WINDOW_DISPLAY:
+                       Dialogs.TypesDialog(self.get_flow_graph().get_parent())
+               elif action == Actions.ERRORS_WINDOW_DISPLAY:
+                       Dialogs.ErrorsDialog(self.get_flow_graph())
                ##################################################
                # Param Modifications
                ##################################################
-               elif state == Actions.BLOCK_PARAM_MODIFY:
+               elif action == Actions.BLOCK_PARAM_MODIFY:
                        selected_block = self.get_flow_graph().get_selected_block()
-                       if selected_block and ParamsDialog(selected_block).run():
-                               self.get_flow_graph().update()
-                               self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
-                               self.get_page().set_saved(False)
+                       if selected_block:
+                               if PropsDialog(selected_block).run():
+                                       #save the new state
+                                       self.get_flow_graph().update()
+                                       self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+                                       self.get_page().set_saved(False)
+                               else:
+                                       #restore the current state
+                                       n = self.get_page().get_state_cache().get_current_state()
+                                       self.get_flow_graph().import_data(n)
+                                       self.get_flow_graph().update()
                ##################################################
                # Undo/Redo
                ##################################################
-               elif state == Actions.FLOW_GRAPH_UNDO:
+               elif action == Actions.FLOW_GRAPH_UNDO:
                        n = self.get_page().get_state_cache().get_prev_state()
                        if n:
                                self.get_flow_graph().unselect()
                                self.get_flow_graph().import_data(n)
                                self.get_flow_graph().update()
                                self.get_page().set_saved(False)
-               elif state == Actions.FLOW_GRAPH_REDO:
+               elif action == Actions.FLOW_GRAPH_REDO:
                        n = self.get_page().get_state_cache().get_next_state()
                        if n:
                                self.get_flow_graph().unselect()
@@ -268,19 +248,19 @@ class ActionHandler:
                ##################################################
                # New/Open/Save/Close
                ##################################################
-               elif state == Actions.FLOW_GRAPH_NEW:
+               elif action == Actions.FLOW_GRAPH_NEW:
                        self.main_window.new_page()
-               elif state == Actions.FLOW_GRAPH_OPEN:
+               elif action == Actions.FLOW_GRAPH_OPEN:
                        file_paths = OpenFlowGraphFileDialog(self.get_page().get_file_path()).run()
                        if file_paths: #open a new page for each file, show only the first
                                for i,file_path in enumerate(file_paths):
                                        self.main_window.new_page(file_path, show=(i==0))
-               elif state == Actions.FLOW_GRAPH_CLOSE:
+               elif action == Actions.FLOW_GRAPH_CLOSE:
                        self.main_window.close_page()
-               elif state == Actions.FLOW_GRAPH_SAVE:
+               elif action == Actions.FLOW_GRAPH_SAVE:
                        #read-only or undefined file path, do save-as
                        if self.get_page().get_read_only() or not self.get_page().get_file_path():
-                               self.handle_states(Actions.FLOW_GRAPH_SAVE_AS)
+                               Actions.FLOW_GRAPH_SAVE_AS()
                        #otherwise try to save
                        else:
                                try:
@@ -289,12 +269,12 @@ class ActionHandler:
                                except IOError:
                                        Messages.send_fail_save(self.get_page().get_file_path())
                                        self.get_page().set_saved(False)
-               elif state == Actions.FLOW_GRAPH_SAVE_AS:
+               elif action == Actions.FLOW_GRAPH_SAVE_AS:
                        file_path = SaveFlowGraphFileDialog(self.get_page().get_file_path()).run()
                        if file_path is not None:
                                self.get_page().set_file_path(file_path)
-                               self.handle_states(Actions.FLOW_GRAPH_SAVE)
-               elif state == Actions.FLOW_GRAPH_SCREEN_CAPTURE:
+                               Actions.FLOW_GRAPH_SAVE()
+               elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE:
                        file_path = SaveImageFileDialog(self.get_page().get_file_path()).run()
                        if file_path is not None:
                                pixbuf = self.get_flow_graph().get_drawing_area().get_pixbuf()
@@ -302,10 +282,10 @@ class ActionHandler:
                ##################################################
                # Gen/Exec/Stop
                ##################################################
-               elif state == Actions.FLOW_GRAPH_GEN:
+               elif action == Actions.FLOW_GRAPH_GEN:
                        if not self.get_page().get_pid():
                                if not self.get_page().get_saved() or not self.get_page().get_file_path():
-                                       self.handle_states(Actions.FLOW_GRAPH_SAVE) #only save if file path missing or not saved
+                                       Actions.FLOW_GRAPH_SAVE() #only save if file path missing or not saved
                                if self.get_page().get_saved() and self.get_page().get_file_path():
                                        generator = self.get_page().get_generator()
                                        try:
@@ -313,37 +293,38 @@ class ActionHandler:
                                                generator.write()
                                        except Exception,e: Messages.send_fail_gen(e)
                                else: self.generator = None
-               elif state == Actions.FLOW_GRAPH_EXEC:
+               elif action == Actions.FLOW_GRAPH_EXEC:
                        if not self.get_page().get_pid():
-                               self.handle_states(Actions.FLOW_GRAPH_GEN)
+                               Actions.FLOW_GRAPH_GEN()
                                if self.get_page().get_saved() and self.get_page().get_file_path():
                                        ExecFlowGraphThread(self)
-               elif state == Actions.FLOW_GRAPH_KILL:
+               elif action == Actions.FLOW_GRAPH_KILL:
                        if self.get_page().get_pid():
                                try: os.kill(self.get_page().get_pid(), signal.SIGKILL)
                                except: print "could not kill pid: %s"%self.get_page().get_pid()
-               elif state == '': #pass and run the global actions
+               elif action == Actions.PAGE_CHANGE: #pass and run the global actions
                        pass
-               else: print '!!! State "%s" not handled !!!'%state
+               else: print '!!! Action "%s" not handled !!!'%action
                ##################################################
                # Global Actions for all States
                ##################################################
                #update general buttons
-               Actions.get_action_from_name(Actions.ELEMENT_DELETE).set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
-               Actions.get_action_from_name(Actions.BLOCK_PARAM_MODIFY).set_sensitive(bool(self.get_flow_graph().get_selected_block()))
-               Actions.get_action_from_name(Actions.BLOCK_ROTATE_CCW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-               Actions.get_action_from_name(Actions.BLOCK_ROTATE_CW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+               Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not self.get_flow_graph().is_valid())
+               Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
+               Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block()))
+               Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+               Actions.BLOCK_ROTATE_CW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
                #update cut/copy/paste
-               Actions.get_action_from_name(Actions.BLOCK_CUT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-               Actions.get_action_from_name(Actions.BLOCK_COPY).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-               Actions.get_action_from_name(Actions.BLOCK_PASTE).set_sensitive(bool(self.clipboard))
+               Actions.BLOCK_CUT.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+               Actions.BLOCK_COPY.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+               Actions.BLOCK_PASTE.set_sensitive(bool(self.clipboard))
                #update enable/disable
-               Actions.get_action_from_name(Actions.BLOCK_ENABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-               Actions.get_action_from_name(Actions.BLOCK_DISABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+               Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+               Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
                #set the exec and stop buttons
                self.update_exec_stop()
                #saved status
-               Actions.get_action_from_name(Actions.FLOW_GRAPH_SAVE).set_sensitive(not self.get_page().get_saved())
+               Actions.FLOW_GRAPH_SAVE.set_sensitive(not self.get_page().get_saved())
                self.main_window.update()
                try: #set the size of the flow graph area (if changed)
                        new_size = self.get_flow_graph().get_option('window_size')
@@ -353,6 +334,7 @@ class ActionHandler:
                #draw the flow graph
                self.get_flow_graph().update_selected()
                self.get_flow_graph().queue_draw()
+               return True #action was handled
 
        def update_exec_stop(self):
                """
@@ -360,9 +342,9 @@ class ActionHandler:
                Lock and unlock the mutex for race conditions with exec flow graph threads.
                """
                sensitive = self.get_flow_graph().is_valid() and not self.get_page().get_pid()
-               Actions.get_action_from_name(Actions.FLOW_GRAPH_GEN).set_sensitive(sensitive)
-               Actions.get_action_from_name(Actions.FLOW_GRAPH_EXEC).set_sensitive(sensitive)
-               Actions.get_action_from_name(Actions.FLOW_GRAPH_KILL).set_sensitive(self.get_page().get_pid() != None)
+               Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive)
+               Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive)
+               Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_pid() != None)
 
 class ExecFlowGraphThread(Thread):
        """Execute the flow graph as a new process and wait on it to finish."""
index 3695e09ef3d7abdddc7b178d132099f83f46e92d..f374efde18d9e5d8d9ec6cbd2e814322e583ce96 100644 (file)
@@ -21,149 +21,254 @@ import pygtk
 pygtk.require('2.0')
 import gtk
 
-######################################################################################################
-# Action Names
-######################################################################################################
-APPLICATION_INITIALIZE = 'app init'
-APPLICATION_QUIT = 'app quit'
-PARAM_MODIFY = 'param modify'
-BLOCK_MOVE = 'block move'
-BLOCK_ROTATE_CCW = 'block rotate ccw'
-BLOCK_ROTATE_CW = 'block rotate cw'
-BLOCK_PARAM_MODIFY = 'block param modify'
-BLOCK_INC_TYPE = 'block increment type'
-BLOCK_DEC_TYPE = 'block decrement type'
-BLOCK_ENABLE = 'block enable'
-BLOCK_DISABLE = 'block disable'
-BLOCK_CUT = 'block cut'
-BLOCK_COPY = 'block copy'
-BLOCK_PASTE = 'block paste'
-PORT_CONTROLLER_INC = 'port controller increment'
-PORT_CONTROLLER_DEC = 'port controller decrement'
-ELEMENT_CREATE = 'element create'
-ELEMENT_DELETE = 'element delete'
-ELEMENT_SELECT = 'element select'
-NOTHING_SELECT = 'nothing select'
-FLOW_GRAPH_OPEN = 'flow graph open'
-FLOW_GRAPH_UNDO = 'flow graph undo'
-FLOW_GRAPH_REDO = 'flow graph redo'
-FLOW_GRAPH_SAVE = 'flow graph save'
-FLOW_GRAPH_SAVE_AS = 'flow graph save as'
-FLOW_GRAPH_CLOSE = 'flow graph close'
-FLOW_GRAPH_NEW = 'flow graph new'
-FLOW_GRAPH_GEN = 'flow graph gen'
-FLOW_GRAPH_EXEC = 'flow graph exec'
-FLOW_GRAPH_KILL = 'flow graph kill'
-FLOW_GRAPH_SCREEN_CAPTURE = 'flow graph screen capture'
-ABOUT_WINDOW_DISPLAY = 'about window display'
-HELP_WINDOW_DISPLAY = 'help window display'
-COLORS_WINDOW_DISPLAY = 'colors window display'
+NO_MODS_MASK = 0
 
-######################################################################################################
-# Action Key Map
-######################################################################################################
-_actions_key_list = (
-       #action name, key name, mod mask
-       (FLOW_GRAPH_NEW, 'n', gtk.gdk.CONTROL_MASK),
-       (FLOW_GRAPH_OPEN, 'o', gtk.gdk.CONTROL_MASK),
-       (FLOW_GRAPH_SAVE, 's', gtk.gdk.CONTROL_MASK),
-       (FLOW_GRAPH_SAVE_AS, 's', gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK),
-       (FLOW_GRAPH_CLOSE, 'w', gtk.gdk.CONTROL_MASK),
-       (APPLICATION_QUIT, 'q', gtk.gdk.CONTROL_MASK),
-       (FLOW_GRAPH_UNDO, 'z', gtk.gdk.CONTROL_MASK),
-       (FLOW_GRAPH_REDO, 'y', gtk.gdk.CONTROL_MASK),
-       (ELEMENT_DELETE, 'Delete', 0),
-       (BLOCK_ROTATE_CCW, 'Left', 0),
-       (BLOCK_ROTATE_CW, 'Right', 0),
-       (BLOCK_DEC_TYPE, 'Up', 0),
-       (BLOCK_INC_TYPE, 'Down', 0),
-       (BLOCK_PARAM_MODIFY, 'Return', 0),
-       (BLOCK_ENABLE, 'e', 0),
-       (BLOCK_DISABLE, 'd', 0),
-       (BLOCK_CUT, 'x', gtk.gdk.CONTROL_MASK),
-       (BLOCK_COPY, 'c', gtk.gdk.CONTROL_MASK),
-       (BLOCK_PASTE, 'v', gtk.gdk.CONTROL_MASK),
-       (FLOW_GRAPH_GEN, 'F5', 0),
-       (FLOW_GRAPH_EXEC, 'F6', 0),
-       (FLOW_GRAPH_KILL, 'F7', 0),
-       (FLOW_GRAPH_SCREEN_CAPTURE, 'Print', 0),
-       (HELP_WINDOW_DISPLAY, 'F1', 0),
-       #the following have no associated gtk.Action
-       (PORT_CONTROLLER_INC, 'equal', 0),
-       (PORT_CONTROLLER_INC, 'plus', 0),
-       (PORT_CONTROLLER_INC, 'KP_Add', 0),
-       (PORT_CONTROLLER_DEC, 'minus', 0),
-       (PORT_CONTROLLER_DEC, 'KP_Subtract', 0),
-)
-
-_actions_key_dict = dict(((key_name, mod_mask), action_name) for action_name, key_name, mod_mask in _actions_key_list)
-def get_action_name_from_key_name(key_name, mod_mask=0):
+########################################################################
+# Actions API
+########################################################################
+_actions_keypress_dict = dict()
+_keymap = gtk.gdk.keymap_get_default()
+_used_mods_mask = NO_MODS_MASK
+def handle_key_press(event):
        """
-       Get the action name associated with the key name and mask.
-       Both keyname and mask have to match.
-       @param key_name the name of the key
-       @param mod_mask the key press mask (shift, ctrl) 0 for none
-       @return the action name or blank string
+       Call the action associated with the key press event.
+       Both the key value and the mask must have a match.
+       @param event a gtk key press event
+       @return true if handled
        """
-       key_name_mod_mask = (key_name, mod_mask)
-       if key_name_mod_mask in _actions_key_dict: return _actions_key_dict[key_name_mod_mask]
-       return ''
+       _used_mods_mask = reduce(lambda x, y: x | y, [mod_mask for keyval, mod_mask in _actions_keypress_dict], NO_MODS_MASK)
+       #extract the key value and the consumed modifiers
+       keyval, egroup, level, consumed = _keymap.translate_keyboard_state(
+               event.hardware_keycode, event.state, event.group)
+       #get the modifier mask and ignore irrelevant modifiers
+       mod_mask = event.state & ~consumed & _used_mods_mask
+       #look up the keypress and call the action
+       try: _actions_keypress_dict[(keyval, mod_mask)]()
+       except KeyError: return False #not handled
+       return True #handled here
 
-######################################################################################################
-# Actions
-######################################################################################################
-_actions_list = (
-       gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', gtk.STOCK_NEW),
-       gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', gtk.STOCK_OPEN),
-       gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', gtk.STOCK_SAVE),
-       gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', gtk.STOCK_SAVE_AS),
-       gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', gtk.STOCK_CLOSE),
-       gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', gtk.STOCK_QUIT),
-       gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', gtk.STOCK_UNDO),
-       gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', gtk.STOCK_REDO),
-       gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', gtk.STOCK_DELETE),
-       gtk.Action(BLOCK_ROTATE_CCW, 'Rotate Counterclockwise', 'Rotate the selected blocks 90 degrees to the left', gtk.STOCK_GO_BACK),
-       gtk.Action(BLOCK_ROTATE_CW, 'Rotate Clockwise', 'Rotate the selected blocks 90 degrees to the right', gtk.STOCK_GO_FORWARD),
-       gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', gtk.STOCK_PROPERTIES),
-       gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', gtk.STOCK_CONNECT),
-       gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', gtk.STOCK_DISCONNECT),
-       gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', gtk.STOCK_CUT),
-       gtk.Action(BLOCK_COPY, '_Copy', 'Copy', gtk.STOCK_COPY),
-       gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', gtk.STOCK_PASTE),
-       gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', gtk.STOCK_ABOUT),
-       gtk.Action(HELP_WINDOW_DISPLAY, '_Help', 'Usage Tips', gtk.STOCK_HELP),
-       gtk.Action(COLORS_WINDOW_DISPLAY, '_Colors', 'Color Mapping', gtk.STOCK_DIALOG_INFO),
-       gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', gtk.STOCK_CONVERT),
-       gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', gtk.STOCK_EXECUTE),
-       gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', gtk.STOCK_STOP),
-       gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', gtk.STOCK_PRINT),
-)
-def get_all_actions(): return _actions_list
+_all_actions_list = list()
+def get_all_actions(): return _all_actions_list
+
+_accel_group = gtk.AccelGroup()
+def get_accel_group(): return _accel_group
 
-_actions_dict = dict((action.get_name(), action) for action in _actions_list)
-def get_action_from_name(action_name):
+class Action(gtk.Action):
        """
-       Retrieve the action from the action list.
-       Search the list and find an action with said name.
-       @param action_name the action name(string)
-       @throw KeyError bad action name
-       @return a gtk action object
+       A custom Action class based on gtk.Action.
+       Pass additional arguments such as keypresses.
+       Register actions and keypresses with this module.
        """
-       if action_name in _actions_dict: return _actions_dict[action_name]
-       raise KeyError('Action Name: "%s" does not exist'%action_name)
 
-######################################################################################################
-# Accelerators
-######################################################################################################
-_accel_group = gtk.AccelGroup()
-def get_accel_group(): return _accel_group
+       def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None):
+               """
+               Create a new Action instance.
+               @param key_presses a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...)
+               @param the regular gtk.Action parameters (defaults to None)
+               """
+               if name is None: name = label
+               gtk.Action.__init__(self,
+                       name=name, label=label,
+                       tooltip=tooltip, stock_id=stock_id,
+               )
+               #register this action
+               _all_actions_list.append(self)
+               for i in range(len(keypresses)/2):
+                       keyval, mod_mask = keypresses[i*2:(i+1)*2]
+                       #register this keypress
+                       assert not _actions_keypress_dict.has_key((keyval, mod_mask))
+                       _actions_keypress_dict[(keyval, mod_mask)] = self
+                       #set the accelerator group, and accelerator path
+                       #register the key name and mod mask with the accelerator path
+                       if label is None: continue #dont register accel
+                       accel_path = '<main>/'+self.get_name()
+                       self.set_accel_group(get_accel_group())
+                       self.set_accel_path(accel_path)
+                       gtk.accel_map_add_entry(accel_path, keyval, mod_mask)
+
+       def __str__(self):
+               """
+               The string representation should be the name of the action id.
+               Try to find the action id for this action by searching this module.
+               """
+               try:
+                       import Actions
+                       return filter(lambda attr: getattr(Actions, attr) == self, dir(Actions))[0]
+               except: return self.get_name()
+
+       def __repr__(self): return str(self)
+
+       def __call__(self):
+               """
+               Emit the activate signal when called with ().
+               """
+               self.emit('activate')
 
-#set the accelerator group, and accelerator path
-#register the key name and mod mask with the accelerator path
-for action_name, key_name, mod_mask in _actions_key_list:
-       try:
-               accel_path = '<main>/'+action_name
-               get_action_from_name(action_name).set_accel_group(get_accel_group())
-               get_action_from_name(action_name).set_accel_path(accel_path)
-               gtk.accel_map_add_entry(accel_path, gtk.gdk.keyval_from_name(key_name), mod_mask)
-       except KeyError: pass #no action was created for this action name
+########################################################################
+# Actions
+########################################################################
+PAGE_CHANGE = Action()
+FLOW_GRAPH_NEW = Action(
+       label='_New',
+       tooltip='Create a new flow graph',
+       stock_id=gtk.STOCK_NEW,
+       keypresses=(gtk.keysyms.n, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_OPEN = Action(
+       label='_Open',
+       tooltip='Open an existing flow graph',
+       stock_id=gtk.STOCK_OPEN,
+       keypresses=(gtk.keysyms.o, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_SAVE = Action(
+       label='_Save',
+       tooltip='Save the current flow graph',
+       stock_id=gtk.STOCK_SAVE,
+       keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_SAVE_AS = Action(
+       label='Save _As',
+       tooltip='Save the current flow graph as...',
+       stock_id=gtk.STOCK_SAVE_AS,
+       keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK),
+)
+FLOW_GRAPH_CLOSE = Action(
+       label='_Close',
+       tooltip='Close the current flow graph',
+       stock_id=gtk.STOCK_CLOSE,
+       keypresses=(gtk.keysyms.w, gtk.gdk.CONTROL_MASK),
+)
+APPLICATION_INITIALIZE = Action()
+APPLICATION_QUIT = Action(
+       label='_Quit',
+       tooltip='Quit program',
+       stock_id=gtk.STOCK_QUIT,
+       keypresses=(gtk.keysyms.q, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_UNDO = Action(
+       label='_Undo',
+       tooltip='Undo a change to the flow graph',
+       stock_id=gtk.STOCK_UNDO,
+       keypresses=(gtk.keysyms.z, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_REDO = Action(
+       label='_Redo',
+       tooltip='Redo a change to the flow graph',
+       stock_id=gtk.STOCK_REDO,
+       keypresses=(gtk.keysyms.y, gtk.gdk.CONTROL_MASK),
+)
+NOTHING_SELECT = Action()
+ELEMENT_SELECT = Action()
+ELEMENT_CREATE = Action()
+ELEMENT_DELETE = Action(
+       label='_Delete',
+       tooltip='Delete the selected blocks',
+       stock_id=gtk.STOCK_DELETE,
+       keypresses=(gtk.keysyms.Delete, NO_MODS_MASK),
+)
+BLOCK_MOVE = Action()
+BLOCK_ROTATE_CCW = Action(
+       label='Rotate Counterclockwise',
+       tooltip='Rotate the selected blocks 90 degrees to the left',
+       stock_id=gtk.STOCK_GO_BACK,
+       keypresses=(gtk.keysyms.Left, NO_MODS_MASK),
+)
+BLOCK_ROTATE_CW = Action(
+       label='Rotate Clockwise',
+       tooltip='Rotate the selected blocks 90 degrees to the right',
+       stock_id=gtk.STOCK_GO_FORWARD,
+       keypresses=(gtk.keysyms.Right, NO_MODS_MASK),
+)
+BLOCK_PARAM_MODIFY = Action(
+       label='_Properties',
+       tooltip='Modify params for the selected block',
+       stock_id=gtk.STOCK_PROPERTIES,
+       keypresses=(gtk.keysyms.Return, NO_MODS_MASK),
+)
+BLOCK_ENABLE = Action(
+       label='E_nable',
+       tooltip='Enable the selected blocks',
+       stock_id=gtk.STOCK_CONNECT,
+       keypresses=(gtk.keysyms.e, NO_MODS_MASK),
+)
+BLOCK_DISABLE = Action(
+       label='D_isable',
+       tooltip='Disable the selected blocks',
+       stock_id=gtk.STOCK_DISCONNECT,
+       keypresses=(gtk.keysyms.d, NO_MODS_MASK),
+)
+BLOCK_CUT = Action(
+       label='Cu_t',
+       tooltip='Cut',
+       stock_id=gtk.STOCK_CUT,
+       keypresses=(gtk.keysyms.x, gtk.gdk.CONTROL_MASK),
+)
+BLOCK_COPY = Action(
+       label='_Copy',
+       tooltip='Copy',
+       stock_id=gtk.STOCK_COPY,
+       keypresses=(gtk.keysyms.c, gtk.gdk.CONTROL_MASK),
+)
+BLOCK_PASTE = Action(
+       label='_Paste',
+       tooltip='Paste',
+       stock_id=gtk.STOCK_PASTE,
+       keypresses=(gtk.keysyms.v, gtk.gdk.CONTROL_MASK),
+)
+ERRORS_WINDOW_DISPLAY = Action(
+       label='_Errors',
+       tooltip='View flow graph errors',
+       stock_id=gtk.STOCK_DIALOG_ERROR,
+)
+ABOUT_WINDOW_DISPLAY = Action(
+       label='_About',
+       tooltip='About this program',
+       stock_id=gtk.STOCK_ABOUT,
+)
+HELP_WINDOW_DISPLAY = Action(
+       label='_Help',
+       tooltip='Usage tips',
+       stock_id=gtk.STOCK_HELP,
+       keypresses=(gtk.keysyms.F1, NO_MODS_MASK),
+)
+TYPES_WINDOW_DISPLAY = Action(
+       label='_Types',
+       tooltip='Types color mapping',
+       stock_id=gtk.STOCK_DIALOG_INFO,
+)
+FLOW_GRAPH_GEN = Action(
+       label='_Generate',
+       tooltip='Generate the flow graph',
+       stock_id=gtk.STOCK_CONVERT,
+       keypresses=(gtk.keysyms.F5, NO_MODS_MASK),
+)
+FLOW_GRAPH_EXEC = Action(
+       label='_Execute',
+       tooltip='Execute the flow graph',
+       stock_id=gtk.STOCK_EXECUTE,
+       keypresses=(gtk.keysyms.F6, NO_MODS_MASK),
+)
+FLOW_GRAPH_KILL = Action(
+       label='_Kill',
+       tooltip='Kill the flow graph',
+       stock_id=gtk.STOCK_STOP,
+       keypresses=(gtk.keysyms.F7, NO_MODS_MASK),
+)
+FLOW_GRAPH_SCREEN_CAPTURE = Action(
+       label='S_creen Capture',
+       tooltip='Create a screen capture of the flow graph',
+       stock_id=gtk.STOCK_PRINT,
+       keypresses=(gtk.keysyms.Print, NO_MODS_MASK),
+)
+PORT_CONTROLLER_DEC = Action(
+       keypresses=(gtk.keysyms.minus, NO_MODS_MASK, gtk.keysyms.KP_Subtract, NO_MODS_MASK),
+)
+PORT_CONTROLLER_INC = Action(
+       keypresses=(gtk.keysyms.plus, NO_MODS_MASK, gtk.keysyms.KP_Add, NO_MODS_MASK),
+)
+BLOCK_INC_TYPE = Action(
+       keypresses=(gtk.keysyms.Down, NO_MODS_MASK),
+)
+BLOCK_DEC_TYPE = Action(
+       keypresses=(gtk.keysyms.Up, NO_MODS_MASK),
+)
index e0c547eba5348af90130848d0c4b737aff961cdf..8fd167869828f163d619b271441b6a60bd9c5d93 100644 (file)
@@ -39,6 +39,7 @@ TOOLBAR_LIST = (
        Actions.FLOW_GRAPH_UNDO,
        Actions.FLOW_GRAPH_REDO,
        None,
+       Actions.ERRORS_WINDOW_DISPLAY,
        Actions.FLOW_GRAPH_GEN,
        Actions.FLOW_GRAPH_EXEC,
        Actions.FLOW_GRAPH_KILL,
@@ -81,6 +82,9 @@ MENU_BAR_LIST = (
                None,
                Actions.BLOCK_PARAM_MODIFY,
        ]),
+       (gtk.Action('View', '_View', None, None), [
+               Actions.ERRORS_WINDOW_DISPLAY,
+       ]),
        (gtk.Action('Build', '_Build', None, None), [
                Actions.FLOW_GRAPH_GEN,
                Actions.FLOW_GRAPH_EXEC,
@@ -88,7 +92,7 @@ MENU_BAR_LIST = (
        ]),
        (gtk.Action('Help', '_Help', None, None), [
                Actions.HELP_WINDOW_DISPLAY,
-               Actions.COLORS_WINDOW_DISPLAY,
+               Actions.TYPES_WINDOW_DISPLAY,
                None,
                Actions.ABOUT_WINDOW_DISPLAY,
        ]),
@@ -104,9 +108,8 @@ class Toolbar(gtk.Toolbar):
                """
                gtk.Toolbar.__init__(self)
                self.set_style(gtk.TOOLBAR_ICONS)
-               for action_name in TOOLBAR_LIST:
-                       if action_name: #add a tool item
-                               action = Actions.get_action_from_name(action_name)
+               for action in TOOLBAR_LIST:
+                       if action: #add a tool item
                                self.add(action.create_tool_item())
                                #this reset of the tooltip property is required (after creating the tool item) for the tooltip to show
                                action.set_property('tooltip', action.get_property('tooltip'))
@@ -123,16 +126,15 @@ class MenuBar(gtk.MenuBar):
                Add the submenu to the menu bar.
                """
                gtk.MenuBar.__init__(self)
-               for main_action,action_names in MENU_BAR_LIST:
+               for main_action, actions in MENU_BAR_LIST:
                        #create the main menu item
                        main_menu_item = main_action.create_menu_item()
                        self.append(main_menu_item)
                        #create the menu
                        main_menu = gtk.Menu()
                        main_menu_item.set_submenu(main_menu)
-                       for action_name in action_names:
-                               if action_name: #append a menu item
-                                       action = Actions.get_action_from_name(action_name)
+                       for action in actions:
+                               if action: #append a menu item
                                        main_menu.append(action.create_menu_item())
                                else: main_menu.append(gtk.SeparatorMenuItem())
                        main_menu.show_all() #this show all is required for the separators to show
index 4add3aa195f9db8d34cd46c09104fd7bf78d2467..8c65bf06f104a2dd347856460d347775c813ff9f 100644 (file)
@@ -37,15 +37,15 @@ BLOCK_MARKUP_TMPL="""\
 class Block(Element):
        """The graphical signal block."""
 
-       def __init__(self, *args, **kwargs):
+       def __init__(self):
                """
                Block contructor.
                Add graphics related params to the block.
                """
                #add the position param
                self.get_params().append(self.get_parent().get_parent().Param(
-                       self,
-                       odict({
+                       block=self,
+                       n=odict({
                                'name': 'GUI Coordinate',
                                'key': '_coordinate',
                                'type': 'raw',
@@ -54,8 +54,8 @@ class Block(Element):
                        })
                ))
                self.get_params().append(self.get_parent().get_parent().Param(
-                       self,
-                       odict({
+                       block=self,
+                       n=odict({
                                'name': 'GUI Rotation',
                                'key': '_rotation',
                                'type': 'raw',
@@ -113,23 +113,16 @@ class Block(Element):
                """
                self.get_param('_rotation').set_value(str(rot))
 
-       def update(self):
+       def create_shapes(self):
                """Update the block, parameters, and ports when a change occurs."""
-               self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
-               self.clear()
-               self._create_labels()
-               self.W = self.label_width + 2*BLOCK_LABEL_PADDING
-               self.H = max(*(
-                       [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
-                       sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
-                       for ports in (self.get_sources(), self.get_sinks())]
-               ))
+               Element.create_shapes(self)
                if self.is_horizontal(): self.add_area((0, 0), (self.W, self.H))
                elif self.is_vertical(): self.add_area((0, 0), (self.H, self.W))
-               map(lambda p: p.update(), self.get_ports())
 
-       def _create_labels(self):
+       def create_labels(self):
                """Create the labels for the signal block."""
+               Element.create_labels(self)
+               self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
                layouts = list()
                #create the main layout
                layout = gtk.DrawingArea().create_pango_layout('')
@@ -142,7 +135,7 @@ class Block(Element):
                        layouts.append(layout)
                        w,h = layout.get_pixel_size()
                        self.label_width = max(w, self.label_width)
-                       self.label_height = self.label_height + h + LABEL_SEPARATION
+                       self.label_height += h + LABEL_SEPARATION
                width = self.label_width
                height = self.label_height
                #setup the pixmap
@@ -164,7 +157,13 @@ class Block(Element):
                        self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
                        for i in range(width):
                                for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
-               map(lambda p: p._create_labels(), self.get_ports())
+               #calculate width and height needed
+               self.W = self.label_width + 2*BLOCK_LABEL_PADDING
+               self.H = max(*(
+                       [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
+                       sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
+                       for ports in (self.get_sources(), self.get_sinks())]
+               ))
 
        def draw(self, gc, window):
                """
index 379c4a6a25e04b0d2ca6db6431efa250cb1e4fab..07b8ea7e0f63f5451d6a182f9d7ae7e7f7a11273 100644 (file)
@@ -28,6 +28,15 @@ NAME_INDEX = 0
 KEY_INDEX = 1
 DOC_INDEX = 2
 
+DOC_MARKUP_TMPL="""\
+#if $doc
+$encode($doc)#slurp
+#else
+undocumented#slurp
+#end if"""
+
+CAT_MARKUP_TMPL="""Category: $cat"""
+
 class BlockTreeWindow(gtk.VBox):
        """The block selection panel."""
 
@@ -48,7 +57,7 @@ class BlockTreeWindow(gtk.VBox):
                self.treeview = gtk.TreeView(self.treestore)
                self.treeview.set_enable_search(False) #disable pop up search box
                self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK)
-               self.treeview.connect('button_press_event', self._handle_mouse_button_press)
+               self.treeview.connect('button-press-event', self._handle_mouse_button_press)
                selection = self.treeview.get_selection()
                selection.set_mode('single')
                selection.connect('changed', self._handle_selection_change)
@@ -97,14 +106,14 @@ class BlockTreeWindow(gtk.VBox):
                                iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None)
                                self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name)
                                self.treestore.set_value(iter, KEY_INDEX, '')
-                               self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode('Category: %s'%cat_name))
+                               self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name))
                                self._categories[sub_category] = iter
                #add block
                if block is None: return
                iter = self.treestore.insert_before(self._categories[category], None)
                self.treestore.set_value(iter, NAME_INDEX, block.get_name())
                self.treestore.set_value(iter, KEY_INDEX, block.get_key())
-               self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode(block.get_doc() or 'undocumented'))
+               self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()))
 
        ############################################################
        ## Helper Methods
index 013bcb00f81556c469ca48f610154e334c423664..fabf34ee727c75bdb70320bbc8e9ef91a6732bac 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2007, 2008 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -32,6 +32,8 @@ class Connection(Element):
        The arrow coloring exposes the enabled and valid states.
        """
 
+       def __init__(self): Element.__init__(self)
+
        def get_coordinate(self):
                """
                Get the 0,0 coordinate.
@@ -48,8 +50,9 @@ class Connection(Element):
                """
                return 0
 
-       def update(self):
+       def create_shapes(self):
                """Precalculate relative coordinates."""
+               Element.create_shapes(self)
                self._sink_rot = None
                self._source_rot = None
                self._sink_coor = None
@@ -72,7 +75,7 @@ class Connection(Element):
 
        def _update_after_move(self):
                """Calculate coordinates."""
-               self.clear()
+               self.clear() #FIXME do i want this here?
                #source connector
                source = self.get_source()
                X, Y = source.get_connector_coordinate()
@@ -123,7 +126,7 @@ class Connection(Element):
                sink = self.get_sink()
                source = self.get_source()
                #check for changes
-               if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.update()
+               if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.create_shapes()
                elif self._sink_coor != sink.get_coordinate() or self._source_coor != source.get_coordinate(): self._update_after_move()
                #cache values
                self._sink_rot = sink.get_rotation()
index 8d764e28e38e8584302026ccae4fbde33133495d..af40f47c088a38d57baebc2dc20477a25fcb9b35 100644 (file)
@@ -57,6 +57,20 @@ def MessageDialogHelper(type, buttons, title=None, markup=None):
        message_dialog.destroy()
        return response
 
+
+ERRORS_MARKUP_TMPL="""\
+#for $i, $err_msg in enumerate($errors)
+<b>Error $i:</b>
+$encode($err_msg.replace('\t', '  '))
+
+#end for"""
+def ErrorsDialog(flowgraph): MessageDialogHelper(
+       type=gtk.MESSAGE_ERROR,
+       buttons=gtk.BUTTONS_CLOSE,
+       title='Flow Graph Errors',
+       markup=Utils.parse_template(ERRORS_MARKUP_TMPL, errors=flowgraph.get_error_messages()),
+)
+
 class AboutDialog(gtk.AboutDialog):
        """A cute little about dialog."""
 
@@ -98,8 +112,8 @@ COLORS_DIALOG_MARKUP_TMPL = """\
 #end if
 """
 
-def ColorsDialog(platform): MessageDialogHelper(
+def TypesDialog(platform): MessageDialogHelper(
        type=gtk.MESSAGE_INFO,
        buttons=gtk.BUTTONS_CLOSE,
-       title='Colors',
+       title='Types',
        markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL, colors=platform.get_colors()))
index 3151917237785ad299ac0cc7b756e74ba8d2d2a8..f0518ee12ba56883debd666ede1a8e31c12bc8fe 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,11 +17,9 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import Colors
 import pygtk
 pygtk.require('2.0')
 import gtk
-import pango
 from Constants import LINE_SELECT_SENSITIVITY
 from Constants import POSSIBLE_ROTATIONS
 
@@ -32,7 +30,7 @@ class Element(object):
        and methods to detect selection of those areas.
        """
 
-       def __init__(self, *args, **kwargs):
+       def __init__(self):
                """
                Make a new list of rectangular areas and lines, and set the coordinate and the rotation.
                """
@@ -61,6 +59,21 @@ class Element(object):
                rotation = rotation or self.get_rotation()
                return rotation in (90, 270)
 
+       def create_labels(self):
+               """
+               Create labels (if applicable) and call on all children.
+               Call this base method before creating labels in the element.
+               """
+               for child in self.get_children(): child.create_labels()
+
+       def create_shapes(self):
+               """
+               Create shapes (if applicable) and call on all children.
+               Call this base method before creating shapes in the element.
+               """
+               self.clear()
+               for child in self.get_children(): child.create_shapes()
+
        def draw(self, gc, window, border_color, bg_color):
                """
                Draw in the given window.
@@ -70,14 +83,14 @@ class Element(object):
                @param bg_color the color for the inside of the rectangle
                """
                X,Y = self.get_coordinate()
-               for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
+               for (rX,rY),(W,H) in self._areas_list:
                        aX = X + rX
                        aY = Y + rY
                        gc.set_foreground(bg_color)
                        window.draw_rectangle(gc, True, aX, aY, W, H)
                        gc.set_foreground(border_color)
                        window.draw_rectangle(gc, False, aX, aY, W, H)
-               for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]:
+               for (x1, y1),(x2, y2) in self._lines_list:
                        gc.set_foreground(border_color)
                        window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
 
@@ -90,8 +103,8 @@ class Element(object):
 
        def clear(self):
                """Empty the lines and areas."""
-               self.areas_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS)
-               self.lines_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS)
+               self._areas_list = list()
+               self._lines_list = list()
 
        def set_coordinate(self, coor):
                """
@@ -136,7 +149,7 @@ class Element(object):
                X, Y = self.get_coordinate()
                self.set_coordinate((X+deltaX, Y+deltaY))
 
-       def add_area(self, rel_coor, area, rotation=None):
+       def add_area(self, rel_coor, area):
                """
                Add an area to the area list.
                An area is actually a coordinate relative to the main coordinate
@@ -144,25 +157,21 @@ class Element(object):
                A positive width is to the right of the coordinate.
                A positive height is above the coordinate.
                The area is associated with a rotation.
-               If rotation is not specified, the element's current rotation is used.
                @param rel_coor (x,y) offset from this element's coordinate
                @param area (width,height) tuple
-               @param rotation rotation in degrees
                """
-               self.areas_dict[rotation or self.get_rotation()].append((rel_coor, area))
+               self._areas_list.append((rel_coor, area))
 
-       def add_line(self, rel_coor1, rel_coor2, rotation=None):
+       def add_line(self, rel_coor1, rel_coor2):
                """
                Add a line to the line list.
                A line is defined by 2 relative coordinates.
                Lines must be horizontal or vertical.
                The line is associated with a rotation.
-               If rotation is not specified, the element's current rotation is used.
                @param rel_coor1 relative (x1,y1) tuple
                @param rel_coor2 relative (x2,y2) tuple
-               @param rotation rotation in degrees
                """
-               self.lines_dict[rotation or self.get_rotation()].append((rel_coor1, rel_coor2))
+               self._lines_list.append((rel_coor1, rel_coor2))
 
        def what_is_selected(self, coor, coor_m=None):
                """
@@ -183,24 +192,24 @@ class Element(object):
                if coor_m:
                        x_m, y_m = [a-b for a,b in zip(coor_m, self.get_coordinate())]
                        #handle rectangular areas
-                       for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
+                       for (x1,y1), (w,h) in self._areas_list:
                                if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
                                        in_between(x1+w, x, x_m) and in_between(y1, y, y_m) or \
                                        in_between(x1, x, x_m) and in_between(y1+h, y, y_m) or \
                                        in_between(x1+w, x, x_m) and in_between(y1+h, y, y_m):
                                        return self
                        #handle horizontal or vertical lines
-                       for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
+                       for (x1, y1), (x2, y2) in self._lines_list:
                                if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
                                        in_between(x2, x, x_m) and in_between(y2, y, y_m):
                                        return self
                        return None
                else:
                        #handle rectangular areas
-                       for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
+                       for (x1,y1), (w,h) in self._areas_list:
                                if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
                        #handle horizontal or vertical lines
-                       for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
+                       for (x1, y1), (x2, y2) in self._lines_list:
                                if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
                                if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
                                if in_between(x, x1, x2) and in_between(y, y1, y2): return self
@@ -220,7 +229,3 @@ class Element(object):
                if rotation not in POSSIBLE_ROTATIONS:
                        raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation, POSSIBLE_ROTATIONS))
                self.rotation = rotation
-
-       def update(self):
-               """Do nothing for the update. Dummy method."""
-               pass
index f8028f199add9ca85120ea7ab19f53dbc93a8352..8feb171f1fd15e1a25c1f24013f56d8a6dd1f768 100644 (file)
@@ -18,10 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
 from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
-from Actions import \
-       ELEMENT_CREATE, ELEMENT_SELECT, \
-       BLOCK_PARAM_MODIFY, BLOCK_MOVE, \
-       ELEMENT_DELETE
+import Actions
 import Colors
 import Utils
 from Element import Element
@@ -39,7 +36,7 @@ class FlowGraph(Element):
        and the connections between inputs and outputs.
        """
 
-       def __init__(self, *args, **kwargs):
+       def __init__(self):
                """
                FlowGraph contructor.
                Create a list for signal blocks and connections. Connect mouse handlers.
@@ -86,7 +83,7 @@ class FlowGraph(Element):
                block.set_coordinate(coor)
                block.set_rotation(0)
                block.get_param('id').set_value(id)
-               self.handle_states(ELEMENT_CREATE)
+               Actions.ELEMENT_CREATE()
 
        ###########################################################################
        # Copy Paste
@@ -291,10 +288,13 @@ class FlowGraph(Element):
 
        def update(self):
                """
-               Call update on all elements.
+               Call the top level rewrite and validate.
+               Call the top level create labels and shapes.
                """
+               self.rewrite()
                self.validate()
-               for element in self.get_elements(): element.update()
+               self.create_labels()
+               self.create_shapes()
 
        ##########################################################################
        ## Get Selected
@@ -406,7 +406,7 @@ class FlowGraph(Element):
                        self._old_selected_port is not self._new_selected_port:
                        try:
                                self.connect(self._old_selected_port, self._new_selected_port)
-                               self.handle_states(ELEMENT_CREATE)
+                               Actions.ELEMENT_CREATE()
                        except: Messages.send_fail_connection()
                        self._old_selected_port = None
                        self._new_selected_port = None
@@ -421,7 +421,7 @@ class FlowGraph(Element):
                        self._selected_elements = list(
                                set.union(old_elements, new_elements) - set.intersection(old_elements, new_elements)
                        )
-               self.handle_states(ELEMENT_SELECT)
+               Actions.ELEMENT_SELECT()
 
        ##########################################################################
        ## Event Handlers
@@ -443,7 +443,7 @@ class FlowGraph(Element):
                #double click detected, bring up params dialog if possible
                if double_click and self.get_selected_block():
                        self.mouse_pressed = False
-                       self.handle_states(BLOCK_PARAM_MODIFY)
+                       Actions.BLOCK_PARAM_MODIFY()
 
        def handle_mouse_button_release(self, left_click, coordinate):
                """
@@ -454,7 +454,7 @@ class FlowGraph(Element):
                self.time = 0
                self.mouse_pressed = False
                if self.element_moved:
-                       self.handle_states(BLOCK_MOVE)
+                       Actions.BLOCK_MOVE()
                        self.element_moved = False
                self.update_selected_elements()
 
@@ -484,7 +484,7 @@ class FlowGraph(Element):
                                adj.emit('changed')
                #remove the connection if selected in drag event
                if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection():
-                       self.handle_states(ELEMENT_DELETE)
+                       Actions.ELEMENT_DELETE()
                #move the selected elements and record the new coordinate
                X, Y = self.get_coordinate()
                if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y)))
index 6d36f4cf70dcc8d79615bef50f7615458d747ebe..9fcbe2a6cb95304fba5a28b3c22a18a897ed8022 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -19,9 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 from Constants import \
        NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH
-from Actions import \
-       APPLICATION_QUIT, FLOW_GRAPH_KILL, \
-       FLOW_GRAPH_SAVE, get_accel_group
+import Actions
 import pygtk
 pygtk.require('2.0')
 import gtk
@@ -67,20 +65,19 @@ PAGE_TITLE_MARKUP_TMPL = """\
 class MainWindow(gtk.Window):
        """The topmost window with menus, the tool bar, and other major windows."""
 
-       def __init__(self, handle_states, platform):
+       def __init__(self, platform):
                """
-               MainWindow contructor.
-               @param handle_states the callback function
+               MainWindow contructor
+               Setup the menu, toolbar, flowgraph editor notebook, block selection window...
                """
                self._platform = platform
                #setup window
-               self.handle_states = handle_states
                gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
                vbox = gtk.VBox()
                self.hpaned = gtk.HPaned()
                self.add(vbox)
                #create the menu bar and toolbar
-               self.add_accel_group(get_accel_group())
+               self.add_accel_group(Actions.get_accel_group())
                vbox.pack_start(Bars.MenuBar(), False)
                vbox.pack_start(Bars.Toolbar(), False)
                vbox.pack_start(self.hpaned)
@@ -123,7 +120,7 @@ class MainWindow(gtk.Window):
                This method in turns calls the state handler to quit.
                @return true
                """
-               self.handle_states(APPLICATION_QUIT)
+               Actions.APPLICATION_QUIT()
                return True
 
        def _handle_page_change(self, notebook, page, page_num):
@@ -137,7 +134,7 @@ class MainWindow(gtk.Window):
                """
                self.current_page = self.notebook.get_nth_page(page_num)
                Messages.send_page_switch(self.current_page.get_file_path())
-               self.handle_states()
+               Actions.PAGE_CHANGE()
 
        ############################################################
        # Report Window
@@ -223,12 +220,12 @@ class MainWindow(gtk.Window):
                        self._set_page(self.page_to_be_closed)
                #unsaved? ask the user
                if not self.page_to_be_closed.get_saved() and self._save_changes():
-                       self.handle_states(FLOW_GRAPH_SAVE) #try to save
+                       Actions.FLOW_GRAPH_SAVE() #try to save
                        if not self.page_to_be_closed.get_saved(): #still unsaved?
                                self.page_to_be_closed = None #set the page to be closed back to None
                                return
                #stop the flow graph if executing
-               if self.page_to_be_closed.get_pid(): self.handle_states(FLOW_GRAPH_KILL)
+               if self.page_to_be_closed.get_pid(): Actions.FLOW_GRAPH_KILL()
                #remove the page
                self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed))
                if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one
index cb45d535992e208b4e2144e913b83d7be8a5fe7f..b14817d04e0d9e891544a99736a99ad3ccbe358a 100644 (file)
@@ -43,7 +43,7 @@ ourpython_PYTHON = \
        MainWindow.py \
        Messages.py \
        NotebookPage.py \
-       ParamsDialog.py \
+       PropsDialog.py \
        Preferences.py \
        StateCache.py \
        __init__.py
index cb6b7ed3079d7b1df77d207d20b18ab6eef2cde1..fddfeaf5f1cf7b07d2708d602ea99bb3164ae70b 100644 (file)
@@ -17,10 +17,10 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-from Actions import FLOW_GRAPH_CLOSE
 import pygtk
 pygtk.require('2.0')
 import gtk
+import Actions
 from StateCache import StateCache
 from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT
 from DrawingArea import DrawingArea
@@ -80,9 +80,8 @@ class NotebookPage(gtk.HBox):
                self.drawing_area = DrawingArea(self.get_flow_graph())
                self.scrolled_window.add_with_viewport(self.get_drawing_area())
                self.pack_start(self.scrolled_window)
-               #inject drawing area and handle states into flow graph
+               #inject drawing area into flow graph
                self.get_flow_graph().drawing_area = self.get_drawing_area()
-               self.get_flow_graph().handle_states = main_window.handle_states
                self.show_all()
 
        def get_drawing_area(self): return self.drawing_area
@@ -104,7 +103,7 @@ class NotebookPage(gtk.HBox):
                @param the button
                """
                self.main_window.page_to_be_closed = self
-               self.main_window.handle_states(FLOW_GRAPH_CLOSE)
+               Actions.FLOW_GRAPH_CLOSE()
 
        def set_markup(self, markup):
                """
index a11fd906591c02870701c8599a2b090bec9f2bea..4464a57ab77505f006b06a3731d1120248d891bb 100644 (file)
@@ -23,6 +23,106 @@ import pygtk
 pygtk.require('2.0')
 import gtk
 
+class InputParam(gtk.HBox):
+       """The base class for an input parameter inside the input parameters dialog."""
+
+       def __init__(self, param, callback=None):
+               gtk.HBox.__init__(self)
+               self.param = param
+               self._callback = callback
+               self.label = gtk.Label() #no label, markup is added by set_markup
+               self.label.set_size_request(150, -1)
+               self.pack_start(self.label, False)
+               self.set_markup = lambda m: self.label.set_markup(m)
+               self.tp = None
+               #connect events
+               self.connect('show', self._update_gui)
+       def set_color(self, color): pass
+
+       def _update_gui(self, *args):
+               """
+               Set the markup, color, tooltip, show/hide.
+               """
+               #set the markup
+               has_cb = \
+                       hasattr(self.param.get_parent(), 'get_callbacks') and \
+                       filter(lambda c: self.param.get_key() in c, self.param.get_parent()._callbacks)
+               self.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self.param, has_cb=has_cb))
+               #set the color
+               self.set_color(self.param.get_color())
+               #set the tooltip
+               if self.tp: self.tp.set_tip(
+                       self.entry,
+                       Utils.parse_template(TIP_MARKUP_TMPL, param=self.param).strip(),
+               )
+               #show/hide
+               if self.param.get_hide() == 'all': self.hide_all()
+               else: self.show_all()
+
+       def _handle_changed(self, *args):
+               """
+               Handle a gui change by setting the new param value,
+               calling the callback (if applicable), and updating.
+               """
+               #set the new value
+               self.param.set_value(self.get_text())
+               #call the callback
+               if self._callback: self._callback(*args)
+               else: self.param.validate()
+               #gui update
+               self._update_gui()
+
+class EntryParam(InputParam):
+       """Provide an entry box for strings and numbers."""
+
+       def __init__(self, *args, **kwargs):
+               InputParam.__init__(self, *args, **kwargs)
+               self.entry = input = gtk.Entry()
+               input.set_text(self.param.get_value())
+               input.connect('changed', self._handle_changed)
+               self.pack_start(input, True)
+               self.get_text = input.get_text
+               #tool tip
+               self.tp = gtk.Tooltips()
+               self.tp.set_tip(self.entry, '')
+               self.tp.enable()
+       def set_color(self, color): self.entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
+
+class EnumParam(InputParam):
+       """Provide an entry box for Enum types with a drop down menu."""
+
+       def __init__(self, *args, **kwargs):
+               InputParam.__init__(self, *args, **kwargs)
+               self._input = gtk.combo_box_new_text()
+               for option in self.param.get_options(): self._input.append_text(option.get_name())
+               self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+               self._input.connect('changed', self._handle_changed)
+               self.pack_start(self._input, False)
+       def get_text(self): return self.param.get_option_keys()[self._input.get_active()]
+
+class EnumEntryParam(InputParam):
+       """Provide an entry box and drop down menu for Raw Enum types."""
+
+       def __init__(self, *args, **kwargs):
+               InputParam.__init__(self, *args, **kwargs)
+               self._input = gtk.combo_box_entry_new_text()
+               for option in self.param.get_options(): self._input.append_text(option.get_name())
+               try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+               except:
+                       self._input.set_active(-1)
+                       self._input.get_child().set_text(self.param.get_value())
+               self._input.connect('changed', self._handle_changed)
+               self._input.get_child().connect('changed', self._handle_changed)
+               self.pack_start(self._input, False)
+       def get_text(self):
+               if self._input.get_active() == -1: return self._input.get_child().get_text()
+               return self.param.get_option_keys()[self._input.get_active()]
+       def set_color(self, color):
+               if self._input.get_active() == -1: #custom entry, use color
+                       self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
+               else: #from enum, make white background
+                       self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff'))
+
 PARAM_MARKUP_TMPL="""\
 #set $foreground = $param.is_valid() and 'black' or 'red'
 <span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>"""
@@ -49,49 +149,19 @@ Error:
 class Param(Element):
        """The graphical parameter."""
 
-       def update(self):
-               """
-               Called when an external change occurs.
-               Update the graphical input by calling the change handler.
-               """
-               if hasattr(self, '_input'): self._handle_changed()
-
-       def get_input_object(self, callback=None):
-               """
-               Get the graphical gtk object to represent this parameter.
-               Create the input object with this data type and the handle changed method.
-               @param callback a function of one argument(this param) to be called from the change handler
-               @return gtk input object
-               """
-               self._callback = callback
-               self._input = self.get_input_class()(self, self._handle_changed)
-               if not self._callback: self.update()
-               return self._input
+       def __init__(self): Element.__init__(self)
 
-       def _handle_changed(self, widget=None):
+       def get_input(self, *args, **kwargs):
                """
-               When the input changes, write the inputs to the data type.
-               Finish by calling the exteral callback.
+               Get the graphical gtk class to represent this parameter.
+               An enum requires and combo parameter.
+               A non-enum with options gets a combined entry/combo parameter.
+               All others get a standard entry parameter.
+               @return gtk input class
                """
-               self.set_value(self._input.get_text())
-               self.validate()
-               #is param is involved in a callback? #FIXME: messy
-               has_cb = \
-                       hasattr(self.get_parent(), 'get_callbacks') and \
-                       filter(lambda c: self.get_key() in c, self.get_parent()._callbacks)
-               self._input.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self, has_cb=has_cb))
-               #hide/show
-               if self.get_hide() == 'all': self._input.hide_all()
-               else: self._input.show_all()
-               #set the color
-               self._input.set_color(self.get_color())
-               #set the tooltip
-               if self._input.tp: self._input.tp.set_tip(
-                       self._input.entry,
-                       Utils.parse_template(TIP_MARKUP_TMPL, param=self).strip(),
-               )
-               #execute the external callback
-               if self._callback: self._callback(self)
+               if self.is_enum(): return EnumParam(self, *args, **kwargs)
+               if self.get_options(): return EnumEntryParam(self, *args, **kwargs)
+               return EntryParam(self, *args, **kwargs)
 
        def get_layout(self):
                """
diff --git a/grc/gui/ParamsDialog.py b/grc/gui/ParamsDialog.py
deleted file mode 100644 (file)
index ccf19d1..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-"""
-Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-"""
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-from Dialogs import TextDisplay
-from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT
-
-def get_title_label(title):
-       """
-       Get a title label for the params window.
-       The title will be bold, underlined, and left justified.
-       @param title the text of the title
-       @return a gtk object
-       """
-       label = gtk.Label()
-       label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title)
-       hbox = gtk.HBox()
-       hbox.pack_start(label, False, False, padding=11)
-       return hbox
-
-class ParamsDialog(gtk.Dialog):
-       """A dialog box to set block parameters."""
-
-       def __init__(self, block):
-               """
-               SignalBlockParamsDialog contructor.
-               @param block the signal block
-               """
-               gtk.Dialog.__init__(self,
-                       title='Properties: %s'%block.get_name(),
-                       buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE),
-               )
-               self.block = block
-               self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
-               vbox = gtk.VBox()
-               #Add the title label
-               vbox.pack_start(get_title_label('Parameters'), False)
-               #Create the scrolled window to hold all the parameters
-               scrolled_window = gtk.ScrolledWindow()
-               scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
-               scrolled_window.add_with_viewport(vbox)
-               self.vbox.pack_start(scrolled_window, True)
-               #Error Messages for the block
-               self._error_box = gtk.VBox()
-               self._error_messages_text_display = TextDisplay()
-               self._error_box.pack_start(gtk.Label(), False, False, 7) #spacing
-               self._error_box.pack_start(get_title_label('Error Messages'), False)
-               self._error_box.pack_start(self._error_messages_text_display, False)
-               #Docs for the block
-               self._docs_box = err_box = gtk.VBox()
-               self._docs_text_display = TextDisplay()
-               self._docs_box.pack_start(gtk.Label(), False, False, 7) #spacing
-               self._docs_box.pack_start(get_title_label('Documentation'), False)
-               self._docs_box.pack_start(self._docs_text_display, False)
-               #Add all the parameters
-               for param in self.block.get_params():
-                       vbox.pack_start(param.get_input_object(self._handle_changed), False)
-               #Add the error and docs box
-               vbox.pack_start(self._error_box, False)
-               vbox.pack_start(self._docs_box, False)
-               #connect and show
-               self.connect('key_press_event', self._handle_key_press)
-               self.show_all()
-               #initial update
-               for param in self.block.get_params(): param.update()
-               self._update()
-
-       def _update(self):
-               """
-               Update the error messages box.
-               Hide the box if there are no errors.
-               Update the documentation block.
-               Hide the box if there are no docs.
-               """
-               self.block.validate()
-               #update the errors box
-               if self.block.is_valid(): self._error_box.hide()
-               else: self._error_box.show()
-               messages = '\n\n'.join(self.block.get_error_messages())
-               self._error_messages_text_display.set_text(messages)
-               #update the docs box
-               if self.block.get_doc(): self._docs_box.show()
-               else: self._docs_box.hide()
-               self._docs_text_display.set_text(self.block.get_doc())
-
-       def _handle_key_press(self, widget, event):
-               """
-               Handle key presses from the keyboard.
-               Call the ok response when enter is pressed.
-               @return false to forward the keypress
-               """
-               keyname = gtk.gdk.keyval_name(event.keyval)
-               if keyname == 'Return': self.response(gtk.RESPONSE_OK)
-               return False #forward the keypress
-
-       def _handle_changed(self, param):
-               """
-               A change occured, update any dependent parameters:
-               The enum inside the variable type may have changed and,
-               the variable param will need an external update.
-               @param param the graphical parameter that initiated the callback
-               """
-               #update dependent params
-               if param.is_enum():
-                       for other_param in param.get_parent().get_params():
-                               if param.get_key() is not other_param.get_key() and (
-                               param.get_key() in other_param._type or \
-                               param.get_key() in other_param._hide): other_param.update()
-               #update
-               self._update()
-               return True
-
-       def run(self):
-               """
-               Call run().
-               @return true if a change occured.
-               """
-               original_data = list()
-               for param in self.block.get_params():
-                       original_data.append(param.get_value())
-               gtk.Dialog.run(self)
-               self.destroy()
-               new_data = list()
-               for param in self.block.get_params():
-                       new_data.append(param.get_value())
-               return original_data != new_data
index a32b0209ffb2815c2e769a673dac58af1239b26a..8bbfaca2322a5a0a7528733bc83777f2e4e2cd5e 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,32 +17,7 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-from FlowGraph import FlowGraph
-from Connection import Connection
-from Block import Block
-from Port import Port
-from Param import Param
+from Element import Element
 
-def conjoin_classes(name, c1, c2):
-       exec("""
-class %s(c1, c2):
-       def __init__(self, *args, **kwargs):
-               c1.__init__(self, *args, **kwargs)
-               c2.__init__(self, *args, **kwargs)
-"""%name, locals())
-       return locals()[name]
-
-def Platform(platform):
-       #combine with gui class
-       for attr, value in (
-               ('FlowGraph', FlowGraph),
-               ('Connection', Connection),
-               ('Block', Block),
-               ('Source', Port),
-               ('Sink', Port),
-               ('Param', Param),
-       ):
-               old_value = getattr(platform, attr)
-               c = conjoin_classes(attr, old_value, value)
-               setattr(platform, attr, c)
-       return platform
+class Platform(Element):
+       def __init__(self): Element.__init__(self)
index d1f36f8b963659aea5d5e8130c8def7ffb3bd965..6763f6cbd553f61ab7673095f247687000e06dc4 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -34,7 +34,7 @@ PORT_MARKUP_TMPL="""\
 class Port(Element):
        """The graphical port."""
 
-       def __init__(self, *args, **kwargs):
+       def __init__(self):
                """
                Port contructor.
                Create list of connector coordinates.
@@ -42,9 +42,9 @@ class Port(Element):
                Element.__init__(self)
                self.connector_coordinates = dict()
 
-       def update(self):
+       def create_shapes(self):
                """Create new areas and labels for the port."""
-               self.clear()
+               Element.create_shapes(self)
                #get current rotation
                rotation = self.get_rotation()
                #get all sibling ports
@@ -82,8 +82,9 @@ class Port(Element):
                #the connector length
                self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index
 
-       def _create_labels(self):
+       def create_labels(self):
                """Create the labels for the socket."""
+               Element.create_labels(self)
                self._bg_color = Colors.get_color(self.get_color())
                #create the layout
                layout = gtk.DrawingArea().create_pango_layout('')
@@ -114,7 +115,7 @@ class Port(Element):
                        border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
                )
                X,Y = self.get_coordinate()
-               (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels
+               (x,y),(w,h) = self._areas_list[0] #use the first area's sizes to place the labels
                if self.is_horizontal():
                        window.draw_image(gc, self.horizontal_label, 0, 0, x+X+(self.W-self.w)/2, y+Y+(self.H-self.h)/2, -1, -1)
                elif self.is_vertical():
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
new file mode 100644 (file)
index 0000000..a7822b2
--- /dev/null
@@ -0,0 +1,171 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+from Dialogs import TextDisplay
+from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT
+
+def get_title_label(title):
+       """
+       Get a title label for the params window.
+       The title will be bold, underlined, and left justified.
+       @param title the text of the title
+       @return a gtk object
+       """
+       label = gtk.Label()
+       label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title)
+       hbox = gtk.HBox()
+       hbox.pack_start(label, False, False, padding=11)
+       return hbox
+
+class PropsDialog(gtk.Dialog):
+       """
+       A dialog to set block parameters, view errors, and view documentation.
+       """
+
+       def __init__(self, block):
+               """
+               Properties dialog contructor.
+               @param block a block instance
+               """
+               self._hash = 0
+               LABEL_SPACING = 7
+               gtk.Dialog.__init__(self,
+                       title='Properties: %s'%block.get_name(),
+                       buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT),
+               )
+               self._block = block
+               self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
+               vbox = gtk.VBox()
+               #Create the scrolled window to hold all the parameters
+               scrolled_window = gtk.ScrolledWindow()
+               scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+               scrolled_window.add_with_viewport(vbox)
+               self.vbox.pack_start(scrolled_window, True)
+               #Params box for block parameters
+               self._params_box = gtk.VBox()
+               self._params_box.pack_start(get_title_label('Parameters'), False)
+               self._input_object_params = list()
+               #Error Messages for the block
+               self._error_box = gtk.VBox()
+               self._error_messages_text_display = TextDisplay()
+               self._error_box.pack_start(gtk.Label(), False, False, LABEL_SPACING)
+               self._error_box.pack_start(get_title_label('Error Messages'), False)
+               self._error_box.pack_start(self._error_messages_text_display, False)
+               #Docs for the block
+               self._docs_box = err_box = gtk.VBox()
+               self._docs_text_display = TextDisplay()
+               self._docs_box.pack_start(gtk.Label(), False, False, LABEL_SPACING)
+               self._docs_box.pack_start(get_title_label('Documentation'), False)
+               self._docs_box.pack_start(self._docs_text_display, False)
+               #Add the boxes
+               vbox.pack_start(self._params_box, False)
+               vbox.pack_start(self._error_box, False)
+               vbox.pack_start(self._docs_box, False)
+               #connect events
+               self.connect('key-press-event', self._handle_key_press)
+               self.connect('show', self._update_gui)
+               #show all (performs initial gui update)
+               self.show_all()
+
+       def _params_changed(self):
+               """
+               Have the params in this dialog changed?
+               Ex: Added, removed, type change, hide change...
+               To the props dialog, the hide setting of 'none' and 'part' are identical.
+               Therfore, the props dialog only cares if the hide setting is/not 'all'.
+               Make a hash that uniquely represents the params state.
+               @return true if changed
+               """
+               old_hash = self._hash
+               self._hash = 0
+               for param in self._block.get_params():
+                       self._hash ^= hash(param)
+                       self._hash ^= hash(param.get_type())
+                       self._hash ^= hash(param.get_hide() == 'all')
+               return self._hash != old_hash
+
+       def _handle_changed(self, *args):
+               """
+               A change occured within a param:
+               Rewrite/validate the block and update the gui.
+               """
+               #update for the block
+               self._block.rewrite()
+               self._block.validate()
+               self._update_gui()
+
+       def _update_gui(self, *args):
+               """
+               Repopulate the parameters box (if changed).
+               Update all the input parameters.
+               Update the error messages box.
+               Hide the box if there are no errors.
+               Update the documentation block.
+               Hide the box if there are no docs.
+               """
+               #update the params box
+               if self._params_changed():
+                       #hide params box before changing
+                       self._params_box.hide_all()
+                       #empty the params box
+                       for io_param in list(self._input_object_params):
+                               self._params_box.remove(io_param)
+                               self._input_object_params.remove(io_param)
+                               io_param.destroy()
+                       #repopulate the params box
+                       for param in self._block.get_params():
+                               if param.get_hide() == 'all': continue
+                               io_param = param.get_input(self._handle_changed)
+                               self._input_object_params.append(io_param)
+                               self._params_box.pack_start(io_param, False)
+                       #show params box with new params
+                       self._params_box.show_all()
+               #update the errors box
+               if self._block.is_valid(): self._error_box.hide()
+               else: self._error_box.show()
+               messages = '\n\n'.join(self._block.get_error_messages())
+               self._error_messages_text_display.set_text(messages)
+               #update the docs box
+               if self._block.get_doc(): self._docs_box.show()
+               else: self._docs_box.hide()
+               self._docs_text_display.set_text(self._block.get_doc())
+
+       def _handle_key_press(self, widget, event):
+               """
+               Handle key presses from the keyboard.
+               Call the ok response when enter is pressed.
+               @return false to forward the keypress
+               """
+               if event.keyval == gtk.keysyms.Return:
+                       self.response(gtk.RESPONSE_ACCEPT)
+                       return True #handled here
+               return False #forward the keypress
+
+       def run(self):
+               """
+               Run the dialog and get its response.
+               @return true if the response was accept
+               """
+               response = gtk.Dialog.run(self)
+               self.destroy()
+               return response == gtk.RESPONSE_ACCEPT
index 04b18b18aa676013b0f09a49122d035cf948c0d2..3f6b7922405da7364653476c28f64c865c20a85e 100644 (file)
@@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-from Actions import FLOW_GRAPH_UNDO, FLOW_GRAPH_REDO, get_action_from_name
+import Actions
 from Constants import STATE_CACHE_SIZE
 
 class StateCache(object):
@@ -88,5 +88,5 @@ class StateCache(object):
                """
                Update the undo and redo actions based on the number of next and prev states.
                """
-               get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(self.num_next_states != 0)
-               get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(self.num_prev_states != 0)
+               Actions.FLOW_GRAPH_REDO.set_sensitive(self.num_next_states != 0)
+               Actions.FLOW_GRAPH_UNDO.set_sensitive(self.num_prev_states != 0)
index ee6dc6cdc4aa2a62cddc7bc5d6a1ecce71bba496..83036a4b858c0c4eb5460738be7eb2f3e4002e6d 100644 (file)
@@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 from Constants import POSSIBLE_ROTATIONS
 from Cheetah.Template import Template
+import gobject
 
 def get_rotated_coordinate(coor, rotation):
        """
@@ -54,23 +55,6 @@ def get_angle_from_coordinates((x1,y1), (x2,y2)):
                if y2 > y1: return 270
                else: return 90
 
-def xml_encode(string):
-       """
-       Encode a string into an xml safe string by replacing special characters.
-       Needed for gtk pango markup in labels.
-       @param string the input string
-       @return output string with safe characters
-       """
-       string = str(string)
-       for char, safe in (
-                       ('&', '&amp;'),
-                       ('<', '&lt;'),
-                       ('>', '&gt;'),
-                       ('"', '&quot;'),
-                       ("'", '&apos;'),
-       ): string = string.replace(char, safe)
-       return string
-
 def parse_template(tmpl_str, **kwargs):
        """
        Parse the template string with the given args.
@@ -78,5 +62,5 @@ def parse_template(tmpl_str, **kwargs):
        @param tmpl_str the template as a string
        @return a string of the parsed template
        """
-       kwargs['encode'] = xml_encode
+       kwargs['encode'] = gobject.markup_escape_text
        return str(Template(tmpl_str, kwargs))
index 47fe13a3cc11ee6c87d81d605e5d2e7317eda4c2..dd39b095de5a0c14920ee1db2bed655c43e5ae1a 100644 (file)
@@ -18,10 +18,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
 from .. base.Block import Block as _Block
+from .. gui.Block import Block as _GUIBlock
 import extract_docs
 import extract_category
 
-class Block(_Block):
+class Block(_Block, _GUIBlock):
+
+       def is_virtual_sink(self): return self.get_key() == 'virtual_sink'
+       def is_virtual_source(self): return self.get_key() == 'virtual_source'
 
        ##for make source to keep track of indexes
        _source_count = 0
@@ -48,13 +52,13 @@ class Block(_Block):
                        flow_graph=flow_graph,
                        n=n,
                )
+               _GUIBlock.__init__(self)
 
        def validate(self):
                """
                Validate this block.
                Call the base class validate.
                Evaluate the checks: each check must evaluate to True.
-               Adjust the nports.
                """
                _Block.validate(self)
                #evaluate the checks
@@ -65,6 +69,12 @@ class Block(_Block):
                                try: assert check_eval
                                except AssertionError: self.add_error_message('Check "%s" failed.'%check)
                        except: self.add_error_message('Check "%s" did not evaluate.'%check)
+
+       def rewrite(self):
+               """
+               Add and remove ports to adjust for the nports.
+               """
+               _Block.rewrite(self)
                #adjust nports
                for get_ports, get_port in (
                        (self.get_sources, self.get_source),
index 5eba9f24dd839ed0b6bbf65427bc4f5a2cd02475..edc18841a00b7844d6c203bf6af1ca19263115d4 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,8 +18,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
 from .. base.Connection import Connection as _Connection
+from .. gui.Connection import Connection as _GUIConnection
 
-class Connection(_Connection):
+class Connection(_Connection, _GUIConnection):
+
+       def __init__(self, **kwargs):
+               _Connection.__init__(self, **kwargs)
+               _GUIConnection.__init__(self)
 
        def is_msg(self):
                return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
index 8cad8be492216d46c86884750f0badfb9e6b83fa..4dd18a81f4cd230dbec042dfb77a2068129ed859 100644 (file)
@@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 import expr_utils
 from .. base.FlowGraph import FlowGraph as _FlowGraph
+from .. gui.FlowGraph import FlowGraph as _GUIFlowGraph
 from Block import Block
 from Connection import Connection
 import re
@@ -26,9 +27,13 @@ import re
 _variable_matcher = re.compile('^(variable\w*)$')
 _parameter_matcher = re.compile('^(parameter)$')
 
-class FlowGraph(_FlowGraph):
+class FlowGraph(_FlowGraph, _GUIFlowGraph):
+
+       def __init__(self, **kwargs):
+               _FlowGraph.__init__(self, **kwargs)
+               _GUIFlowGraph.__init__(self)
+               self._eval_cache = dict()
 
-       _eval_cache = dict()
        def _eval(self, code, namespace, namespace_hash):
                """
                Evaluate the code with the given namespace.
@@ -37,6 +42,7 @@ class FlowGraph(_FlowGraph):
                @param namespace_hash a unique hash for the namespace
                @return the resultant object
                """
+               if not code: raise Exception, 'Cannot evaluate empty statement.'
                my_hash = hash(code) ^ namespace_hash
                #cache if does not exist
                if not self._eval_cache.has_key(my_hash):
@@ -109,6 +115,13 @@ class FlowGraph(_FlowGraph):
                parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.get_enabled_blocks())
                return parameters
 
+       def rewrite(self):
+               """
+               Flag the namespace to be renewed.
+               """
+               self._renew_eval_ns = True
+               _FlowGraph.rewrite(self)
+
        def evaluate(self, expr):
                """
                Evaluate the expression.
@@ -116,8 +129,8 @@ class FlowGraph(_FlowGraph):
                @throw Exception bad expression
                @return the evaluated data
                """
-               if self.is_flagged():
-                       self.deflag()
+               if self._renew_eval_ns:
+                       self._renew_eval_ns = False
                        #reload namespace
                        n = dict()
                        #load imports
index f971d0c3fb6330ca7b06d24f5863e777334d6399..34d5ab116b07e629f16ecf0d70c29361a16579da 100644 (file)
@@ -18,7 +18,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
 import expr_utils
-from .. base.Param import Param as _Param, EntryParam
+from .. base.Param import Param as _Param
+from .. gui.Param import Param as _GUIParam
+from .. gui.Param import EntryParam
 import Constants
 import numpy
 import os
@@ -83,21 +85,24 @@ COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES)
 REAL_TYPES = tuple(REAL_TYPES + INT_TYPES)
 INT_TYPES = tuple(INT_TYPES)
 
-class Param(_Param):
+class Param(_Param, _GUIParam):
 
-       _init = False
-       _hostage_cells = list()
+       def __init__(self, **kwargs):
+               _Param.__init__(self, **kwargs)
+               _GUIParam.__init__(self)
+               self._init = False
+               self._hostage_cells = list()
 
-       ##possible param types
-       TYPES = _Param.TYPES + [
+       def get_types(self): return (
+               'raw', 'enum',
                'complex', 'real', 'int',
                'complex_vector', 'real_vector', 'int_vector',
                'hex', 'string', 'bool',
                'file_open', 'file_save',
-               'id',
+               'id', 'stream_id',
                'grid_pos', 'notebook',
                'import',
-       ]
+       )
 
        def __repr__(self):
                """
@@ -148,9 +153,9 @@ class Param(_Param):
                                dt_str = dt_str[:max_len-3] + '...'
                return dt_str
 
-       def get_input_class(self):
-               if self.get_type() in ('file_open', 'file_save'): return FileParam
-               return _Param.get_input_class(self)
+       def get_input(self, *args, **kwargs):
+               if self.get_type() in ('file_open', 'file_save'): return FileParam(self, *args, **kwargs)
+               return _GUIParam.get_input(self, *args, **kwargs)
 
        def get_color(self):
                """
@@ -172,6 +177,7 @@ class Param(_Param):
                                'hex': Constants.INT_COLOR_SPEC,
                                'string': Constants.BYTE_VECTOR_COLOR_SPEC,
                                'id': Constants.ID_COLOR_SPEC,
+                               'stream_id': Constants.ID_COLOR_SPEC,
                                'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
                                'notebook': Constants.INT_VECTOR_COLOR_SPEC,
                                'raw': Constants.WILDCARD_COLOR_SPEC,
@@ -248,7 +254,7 @@ class Param(_Param):
                elif t in ('raw', 'complex', 'real', 'int', 'complex_vector', 'real_vector', 'int_vector', 'hex', 'bool'):
                        #raise exception if python cannot evaluate this value
                        try: e = self.get_parent().get_parent().evaluate(v)
-                       except Exception, e: raise Exception, 'Value "%s" cannot be evaluated: %s'%(v, e)
+                       except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e)
                        #raise an exception if the data is invalid
                        if t == 'raw': return e
                        elif t == 'complex':
@@ -310,14 +316,31 @@ class Param(_Param):
                        #can python use this as a variable?
                        try: assert _check_id_matcher.match(v)
                        except AssertionError: raise Exception, 'ID "%s" must begin with a letter and may contain letters, numbers, and underscores.'%v
-                       params = self.get_all_params('id')
-                       keys = [param.get_value() for param in params]
-                       try: assert keys.count(v) <= 1 #id should only appear once, or zero times if block is disabled
+                       ids = [param.get_value() for param in self.get_all_params(t)]
+                       try: assert ids.count(v) <= 1 #id should only appear once, or zero times if block is disabled
                        except: raise Exception, 'ID "%s" is not unique.'%v
                        try: assert v not in ID_BLACKLIST
                        except: raise Exception, 'ID "%s" is blacklisted.'%v
                        return v
                #########################
+               # Stream ID Type
+               #########################
+               elif t == 'stream_id':
+                       #get a list of all stream ids used in the virtual sinks 
+                       ids = [param.get_value() for param in filter(
+                               lambda p: p.get_parent().is_virtual_sink(),
+                               self.get_all_params(t),
+                       )]
+                       #check that the virtual sink's stream id is unique
+                       if self.get_parent().is_virtual_sink():
+                               try: assert ids.count(v) <= 1 #id should only appear once, or zero times if block is disabled
+                               except: raise Exception, 'Stream ID "%s" is not unique.'%v
+                       #check that the virtual source's steam id is found
+                       if self.get_parent().is_virtual_source():
+                               try: assert v in ids
+                               except: raise Exception, 'Stream ID "%s" is not found.'%v
+                       return v
+               #########################
                # Grid Position Type
                #########################
                elif t == 'grid_pos':
@@ -362,7 +385,7 @@ class Param(_Param):
                        try: notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0]
                        except: raise Exception, 'Notebook id "%s" is not an existing notebook id.'%notebook_id
                        #check that page index exists
-                       try: assert int(page_index) in range(len(notebook_block.get_param('labels').get_evaluated()))
+                       try: assert int(page_index) in range(len(notebook_block.get_param('labels').evaluate()))
                        except: raise Exception, 'Page index "%s" is not a valid index number.'%page_index
                        return notebook_id, page_index
                #########################
@@ -380,17 +403,18 @@ class Param(_Param):
        def to_code(self):
                """
                Convert the value to code.
+               For string and list types, check the init flag, call evaluate().
+               This ensures that evaluate() was called to set the xxxify_flags.
                @return a string representing the code
                """
-               #run init tasks in evaluate
-               #such as setting flags
-               if not self._init: self.evaluate()
                v = self.get_value()
                t = self.get_type()
                if t in ('string', 'file_open', 'file_save'): #string types
+                       if not self._init: self.evaluate()
                        if self._stringify_flag: return '"%s"'%v.replace('"', '\"')
                        else: return v
                elif t in ('complex_vector', 'real_vector', 'int_vector'): #vector types
+                       if not self._init: self.evaluate()
                        if self._lisitify_flag: return '(%s, )'%v
                        else: return '(%s)'%v
                else: return v
index d55dbf4ce71a224fa89fd710a396f466db7c2391..bb56d361b5296406c9186086b05f4f6c39a32837 100644 (file)
@@ -20,10 +20,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 import os
 from gnuradio import gr
 from .. base.Platform import Platform as _Platform
+from .. gui.Platform import Platform as _GUIPlatform
 from FlowGraph import FlowGraph as _FlowGraph
 from Connection import Connection as _Connection
 from Block import Block as _Block
-from Port import Source,Sink
+from Port import Port as _Port
 from Param import Param as _Param
 from Generator import Generator
 from Constants import \
@@ -46,7 +47,7 @@ COLORS = (#title, #color spec
        ('Message', Constants.MSG_COLOR_SPEC),
 )
 
-class Platform(_Platform):
+class Platform(_Platform, _GUIPlatform):
 
        def __init__(self):
                """
@@ -70,6 +71,7 @@ class Platform(_Platform):
                        generator=Generator,
                        colors=COLORS,
                )
+               _GUIPlatform.__init__(self)
 
        ##############################################
        # Constructors
@@ -77,6 +79,5 @@ class Platform(_Platform):
        FlowGraph = _FlowGraph
        Connection = _Connection
        Block = _Block
-       Source = Source
-       Sink = Sink
+       Port = _Port
        Param = _Param
index daf8f9ca34c1f687fffc3e54dac26af3dc35b6e3..6965371df8a9e922dbeb808d78da53bf93c81a59 100644 (file)
@@ -18,41 +18,100 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
 from .. base.Port import Port as _Port
+from .. gui.Port import Port as _GUIPort
 import Constants
 
-class Port(_Port):
-
-       ##possible port types
-       TYPES = ['complex', 'float', 'int', 'short', 'byte', 'msg']
-
-       def __init__(self, block, n):
+def _get_source_from_virtual_sink_port(vsp):
+       """
+       Resolve the source port that is connected to the given virtual sink port.
+       Use the get source from virtual source to recursively resolve subsequent ports. 
+       """
+       try: return _get_source_from_virtual_source_port(
+               vsp.get_enabled_connections()[0].get_source())
+       except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp
+
+def _get_source_from_virtual_source_port(vsp, traversed=[]):
+       """
+       Recursively resolve source ports over the virtual connections.
+       Keep track of traversed sources to avoid recursive loops.
+       """
+       if not vsp.get_parent().is_virtual_source(): return vsp
+       if vsp in traversed: raise Exception, 'Loop found when resolving virtual source %s'%vsp
+       try: return _get_source_from_virtual_source_port(
+               _get_source_from_virtual_sink_port(
+                       filter(#get all virtual sinks with a matching stream id
+                               lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
+                               filter(#get all enabled blocks that are also virtual sinks
+                                       lambda b: b.is_virtual_sink(),
+                                       vsp.get_parent().get_parent().get_enabled_blocks(),
+                               ),
+                       )[0].get_sinks()[0]
+               ), traversed + [vsp],
+       )
+       except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
+
+class Port(_Port, _GUIPort):
+
+       def __init__(self, block, n, dir):
                """
                Make a new port from nested data.
                @param block the parent element
                @param n the nested odict
+               @param dir the direction
                """
+               self._n = n
+               if n['type'] == 'msg': n['key'] = 'msg'
+               if dir == 'source' and not n.find('key'):
+                       n['key'] = str(block._source_count)
+                       block._source_count += 1
+               if dir == 'sink' and not n.find('key'):
+                       n['key'] = str(block._sink_count)
+                       block._sink_count += 1
                #build the port
                _Port.__init__(
                        self,
                        block=block,
                        n=n,
+                       dir=dir,
                )
+               _GUIPort.__init__(self)
                self._nports = n.find('nports') or ''
                self._vlen = n.find('vlen') or ''
                self._optional = bool(n.find('optional'))
 
+       def get_types(self): return ('complex', 'float', 'int', 'short', 'byte', 'msg', '')
+
        def validate(self):
                _Port.validate(self)
                try: assert self.get_enabled_connections() or self.get_optional()
                except AssertionError: self.add_error_message('Port is not connected.')
                try: assert self.is_source() or len(self.get_enabled_connections()) <= 1
                except AssertionError: self.add_error_message('Port has too many connections.')
+               #message port logic
                if self.get_type() == 'msg':
                        try: assert not self.get_nports()
                        except AssertionError: self.add_error_message('A port of type "msg" cannot have "nports" set.')
                        try: assert self.get_vlen() == 1
                        except AssertionError: self.add_error_message('A port of type "msg" must have a "vlen" of 1.')
 
+       def rewrite(self):
+               """
+               Handle the port cloning for virtual blocks.
+               """
+               _Port.rewrite(self)
+               if self.get_parent().is_virtual_sink() or self.get_parent().is_virtual_source():
+                       try: #clone type and vlen
+                               source = self.resolve_virtual_source()
+                               self._type = str(source.get_type())
+                               self._vlen = str(source.get_vlen())
+                       except: #reset type and vlen
+                               self._type = ''
+                               self._vlen = ''
+
+       def resolve_virtual_source(self):
+               if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self)
+               if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self)
+
        def get_vlen(self):
                """
                Get the vector length.
@@ -109,24 +168,4 @@ class Port(_Port):
        def copy(self, new_key=None):
                n = self._n.copy()
                if new_key: n['key'] = new_key
-               return self.__class__(self.get_parent(), n)
-
-class Source(Port):
-
-       def __init__(self, block, n):
-               self._n = n #save n
-               if n['type'] == 'msg': n['key'] = 'msg'
-               if not n.find('key'):
-                       n['key'] = str(block._source_count)
-                       block._source_count = block._source_count + 1
-               Port.__init__(self, block, n)
-
-class Sink(Port):
-
-       def __init__(self, block, n):
-               self._n = n #save n
-               if n['type'] == 'msg': n['key'] = 'msg'
-               if not n.find('key'):
-                       n['key'] = str(block._sink_count)
-                       block._sink_count = block._sink_count + 1
-               Port.__init__(self, block, n)
+               return self.__class__(self.get_parent(), n, self._dir)
index df346dd165567002a34fcfbcd2787818ef43cbea..dce4037d58a4a9cde77cf99ca7bd10120f81b279 100644 (file)
@@ -154,6 +154,13 @@ class $(class_name)(gr.hier_block2):
 ##     The port name should be the id of the parent block.
 ##     However, port names for IO pads should be self.
 ########################################################
+#def make_port_name($port)
+       #if $port.get_parent().get_key().startswith('pad_')
+self#slurp
+       #else
+self.$port.get_parent().get_id()#slurp
+       #end if
+#end def
 #if $connections
 
                $DIVIDER
@@ -163,17 +170,14 @@ class $(class_name)(gr.hier_block2):
 #for $con in $connections
        #set $source = $con.get_source()
        #set $sink = $con.get_sink()
-       #if $source.get_parent().get_key() == 'pad_source'
-               #set $source_name = 'self'
-       #else
-               #set $source_name = 'self.' + $source.get_parent().get_id()
+       ##resolve virtual sources to the actual sources
+       #if $source.get_parent().is_virtual_source()
+               #set $source = $source.resolve_virtual_source()
        #end if
-       #if $sink.get_parent().get_key() == 'pad_sink'
-               #set $sink_name = 'self'
-       #else
-               #set $sink_name = 'self.' + $sink.get_parent().get_id()
+       ##do not generate connections with virtual sinks
+       #if not $sink.get_parent().is_virtual_sink()
+               self.connect(($make_port_name($source), $source.get_key()), ($make_port_name($sink), $sink.get_key()))
        #end if
-               self.connect(($source_name, $source.get_key()), ($sink_name, $sink.get_key()))
 #end for
 
 ########################################################
@@ -194,6 +198,20 @@ class $(class_name)(gr.hier_block2):
 ##     For top block code, generate a main routine.
 ##     Instantiate the top block and run as gui or cli.
 ########################################################
+#def make_default($type, $param)
+       #if $type == 'eng_float'
+eng_notation.num_to_str($param.get_make())#slurp
+       #else
+$param.get_make()#slurp
+       #end if
+#end def
+#def make_short_id($param)
+       #set $short_id = $param.get_param('short_id').get_evaluated()
+       #if $short_id
+               #set $short_id = '-' + $short_id
+       #end if
+$short_id#slurp
+#end def
 #if $generate_options != 'hb'
 if __name__ == '__main__':
        parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
@@ -202,12 +220,8 @@ if __name__ == '__main__':
                #set $type = $param.get_param('type').get_value()
                #if $type
                        #silent $params_eq_list.append('%s=options.%s'%($param.get_id(), $param.get_id()))
-                       #set $short_id = $param.get_param('short_id').get_evaluated()
-                       #if $short_id
-                               #set $short_id = '-' + $short_id
-                       #end if
-       parser.add_option("$short_id", "--$param.get_id()", dest="$param.get_id()", type="$type", default=$param.get_make(),
-               help="Set $($param.get_param('label').evaluate() or $param.get_id()) [default=%default]")
+       parser.add_option("$make_short_id($param)", "--$param.get_id().replace('_', '-')", dest="$param.get_id()", type="$type", default=$make_default($type, $param),
+               help="Set $($param.get_param('label').get_evaluated() or $param.get_id()) [default=%default]")
                #end if
        #end for
        (options, args) = parser.parse_args()
index 00d4366ddfc2c24fc3d9c0094077b96e6ac3d3e1..38c8f655ce854b350e4f0d3b693b91e325061f85 100755 (executable)
@@ -32,9 +32,6 @@ from gnuradio.grc.gui.Dialogs import TextDisplay
 from gnuradio.grc.python.Platform import Platform
 platform = Platform()
 
-from gnuradio.grc.gui.Platform import Platform
-platform = Platform(platform)
-
 flow_graph = platform.get_new_flow_graph()
 block = flow_graph.get_new_block('usrp2_probe')
 
@@ -42,6 +39,11 @@ block = flow_graph.get_new_block('usrp2_probe')
 usrp_interface_param = block.get_param('interface')
 usrp_type_param = block.get_param('type')
 
+def get_input(param):
+       param.validate()
+       input = param.get_input()
+       return input
+
 class USRP2ProbeWindow(gtk.Window):
        """
        The main window for USRP Dignostics.
@@ -69,8 +71,8 @@ class USRP2ProbeWindow(gtk.Window):
                #create vbox for storage
                vbox = gtk.VBox()
                frame.add(vbox)
-               vbox.pack_start(usrp_interface_param.get_input_object(), False)
-               vbox.pack_start(usrp_type_param.get_input_object(), False)
+               vbox.pack_start(get_input(usrp_interface_param), False)
+               vbox.pack_start(get_input(usrp_type_param), False)
                #make the tree model for holding mac addrs
                self.treestore = gtk.TreeStore(gobject.TYPE_STRING)
                self.treeview = gtk.TreeView(self.treestore)
index 6565612c16e87980e5d4e64d2ec6597358827d4b..d2e92e7530ab10dff1b46062ac13840d7209b544 100755 (executable)
@@ -30,9 +30,6 @@ from gnuradio.grc.gui.Dialogs import TextDisplay
 from gnuradio.grc.python.Platform import Platform
 platform = Platform()
 
-from gnuradio.grc.gui.Platform import Platform
-platform = Platform(platform)
-
 flow_graph = platform.get_new_flow_graph()
 block = flow_graph.get_new_block('usrp_probe')
 
@@ -40,6 +37,11 @@ block = flow_graph.get_new_block('usrp_probe')
 usrp_which_param = block.get_param('which')
 usrp_dboard_param = block.get_param('dboard')
 
+def get_input(param):
+       param.validate()
+       input = param.get_input()
+       return input
+
 class USRPProbeWindow(gtk.Window):
        """
        The main window for USRP Dignostics.
@@ -66,8 +68,8 @@ class USRPProbeWindow(gtk.Window):
                #create vbox for storage
                vbox = gtk.VBox()
                frame.add(vbox)
-               vbox.pack_start(usrp_which_param.get_input_object(), False)
-               vbox.pack_start(usrp_dboard_param.get_input_object(), False)
+               vbox.pack_start(get_input(usrp_which_param), False)
+               vbox.pack_start(get_input(usrp_dboard_param), False)
                self.probe_button = gtk.Button('Probe')
                self.probe_button.connect('clicked', self._probe_usrp)
                vbox.pack_start(self.probe_button, False)
index bb40e1f160fe4009dec974596cefed2ca38f0284..b4e3af39d671f9a98b17079a124277c21514a845 100644 (file)
@@ -25,8 +25,7 @@
 * size params for the graphical sinks
 * callbacks for set average on fft, waterfall, number sinks
 * add units to params: Sps, Hz, dB...
-* command line options should replace _ with - for the --option
-  * add bool type to command line option store_true or store_false
+* add bool type to command line option store_true or store_false
 
 ##################################################
 # Features
@@ -59,6 +58,8 @@
 ##################################################
 # Problems
 ##################################################
+* msg ports dont work with virtual connections
+  * dont fix this until pmts are used?
 * hier block generation
   * auto generate hier library on changes
   * auto clean hier library when block removed
 * dont generate py files in saved flowgraph dir
 * save/restore cwd
 * threads dont die on exit in probe and variable sink
-* overloaded gui classes for each platform, move param input objects into overloaded
-* align param titles in paramsdialog
-* better error for blank string params
+* align param titles in properties dialog
 * weird grid params misbehaving
-* params dialog needs to dynamically update for all params
-  * will not update for non-enum params
-  * needs to account for added or removed params
-  * example with grid params need update after notebook change
-* use .strip() on the hide property so we can do away with #slurp(s) in the templates
 
 ##################################################
 # Future
index 89a768d4685c43bdde8e820017ffc185bf80257f..165e179d677f6f00f8f71d3285da72d240113daa 100644 (file)
@@ -2,3 +2,4 @@
 /Makefile.in
 /.libs
 /.deps
+test_gruel
index 62b2d5bad25873e4ca4e48681c91b4be25e149bd..c75136de1cc16481704b99e1af10da3dbbc12aed 100644 (file)
@@ -22,8 +22,8 @@ include $(top_srcdir)/Makefile.common
 EXTRA_DIST = \
        bootstrap \
        configure \
-       configure.gnu
-
+       configure.gnu \
+       u2_flash_tool
 
 SUBDIRS = config 
 
index 60d6d2a7ecb2118ac084b6d25f45f54dfa9a8346..53ca9b518aede547457118c36d464e35acd9bffc 100755 (executable)
@@ -3,7 +3,7 @@
 # wrapper to setup cross-compilation of firmware
 #
 
-for v in CC CPP CXX AS AR NM RANLIB STRIP F77 CFLAGS CXXFLAGS CPPFLAGS LDFLAGS 
+for v in CC CPP CXX AS AR NM RANLIB STRIP F77 CFLAGS CXXFLAGS CPPFLAGS LDFLAGS CCAS CCASFLAGS USB_LIBS USB_CFLAGS
 do
   unset $v
 done
@@ -26,6 +26,10 @@ do
       (CXXFLAGS=*) ;;
       (CPPFLAGS=*) ;;
       (LDFLAGS=*)  ;;
+      (CCAS=*)     ;;
+      (CCASFLAGS=*)  ;;
+      (USB_CFLAGS=*) ;;
+      (USB_LIBS=*) ;;
       (*)  args="$args $t" ;;
   esac
 done
index ee713e4ac3e61e2a1649b3fcc082ebd8836ce98d..af4f0b9fbf9136409c820e2e40eeb5ab9d7a3eae 100644 (file)
@@ -139,20 +139,20 @@ module dsp_core_rx
    always @(posedge clk) strobe_cic_d1 <= strobe_cic;
    
    small_hb_dec #(.WIDTH(18)) small_hb_i
-     (.clk(clk),.rst(rst),.bypass(~enable_hb1),
+     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
       .stb_in(strobe_cic_d1),.data_in(i_cic_scaled),.stb_out(strobe_hb1),.data_out(i_hb1));
    
    small_hb_dec #(.WIDTH(18)) small_hb_q
-     (.clk(clk),.rst(rst),.bypass(~enable_hb1),
+     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
       .stb_in(strobe_cic_d1),.data_in(q_cic_scaled),.stb_out(),.data_out(q_hb1));
 
    wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate};
    hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_i
-     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.cpi(cpi_hb),
+     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
       .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2));
 
    hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_q
-     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.cpi(cpi_hb),
+     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
       .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2));
 
    round #(.bits_in(18),.bits_out(16)) round_iout (.in(i_hb2),.out(i_out));
index b256eb57f6ec4eb91b6590880adf3ff775bc7d9e..8fb5ba222bf9e064c2feaaf04336f3f975f5a153 100644 (file)
@@ -9,6 +9,7 @@ module hb_dec
     (input clk,
      input rst,
      input bypass,
+     input run,
      input [8:0] cpi,  // Clocks per input -- equal to the decimation ratio ahead of this block
      input stb_in,
      input [IWIDTH-1:0] data_in,
@@ -25,7 +26,7 @@ module hb_dec
    assign              do_mult = 1;
    
    always @(posedge clk)
-     if(rst)
+     if(rst | ~run)
        odd <= 0;
      else if(stb_in)
        odd <= ~odd;
@@ -34,7 +35,7 @@ module hb_dec
    assign              write_even = stb_in & ~odd;
 
    always @(posedge clk)
-     if(rst)
+     if(rst | ~run)
        phase <= 0;
      else if(stb_in & odd)
        phase <= 1;
index 9957de15aa1247ab3f714ac3f3638f41dba4879e..8519b628a32dc56484fc68e6d5b53f4d60750a55 100644 (file)
@@ -8,6 +8,7 @@ module small_hb_dec
     (input clk,
      input rst,
      input bypass,
+     input run,
      input stb_in,
      input [WIDTH-1:0] data_in,
      output reg stb_out,
@@ -21,15 +22,26 @@ module small_hb_dec
    wire                go;
    reg                         phase, go_d1, go_d2, go_d3, go_d4;
    always @(posedge clk)
-     if(rst)
+     if(rst | ~run)
        phase <= 0;
      else if(stb_in_d1)
        phase <= ~phase;
    assign              go = stb_in_d1 & phase;
-   always @(posedge clk) go_d1 <= go;
-   always @(posedge clk) go_d2 <= go_d1;
-   always @(posedge clk) go_d3 <= go_d2;
-   always @(posedge clk) go_d4 <= go_d3;
+   always @(posedge clk) 
+     if(rst | ~run)
+       begin
+         go_d1 <= 0;
+         go_d2 <= 0;
+         go_d3 <= 0;
+         go_d4 <= 0;
+       end
+     else
+       begin
+         go_d1 <= go;
+         go_d2 <= go_d1;
+         go_d3 <= go_d2;
+         go_d4 <= go_d3;
+       end
 
    wire [17:0]                 coeff_a = -10690;
    wire [17:0]                 coeff_b = 75809;
index 83323f09358b23ef97e940b972a30ab727c57b81..d30ee14f128ed2ebce92e2b89d7857ab185942b6 100644 (file)
@@ -72,12 +72,14 @@ namespace vrt {
                 int *ctrl_fd_ptr, struct in_addr *ctrl_port_inaddr,
                 int *data_fd_ptr, int *data_port_ptr);
 
+    // dsprxno selects the Rx DSP pipe (0 or 1) to configure
     static bool
-    send_rx_command(int ctrl_fd, bool start,
-                   struct in_addr addr, int data_port, int samples_per_pkt, int siggen_param);
+    send_rx_command(int ctrl_fd, int rxdspno, bool start,
+                   struct in_addr addr, int data_port, int samples_per_pkt);
 
+    // dsprxno selects the Rx DSP pipe (0 or 1) to stop
     static bool
-    send_stop_rx_command(int ctrl_fd);
+    send_stop_rx_command(int ctrl_fd, int rxdspno);
     
     static int control_port() { return 790; }
     int data_socket_fd() const { return d_data_fd; }
@@ -94,9 +96,11 @@ namespace vrt {
 
     vrt::rx::sptr vrt_rx() const { return d_rx; }
 
+    // FIXME add rxdspno as the first parameter
     bool start_streaming(int samples_per_pkt = 0);
-    bool stop_streaming();
 
+    // FIXME add rxdspno as the first parameter
+    bool stop_streaming();
 
     /* convenience methods that ultimately write the dboard pins */
     bool set_center_freq(double target_freq);
index 8cf542e0f3b5889f953b718d8a091cb3350769f0..a8bc3e525bdb5eea535c128d29b74c5b7b0d30ad 100644 (file)
@@ -76,14 +76,18 @@ vrt::quadradio::open(const char *ip)
 bool
 vrt::quadradio::start_streaming(int samples_per_pkt)
 {
-  return send_rx_command(d_ctrl_fd, true, d_ctrl_port_inaddr,
-                        d_data_port, samples_per_pkt, 0);
+  int rxdspno = 0;     // FIXME make it the first param
+
+  return send_rx_command(d_ctrl_fd, rxdspno, true, d_ctrl_port_inaddr,
+                        d_data_port, samples_per_pkt);
 }
 
 bool
 vrt::quadradio::stop_streaming()
 {
-  return send_stop_rx_command(d_ctrl_fd);
+  int rxdspno = 0;     // FIXME make it the first param
+
+  return send_stop_rx_command(d_ctrl_fd, rxdspno);
 }
 
 bool
@@ -288,9 +292,9 @@ vrt::quadradio::open_sockets(const char *quad_radio_ip, int quad_radio_ctrl_port
 // ------------------------------------------------------------------------
 
 bool
-vrt::quadradio::send_rx_command(int ctrl_fd, bool start,
+vrt::quadradio::send_rx_command(int ctrl_fd, int rxdspno, bool start,
                                struct in_addr addr, int data_port,
-                               int samples_per_pkt, int siggen_param)
+                               int samples_per_pkt)
 {
   uint32_t cmd[7];
   cmd[0] = htonl(0);              // verb: set
@@ -299,17 +303,17 @@ vrt::quadradio::send_rx_command(int ctrl_fd, bool start,
   cmd[3] = addr.s_addr;                   // ip address to send data to (already network endian)
   cmd[4] = htonl(data_port);      // port to send data to
   cmd[5] = htonl(samples_per_pkt);
-  cmd[6] = htonl(siggen_param);
+  cmd[6] = htonl(rxdspno);        // the DSP pipeline to configure
 
   return send_and_check(ctrl_fd, cmd, sizeof(cmd));
 }
 
 bool
-vrt::quadradio::send_stop_rx_command(int ctrl_fd)
+vrt::quadradio::send_stop_rx_command(int ctrl_fd, int rxdspno)
 {
   struct in_addr in_addr;
   in_addr.s_addr = 0;
-  return send_rx_command(ctrl_fd, false, in_addr, 0, 0, 0);
+  return send_rx_command(ctrl_fd, rxdspno, false, in_addr, 0, 0);
 }
 
 bool