summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore29
-rw-r--r--config/Makefile.am1
-rw-r--r--config/grc_gr_noaa.m441
-rw-r--r--config/grc_grc.m42
-rw-r--r--configure.ac3
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h4
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h4
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h2
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h2
-rw-r--r--gnuradio-core/src/python/gnuradio/Makefile.am1
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am1
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/generic_usrp.py (renamed from gnuradio-examples/python/digital/generic_usrp.py)9
-rw-r--r--gnuradio-core/src/python/gnuradio/eng_option.py22
-rw-r--r--gnuradio-core/src/python/gnuradio/usrp_options.py (renamed from gnuradio-examples/python/digital/usrp_options.py)6
-rw-r--r--gnuradio-examples/python/digital/Makefile.am2
-rwxr-xr-xgnuradio-examples/python/digital/benchmark_qt_rx.py2
-rw-r--r--gnuradio-examples/python/digital/usrp_receive_path.py2
-rw-r--r--gnuradio-examples/python/digital/usrp_transmit_path.py2
-rw-r--r--gr-noaa/.gitignore2
-rw-r--r--gr-noaa/Makefile.am29
-rw-r--r--gr-noaa/README53
-rw-r--r--gr-noaa/apps/.gitignore1
-rw-r--r--gr-noaa/apps/Makefile.am35
-rw-r--r--gr-noaa/apps/demod_hrpt_file.grc781
-rwxr-xr-xgr-noaa/apps/demod_hrpt_file.py130
-rw-r--r--gr-noaa/apps/usrp_rx_hrpt.cfg13
-rw-r--r--gr-noaa/apps/usrp_rx_hrpt.grc1394
-rwxr-xr-xgr-noaa/apps/usrp_rx_hrpt.py435
-rw-r--r--gr-noaa/apps/usrp_rx_lrit.grc1477
-rwxr-xr-xgr-noaa/apps/usrp_rx_lrit.py399
-rw-r--r--gr-noaa/grc/.gitignore1
-rw-r--r--gr-noaa/grc/Makefile.am31
-rw-r--r--gr-noaa/grc/noaa_hrpt_decoder.xml12
-rw-r--r--gr-noaa/grc/noaa_hrpt_deframer.xml16
-rw-r--r--gr-noaa/grc/noaa_hrpt_pll_cf.xml34
-rw-r--r--gr-noaa/grc/noaa_hrpt_sync_fb.xml39
-rw-r--r--gr-noaa/lib/.gitignore4
-rw-r--r--gr-noaa/lib/Makefile.am46
-rw-r--r--gr-noaa/lib/noaa_hrpt_decoder.cc77
-rw-r--r--gr-noaa/lib/noaa_hrpt_decoder.h47
-rw-r--r--gr-noaa/lib/noaa_hrpt_deframer.cc125
-rw-r--r--gr-noaa/lib/noaa_hrpt_deframer.h59
-rw-r--r--gr-noaa/lib/noaa_hrpt_pll_cf.cc82
-rw-r--r--gr-noaa/lib/noaa_hrpt_pll_cf.h55
-rw-r--r--gr-noaa/lib/noaa_hrpt_sync_fb.cc90
-rw-r--r--gr-noaa/lib/noaa_hrpt_sync_fb.h58
-rw-r--r--gr-noaa/python/Makefile.am27
-rw-r--r--gr-noaa/swig/.gitignore6
-rw-r--r--gr-noaa/swig/Makefile.am68
-rw-r--r--gr-noaa/swig/Makefile.swig.gen259
-rw-r--r--gr-noaa/swig/__init__.py28
-rw-r--r--gr-noaa/swig/noaa_hrpt_decoder.i32
-rw-r--r--gr-noaa/swig/noaa_hrpt_deframer.i32
-rw-r--r--gr-noaa/swig/noaa_hrpt_pll_cf.i37
-rw-r--r--gr-noaa/swig/noaa_hrpt_sync_fb.i37
-rw-r--r--gr-noaa/swig/noaa_swig.i35
-rw-r--r--gr-utils/src/python/Makefile.am6
-rwxr-xr-xgr-utils/src/python/gr_plot_qt.py214
-rw-r--r--gr-utils/src/python/pyqt_plot.py237
-rw-r--r--gr-utils/src/python/pyqt_plot.ui673
-rwxr-xr-xgr-utils/src/python/qr_fft.py505
-rwxr-xr-xgr-utils/src/python/usrp2_siggen.py389
-rwxr-xr-xgr-utils/src/python/usrp2_siggen_gui.py275
-rwxr-xr-xgr-utils/src/python/usrp_siggen.py471
-rwxr-xr-xgr-utils/src/python/usrp_siggen_gui.py310
-rw-r--r--gr-wxgui/src/python/fft_window.py6
-rw-r--r--gr-wxgui/src/python/forms/converters.py9
-rw-r--r--gr-wxgui/src/python/forms/forms.py11
-rw-r--r--grc/Makefile.inc4
-rw-r--r--grc/base/Block.py66
-rw-r--r--grc/base/Element.py68
-rw-r--r--grc/base/FlowGraph.py20
-rw-r--r--grc/base/Param.py134
-rw-r--r--grc/base/Platform.py5
-rw-r--r--grc/base/Port.py32
-rw-r--r--grc/blocks/Makefile.am4
-rw-r--r--grc/blocks/band_pass_filter.xml19
-rw-r--r--grc/blocks/band_reject_filter.xml19
-rw-r--r--grc/blocks/blks2_cvsd_decode.xml32
-rw-r--r--grc/blocks/blks2_cvsd_encode.xml32
-rw-r--r--grc/blocks/block_tree.xml7
-rw-r--r--grc/blocks/gr_noise_source_x.xml2
-rw-r--r--grc/blocks/gr_sig_source_x.xml2
-rw-r--r--grc/blocks/high_pass_filter.xml19
-rw-r--r--grc/blocks/low_pass_filter.xml19
-rw-r--r--grc/blocks/options.xml9
-rw-r--r--grc/blocks/pad_sink.xml3
-rw-r--r--grc/blocks/pad_source.xml6
-rw-r--r--grc/blocks/parameter.xml9
-rw-r--r--grc/blocks/virtual_sink.xml21
-rw-r--r--grc/blocks/virtual_source.xml21
-rw-r--r--grc/blocks/wxgui_fftsink2.xml7
-rw-r--r--grc/blocks/wxgui_waterfallsink2.xml7
-rw-r--r--grc/examples/Makefile.am3
-rw-r--r--grc/examples/audio/cvsd_sweep.grc918
-rw-r--r--grc/gui/ActionHandler.py190
-rw-r--r--grc/gui/Actions.py379
-rw-r--r--grc/gui/Bars.py18
-rw-r--r--grc/gui/Block.py37
-rw-r--r--grc/gui/BlockTreeWindow.py15
-rw-r--r--grc/gui/Connection.py11
-rw-r--r--grc/gui/Dialogs.py18
-rw-r--r--grc/gui/Element.py53
-rw-r--r--grc/gui/FlowGraph.py26
-rw-r--r--grc/gui/MainWindow.py23
-rw-r--r--grc/gui/Makefile.am2
-rw-r--r--grc/gui/NotebookPage.py7
-rw-r--r--grc/gui/Param.py150
-rw-r--r--grc/gui/Platform.py33
-rw-r--r--grc/gui/Port.py13
-rw-r--r--grc/gui/PropsDialog.py (renamed from grc/gui/ParamsDialog.py)134
-rw-r--r--grc/gui/StateCache.py6
-rw-r--r--grc/gui/Utils.py20
-rw-r--r--grc/python/Block.py14
-rw-r--r--grc/python/Connection.py9
-rw-r--r--grc/python/FlowGraph.py21
-rw-r--r--grc/python/Param.py62
-rw-r--r--grc/python/Platform.py9
-rw-r--r--grc/python/Port.py93
-rw-r--r--grc/python/flow_graph.tmpl44
-rwxr-xr-xgrc/scripts/usrp2_probe12
-rwxr-xr-xgrc/scripts/usrp_probe12
-rw-r--r--grc/todo.txt14
-rw-r--r--gruel/src/lib/.gitignore1
-rw-r--r--usrp2/firmware/Makefile.am4
-rwxr-xr-xusrp2/firmware/configure.gnu6
-rw-r--r--usrp2/fpga/sdr_lib/dsp_core_rx.v8
-rw-r--r--usrp2/fpga/sdr_lib/hb_dec.v5
-rw-r--r--usrp2/fpga/sdr_lib/small_hb_dec.v22
-rw-r--r--vrt/include/vrt/quadradio.h12
-rw-r--r--vrt/lib/quadradio.cc20
135 files changed, 9625 insertions, 2697 deletions
diff --git a/.gitignore b/.gitignore
index 6a6326509..b333709ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
-*~
diff --git a/config/Makefile.am b/config/Makefile.am
index d6a3ad393..3aead353a 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -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
index 000000000..b00579ff5
--- /dev/null
+++ b/config/grc_gr_noaa.m4
@@ -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])
+ ])
+])
diff --git a/config/grc_grc.m4 b/config/grc_grc.m4
index ce23e3c25..7ee009fae 100644
--- a/config/grc_grc.m4
+++ b/config/grc_grc.m4
@@ -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
diff --git a/configure.ac b/configure.ac
index 2bb37935e..b6b596bef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
index bfc4c0467..8971d3d39 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
@@ -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,
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
index b79a89fe9..d4c886ec3 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
@@ -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
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
index 7be611e23..a7e8de62a 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
@@ -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)
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
index 7d0a31c59..b2e67e817 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
@@ -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>
*
*/
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
index b334f5878..e05e18ff2 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
@@ -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,
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
index 83997c0c9..200adee3d 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
@@ -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>
*/
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
index d5eba885c..6a9598f34 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
@@ -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)
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
index 50849d510..d2efc591a 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
@@ -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>
*/
diff --git a/gnuradio-core/src/python/gnuradio/Makefile.am b/gnuradio-core/src/python/gnuradio/Makefile.am
index ed36bbae7..dcc0017b3 100644
--- a/gnuradio-core/src/python/gnuradio/Makefile.am
+++ b/gnuradio-core/src/python/gnuradio/Makefile.am
@@ -34,5 +34,6 @@ grpython_PYTHON = \
packet_utils.py \
gr_unittest.py \
optfir.py \
+ usrp_options.py \
window.py
endif
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
index 17be09cc7..f0825b151 100644
--- a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
@@ -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-examples/python/digital/generic_usrp.py b/gnuradio-core/src/python/gnuradio/blks2impl/generic_usrp.py
index c7ccbe53c..5abbaf9eb 100644
--- a/gnuradio-examples/python/digital/generic_usrp.py
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/generic_usrp.py
@@ -33,7 +33,7 @@ class _dummy_freq_result(object):
self.baseband_freq = target_freq
self.dxc_freq = 0
self.residual_freq = 0
-from gnuradio import gr, usrp, usrp2
+from gnuradio import gr
########################################################################
# generic usrp common stuff
@@ -167,6 +167,7 @@ class generic_usrp_source_c(_generic_usrp_base, gr.hier_block2):
# 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)
@@ -178,6 +179,7 @@ class generic_usrp_source_c(_generic_usrp_base, gr.hier_block2):
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)
@@ -224,6 +226,7 @@ class generic_usrp_sink_c(_generic_usrp_base, gr.hier_block2):
# 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)
@@ -234,6 +237,8 @@ class generic_usrp_sink_c(_generic_usrp_base, gr.hier_block2):
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_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)
diff --git a/gnuradio-core/src/python/gnuradio/eng_option.py b/gnuradio-core/src/python/gnuradio/eng_option.py
index 09c3e1d87..e10235f14 100644
--- a/gnuradio-core/src/python/gnuradio/eng_option.py
+++ b/gnuradio-core/src/python/gnuradio/eng_option.py
@@ -23,29 +23,11 @@
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-examples/python/digital/usrp_options.py b/gnuradio-core/src/python/gnuradio/usrp_options.py
index 380ef60f4..86dba2f9a 100644
--- a/gnuradio-examples/python/digital/usrp_options.py
+++ b/gnuradio-core/src/python/gnuradio/usrp_options.py
@@ -27,7 +27,7 @@ class _parser_groups(object):
self.usrp1exp_grp = parser.add_option_group("USRP1 Expert Options")
self.usrp2_grp = parser.add_option_group("USRP2 Specific Options")
-import generic_usrp
+from gnuradio import blks2
def _add_options(parser):
"""
@@ -76,7 +76,7 @@ def add_rx_options(parser):
help="set fpga decimation rate to DECIM [default=%default]")
def create_usrp_source(options):
- u = generic_usrp.generic_usrp_source_c(
+ u = blks2.generic_usrp_source_c(
usrpx=options.usrpx,
which=options.which,
subdev_spec=options.rx_subdev_spec,
@@ -107,7 +107,7 @@ def add_tx_options(parser):
help="set fpga interpolation rate to INTERP [default=%default]")
def create_usrp_sink(options):
- u = generic_usrp.generic_usrp_sink_c(
+ u = blks2.generic_usrp_sink_c(
usrpx=options.usrpx,
which=options.which,
subdev_spec=options.tx_subdev_spec,
diff --git a/gnuradio-examples/python/digital/Makefile.am b/gnuradio-examples/python/digital/Makefile.am
index 64ce4ec46..e32180cd4 100644
--- a/gnuradio-examples/python/digital/Makefile.am
+++ b/gnuradio-examples/python/digital/Makefile.am
@@ -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
diff --git a/gnuradio-examples/python/digital/benchmark_qt_rx.py b/gnuradio-examples/python/digital/benchmark_qt_rx.py
index 33cf94a5c..0cbb68d23 100755
--- a/gnuradio-examples/python/digital/benchmark_qt_rx.py
+++ b/gnuradio-examples/python/digital/benchmark_qt_rx.py
@@ -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/usrp_receive_path.py b/gnuradio-examples/python/digital/usrp_receive_path.py
index fd47c2725..e28eb0a8c 100644
--- a/gnuradio-examples/python/digital/usrp_receive_path.py
+++ b/gnuradio-examples/python/digital/usrp_receive_path.py
@@ -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
diff --git a/gnuradio-examples/python/digital/usrp_transmit_path.py b/gnuradio-examples/python/digital/usrp_transmit_path.py
index ed2603fa3..ad9f741a6 100644
--- a/gnuradio-examples/python/digital/usrp_transmit_path.py
+++ b/gnuradio-examples/python/digital/usrp_transmit_path.py
@@ -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
index 000000000..282522db0
--- /dev/null
+++ b/gr-noaa/.gitignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/gr-noaa/Makefile.am b/gr-noaa/Makefile.am
new file mode 100644
index 000000000..f3f4f6a38
--- /dev/null
+++ b/gr-noaa/Makefile.am
@@ -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
index 000000000..d99c0d90a
--- /dev/null
+++ b/gr-noaa/README
@@ -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
index 000000000..773a6df9b
--- /dev/null
+++ b/gr-noaa/apps/.gitignore
@@ -0,0 +1 @@
+*.dat
diff --git a/gr-noaa/apps/Makefile.am b/gr-noaa/apps/Makefile.am
new file mode 100644
index 000000000..906638ff1
--- /dev/null
+++ b/gr-noaa/apps/Makefile.am
@@ -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
index 000000000..4a5e87170
--- /dev/null
+++ b/gr-noaa/apps/demod_hrpt_file.grc
@@ -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
index 000000000..a1469e9e0
--- /dev/null
+++ b/gr-noaa/apps/demod_hrpt_file.py
@@ -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
index 000000000..69f3c0bf0
--- /dev/null
+++ b/gr-noaa/apps/usrp_rx_hrpt.cfg
@@ -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
index 000000000..90d868769
--- /dev/null
+++ b/gr-noaa/apps/usrp_rx_hrpt.grc
@@ -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
index 000000000..7efbecd3a
--- /dev/null
+++ b/gr-noaa/apps/usrp_rx_hrpt.py
@@ -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
index 000000000..55fe39787
--- /dev/null
+++ b/gr-noaa/apps/usrp_rx_lrit.grc
@@ -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
index 000000000..bc313e3af
--- /dev/null
+++ b/gr-noaa/apps/usrp_rx_lrit.py
@@ -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
index 000000000..70845e08e
--- /dev/null
+++ b/gr-noaa/grc/.gitignore
@@ -0,0 +1 @@
+Makefile.in
diff --git a/gr-noaa/grc/Makefile.am b/gr-noaa/grc/Makefile.am
new file mode 100644
index 000000000..1f056473c
--- /dev/null
+++ b/gr-noaa/grc/Makefile.am
@@ -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
index 000000000..183d72aba
--- /dev/null
+++ b/gr-noaa/grc/noaa_hrpt_decoder.xml
@@ -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
index 000000000..af36abf2a
--- /dev/null
+++ b/gr-noaa/grc/noaa_hrpt_deframer.xml
@@ -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
index 000000000..bbe15e8c3
--- /dev/null
+++ b/gr-noaa/grc/noaa_hrpt_pll_cf.xml
@@ -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
index 000000000..e066e3489
--- /dev/null
+++ b/gr-noaa/grc/noaa_hrpt_sync_fb.xml
@@ -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
index 000000000..02b052397
--- /dev/null
+++ b/gr-noaa/lib/.gitignore
@@ -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
index 000000000..6435d192e
--- /dev/null
+++ b/gr-noaa/lib/Makefile.am
@@ -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
index 000000000..8cfaa913c
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_decoder.cc
@@ -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
index 000000000..305243b09
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_decoder.h
@@ -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
index 000000000..89486aa19
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_deframer.cc
@@ -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
index 000000000..0aeb16a2d
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_deframer.h
@@ -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
index 000000000..08ab1d15f
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_pll_cf.cc
@@ -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
index 000000000..507d47fe7
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_pll_cf.h
@@ -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
index 000000000..f99947f82
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_sync_fb.cc
@@ -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
index 000000000..a9416b9ea
--- /dev/null
+++ b/gr-noaa/lib/noaa_hrpt_sync_fb.h
@@ -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
index 000000000..869c5f353
--- /dev/null
+++ b/gr-noaa/python/Makefile.am
@@ -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
index 000000000..d18a966df
--- /dev/null
+++ b/gr-noaa/swig/.gitignore
@@ -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
index 000000000..cd7686e21
--- /dev/null
+++ b/gr-noaa/swig/Makefile.am
@@ -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
index 000000000..3d7102fe3
--- /dev/null
+++ b/gr-noaa/swig/Makefile.swig.gen
@@ -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
index 000000000..d8d337e65
--- /dev/null
+++ b/gr-noaa/swig/__init__.py
@@ -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
index 000000000..ddf181c28
--- /dev/null
+++ b/gr-noaa/swig/noaa_hrpt_decoder.i
@@ -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
index 000000000..6914b93e6
--- /dev/null
+++ b/gr-noaa/swig/noaa_hrpt_deframer.i
@@ -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
index 000000000..859548a2d
--- /dev/null
+++ b/gr-noaa/swig/noaa_hrpt_pll_cf.i
@@ -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
index 000000000..a8e5b21dd
--- /dev/null
+++ b/gr-noaa/swig/noaa_hrpt_sync_fb.i
@@ -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
index 000000000..e6497bc46
--- /dev/null
+++ b/gr-noaa/swig/noaa_swig.i
@@ -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"
diff --git a/gr-utils/src/python/Makefile.am b/gr-utils/src/python/Makefile.am
index 59ca215a7..fb21e4f44 100644
--- a/gr-utils/src/python/Makefile.am
+++ b/gr-utils/src/python/Makefile.am
@@ -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
diff --git a/gr-utils/src/python/gr_plot_qt.py b/gr-utils/src/python/gr_plot_qt.py
index a5e3463c8..f3dc472f5 100755
--- a/gr-utils/src/python/gr_plot_qt.py
+++ b/gr-utils/src/python/gr_plot_qt.py
@@ -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()
diff --git a/gr-utils/src/python/pyqt_plot.py b/gr-utils/src/python/pyqt_plot.py
index 74c43c3eb..98977da97 100644
--- a/gr-utils/src/python/pyqt_plot.py
+++ b/gr-utils/src/python/pyqt_plot.py
@@ -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
diff --git a/gr-utils/src/python/pyqt_plot.ui b/gr-utils/src/python/pyqt_plot.ui
index 19a62adf5..7244d24c9 100644
--- a/gr-utils/src/python/pyqt_plot.ui
+++ b/gr-utils/src/python/pyqt_plot.ui
@@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>927</width>
- <height>696</height>
+ <height>718</height>
</rect>
</property>
<property name="windowTitle" >
@@ -14,126 +14,14 @@
</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>
@@ -144,185 +32,416 @@
<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>
@@ -341,6 +460,7 @@
<string>&amp;File</string>
</property>
<addaction name="action_open" />
+ <addaction name="action_reload" />
<addaction name="action_exit" />
</widget>
<addaction name="menu_File" />
@@ -359,6 +479,11 @@
<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
index c2f06d715..000000000
--- a/gr-utils/src/python/qr_fft.py
+++ /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
index 9ade933c7..000000000
--- a/gr-utils/src/python/usrp2_siggen.py
+++ /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
index 89bc6e589..000000000
--- a/gr-utils/src/python/usrp2_siggen_gui.py
+++ /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)
diff --git a/gr-utils/src/python/usrp_siggen.py b/gr-utils/src/python/usrp_siggen.py
index 8ae2fbfbf..8ee8cfd2a 100755
--- a/gr-utils/src/python/usrp_siggen.py
+++ b/gr-utils/src/python/usrp_siggen.py
@@ -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
#
@@ -20,200 +20,307 @@
# 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
index 000000000..40848fbee
--- /dev/null
+++ b/gr-utils/src/python/usrp_siggen_gui.py
@@ -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)
diff --git a/gr-wxgui/src/python/fft_window.py b/gr-wxgui/src/python/fft_window.py
index 237c8940c..e025c28dd 100644
--- a/gr-wxgui/src/python/fft_window.py
+++ b/gr-wxgui/src/python/fft_window.py
@@ -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
diff --git a/gr-wxgui/src/python/forms/converters.py b/gr-wxgui/src/python/forms/converters.py
index 9f757aa84..db14d2752 100644
--- a/gr-wxgui/src/python/forms/converters.py
+++ b/gr-wxgui/src/python/forms/converters.py
@@ -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):
diff --git a/gr-wxgui/src/python/forms/forms.py b/gr-wxgui/src/python/forms/forms.py
index c69315b03..8dc58367d 100644
--- a/gr-wxgui/src/python/forms/forms.py
+++ b/gr-wxgui/src/python/forms/forms.py
@@ -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
diff --git a/grc/Makefile.inc b/grc/Makefile.inc
index 96ee11b67..c45d1ce1f 100644
--- a/grc/Makefile.inc
+++ b/grc/Makefile.inc
@@ -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
diff --git a/grc/base/Block.py b/grc/base/Block.py
index d5e104785..203e878e4 100644
--- a/grc/base/Block.py
+++ b/grc/base/Block.py
@@ -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()
diff --git a/grc/base/Element.py b/grc/base/Element.py
index 16000c46c..a57090f3b 100644
--- a/grc/base/Element.py
+++ b/grc/base/Element.py
@@ -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
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
index ea489e948..7c51ef42a 100644
--- a/grc/base/FlowGraph.py
+++ b/grc/base/FlowGraph.py
@@ -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
diff --git a/grc/base/Param.py b/grc/base/Param.py
index 93c1c52bd..e56eac36e 100644
--- a/grc/base/Param.py
+++ b/grc/base/Param.py
@@ -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
diff --git a/grc/base/Platform.py b/grc/base/Platform.py
index 02d6d2319..51a3b2f87 100644
--- a/grc/base/Platform.py
+++ b/grc/base/Platform.py
@@ -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
diff --git a/grc/base/Port.py b/grc/base/Port.py
index f4e8e5e1f..494ea894f 100644
--- a/grc/base/Port.py
+++ b/grc/base/Port.py
@@ -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):
diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am
index caae6ce75..617a3bf60 100644
--- a/grc/blocks/Makefile.am
+++ b/grc/blocks/Makefile.am
@@ -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 \
diff --git a/grc/blocks/band_pass_filter.xml b/grc/blocks/band_pass_filter.xml
index e2e9acf4e..af083473d 100644
--- a/grc/blocks/band_pass_filter.xml
+++ b/grc/blocks/band_pass_filter.xml
@@ -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>
@@ -118,27 +118,28 @@
</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/band_reject_filter.xml b/grc/blocks/band_reject_filter.xml
index 3b58f0b51..dd5e7a9d7 100644
--- a/grc/blocks/band_reject_filter.xml
+++ b/grc/blocks/band_reject_filter.xml
@@ -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>
@@ -84,27 +84,28 @@
</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
index 000000000..6be7daa22
--- /dev/null
+++ b/grc/blocks/blks2_cvsd_decode.xml
@@ -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
index 000000000..3123b1aa9
--- /dev/null
+++ b/grc/blocks/blks2_cvsd_encode.xml
@@ -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>
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index 5b45466f5..296f0ee91 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -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>
@@ -250,6 +252,11 @@
<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>
<block>gr_probe_density_b</block>
diff --git a/grc/blocks/gr_noise_source_x.xml b/grc/blocks/gr_noise_source_x.xml
index 4fcef5148..4789b4400 100644
--- a/grc/blocks/gr_noise_source_x.xml
+++ b/grc/blocks/gr_noise_source_x.xml
@@ -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>
diff --git a/grc/blocks/gr_sig_source_x.xml b/grc/blocks/gr_sig_source_x.xml
index c329dba67..644cf52d0 100644
--- a/grc/blocks/gr_sig_source_x.xml
+++ b/grc/blocks/gr_sig_source_x.xml
@@ -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>
diff --git a/grc/blocks/high_pass_filter.xml b/grc/blocks/high_pass_filter.xml
index 5be916fa9..0e29cbb36 100644
--- a/grc/blocks/high_pass_filter.xml
+++ b/grc/blocks/high_pass_filter.xml
@@ -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>
@@ -79,27 +79,28 @@
</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/low_pass_filter.xml b/grc/blocks/low_pass_filter.xml
index 27120c047..26435fd4d 100644
--- a/grc/blocks/low_pass_filter.xml
+++ b/grc/blocks/low_pass_filter.xml
@@ -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>
@@ -79,27 +79,28 @@
</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/options.xml b/grc/blocks/options.xml
index 18d6e2f0c..1798a69f8 100644
--- a/grc/blocks/options.xml
+++ b/grc/blocks/options.xml
@@ -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>
diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml
index 477f2ad13..734526793 100644
--- a/grc/blocks/pad_sink.xml
+++ b/grc/blocks/pad_sink.xml
@@ -59,10 +59,7 @@
<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>
diff --git a/grc/blocks/pad_source.xml b/grc/blocks/pad_source.xml
index b6ef2c55d..f44d96238 100644
--- a/grc/blocks/pad_source.xml
+++ b/grc/blocks/pad_source.xml
@@ -59,10 +59,8 @@
<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>
diff --git a/grc/blocks/parameter.xml b/grc/blocks/parameter.xml
index 5d08c4b39..e35b8f4d1 100644
--- a/grc/blocks/parameter.xml
+++ b/grc/blocks/parameter.xml
@@ -45,7 +45,7 @@
</option>
<option>
<name>Int</name>
- <key>int</key>
+ <key>intx</key>
<opt>type:int</opt>
</option>
<option>
@@ -58,6 +58,13 @@
<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
index 000000000..35fb27e67
--- /dev/null
+++ b/grc/blocks/virtual_sink.xml
@@ -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
index 000000000..e0c775449
--- /dev/null
+++ b/grc/blocks/virtual_source.xml
@@ -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>
diff --git a/grc/blocks/wxgui_fftsink2.xml b/grc/blocks/wxgui_fftsink2.xml
index faeca37e3..6f19f1aa4 100644
--- a/grc/blocks/wxgui_fftsink2.xml
+++ b/grc/blocks/wxgui_fftsink2.xml
@@ -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,
@@ -103,6 +104,12 @@ $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
<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>
<value>1024</value>
diff --git a/grc/blocks/wxgui_waterfallsink2.xml b/grc/blocks/wxgui_waterfallsink2.xml
index 79ca356f7..35790f820 100644
--- a/grc/blocks/wxgui_waterfallsink2.xml
+++ b/grc/blocks/wxgui_waterfallsink2.xml
@@ -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,
@@ -75,6 +76,12 @@ $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
<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>
<value>512</value>
diff --git a/grc/examples/Makefile.am b/grc/examples/Makefile.am
index 969485c0d..78321ce0a 100644
--- a/grc/examples/Makefile.am
+++ b/grc/examples/Makefile.am
@@ -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
index 000000000..8d0b385ce
--- /dev/null
+++ b/grc/examples/audio/cvsd_sweep.grc
@@ -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>
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index ff137f669..ee3e19a6c 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -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."""
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index 3695e09ef..f374efde1 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -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),
+)
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index e0c547eba..8fd167869 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -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
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 4add3aa19..8c65bf06f 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -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):
"""
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
index 379c4a6a2..07b8ea7e0 100644
--- a/grc/gui/BlockTreeWindow.py
+++ b/grc/gui/BlockTreeWindow.py
@@ -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
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index 013bcb00f..fabf34ee7 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -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()
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
index 8d764e28e..af40f47c0 100644
--- a/grc/gui/Dialogs.py
+++ b/grc/gui/Dialogs.py
@@ -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()))
diff --git a/grc/gui/Element.py b/grc/gui/Element.py
index 315191723..f0518ee12 100644
--- a/grc/gui/Element.py
+++ b/grc/gui/Element.py
@@ -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
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index f8028f199..8feb171f1 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -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)))
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
index 6d36f4cf7..9fcbe2a6c 100644
--- a/grc/gui/MainWindow.py
+++ b/grc/gui/MainWindow.py
@@ -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
diff --git a/grc/gui/Makefile.am b/grc/gui/Makefile.am
index cb45d5359..b14817d04 100644
--- a/grc/gui/Makefile.am
+++ b/grc/gui/Makefile.am
@@ -43,7 +43,7 @@ ourpython_PYTHON = \
MainWindow.py \
Messages.py \
NotebookPage.py \
- ParamsDialog.py \
+ PropsDialog.py \
Preferences.py \
StateCache.py \
__init__.py
diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py
index cb6b7ed30..fddfeaf5f 100644
--- a/grc/gui/NotebookPage.py
+++ b/grc/gui/NotebookPage.py
@@ -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):
"""
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index a11fd9065..4464a57ab 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -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/Platform.py b/grc/gui/Platform.py
index a32b0209f..8bbfaca23 100644
--- a/grc/gui/Platform.py
+++ b/grc/gui/Platform.py
@@ -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)
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index d1f36f8b9..6763f6cbd 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -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/ParamsDialog.py b/grc/gui/PropsDialog.py
index ccf19d1a2..a7822b228 100644
--- a/grc/gui/ParamsDialog.py
+++ b/grc/gui/PropsDialog.py
@@ -37,70 +37,118 @@ def get_title_label(title):
hbox.pack_start(label, False, False, padding=11)
return hbox
-class ParamsDialog(gtk.Dialog):
- """A dialog box to set block parameters."""
+class PropsDialog(gtk.Dialog):
+ """
+ A dialog to set block parameters, view errors, and view documentation.
+ """
def __init__(self, block):
"""
- SignalBlockParamsDialog contructor.
- @param block the signal 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_CLOSE, gtk.RESPONSE_CLOSE),
+ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT),
)
- self.block = block
+ 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)
+ #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, 7) #spacing
+ 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, 7) #spacing
+ 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 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
+ #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 and show
- self.connect('key_press_event', self._handle_key_press)
+ #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()
- #initial update
- for param in self.block.get_params(): param.update()
- self._update()
- def _update(self):
+ 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.
"""
- self.block.validate()
+ #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()
+ if self._block.is_valid(): self._error_box.hide()
else: self._error_box.show()
- messages = '\n\n'.join(self.block.get_error_messages())
+ 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()
+ if self._block.get_doc(): self._docs_box.show()
else: self._docs_box.hide()
- self._docs_text_display.set_text(self.block.get_doc())
+ self._docs_text_display.set_text(self._block.get_doc())
def _handle_key_press(self, widget, event):
"""
@@ -108,38 +156,16 @@ class ParamsDialog(gtk.Dialog):
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)
+ if event.keyval == gtk.keysyms.Return:
+ self.response(gtk.RESPONSE_ACCEPT)
+ return True #handled here
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.
+ Run the dialog and get its response.
+ @return true if the response was accept
"""
- original_data = list()
- for param in self.block.get_params():
- original_data.append(param.get_value())
- gtk.Dialog.run(self)
+ response = 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
+ return response == gtk.RESPONSE_ACCEPT
diff --git a/grc/gui/StateCache.py b/grc/gui/StateCache.py
index 04b18b18a..3f6b79224 100644
--- a/grc/gui/StateCache.py
+++ b/grc/gui/StateCache.py
@@ -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)
diff --git a/grc/gui/Utils.py b/grc/gui/Utils.py
index ee6dc6cdc..83036a4b8 100644
--- a/grc/gui/Utils.py
+++ b/grc/gui/Utils.py
@@ -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))
diff --git a/grc/python/Block.py b/grc/python/Block.py
index 47fe13a3c..dd39b095d 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -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),
diff --git a/grc/python/Connection.py b/grc/python/Connection.py
index 5eba9f24d..edc18841a 100644
--- a/grc/python/Connection.py
+++ b/grc/python/Connection.py
@@ -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'
diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py
index 8cad8be49..4dd18a81f 100644
--- a/grc/python/FlowGraph.py
+++ b/grc/python/FlowGraph.py
@@ -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
diff --git a/grc/python/Param.py b/grc/python/Param.py
index f971d0c3f..34d5ab116 100644
--- a/grc/python/Param.py
+++ b/grc/python/Param.py
@@ -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
diff --git a/grc/python/Platform.py b/grc/python/Platform.py
index d55dbf4ce..bb56d361b 100644
--- a/grc/python/Platform.py
+++ b/grc/python/Platform.py
@@ -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
diff --git a/grc/python/Port.py b/grc/python/Port.py
index daf8f9ca3..6965371df 100644
--- a/grc/python/Port.py
+++ b/grc/python/Port.py
@@ -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)
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index df346dd16..dce4037d5 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -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()
diff --git a/grc/scripts/usrp2_probe b/grc/scripts/usrp2_probe
index 00d4366dd..38c8f655c 100755
--- a/grc/scripts/usrp2_probe
+++ b/grc/scripts/usrp2_probe
@@ -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)
diff --git a/grc/scripts/usrp_probe b/grc/scripts/usrp_probe
index 6565612c1..d2e92e753 100755
--- a/grc/scripts/usrp_probe
+++ b/grc/scripts/usrp_probe
@@ -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)
diff --git a/grc/todo.txt b/grc/todo.txt
index bb40e1f16..b4e3af39d 100644
--- a/grc/todo.txt
+++ b/grc/todo.txt
@@ -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
@@ -66,15 +67,8 @@
* 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
diff --git a/gruel/src/lib/.gitignore b/gruel/src/lib/.gitignore
index 89a768d46..165e179d6 100644
--- a/gruel/src/lib/.gitignore
+++ b/gruel/src/lib/.gitignore
@@ -2,3 +2,4 @@
/Makefile.in
/.libs
/.deps
+test_gruel
diff --git a/usrp2/firmware/Makefile.am b/usrp2/firmware/Makefile.am
index 62b2d5bad..c75136de1 100644
--- a/usrp2/firmware/Makefile.am
+++ b/usrp2/firmware/Makefile.am
@@ -22,8 +22,8 @@ include $(top_srcdir)/Makefile.common
EXTRA_DIST = \
bootstrap \
configure \
- configure.gnu
-
+ configure.gnu \
+ u2_flash_tool
SUBDIRS = config
diff --git a/usrp2/firmware/configure.gnu b/usrp2/firmware/configure.gnu
index 60d6d2a7e..53ca9b518 100755
--- a/usrp2/firmware/configure.gnu
+++ b/usrp2/firmware/configure.gnu
@@ -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
diff --git a/usrp2/fpga/sdr_lib/dsp_core_rx.v b/usrp2/fpga/sdr_lib/dsp_core_rx.v
index ee713e4ac..af4f0b9fb 100644
--- a/usrp2/fpga/sdr_lib/dsp_core_rx.v
+++ b/usrp2/fpga/sdr_lib/dsp_core_rx.v
@@ -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));
diff --git a/usrp2/fpga/sdr_lib/hb_dec.v b/usrp2/fpga/sdr_lib/hb_dec.v
index b256eb57f..8fb5ba222 100644
--- a/usrp2/fpga/sdr_lib/hb_dec.v
+++ b/usrp2/fpga/sdr_lib/hb_dec.v
@@ -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;
diff --git a/usrp2/fpga/sdr_lib/small_hb_dec.v b/usrp2/fpga/sdr_lib/small_hb_dec.v
index 9957de15a..8519b628a 100644
--- a/usrp2/fpga/sdr_lib/small_hb_dec.v
+++ b/usrp2/fpga/sdr_lib/small_hb_dec.v
@@ -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;
diff --git a/vrt/include/vrt/quadradio.h b/vrt/include/vrt/quadradio.h
index 83323f093..d30ee14f1 100644
--- a/vrt/include/vrt/quadradio.h
+++ b/vrt/include/vrt/quadradio.h
@@ -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);
diff --git a/vrt/lib/quadradio.cc b/vrt/lib/quadradio.cc
index 8cf542e0f..a8bc3e525 100644
--- a/vrt/lib/quadradio.cc
+++ b/vrt/lib/quadradio.cc
@@ -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