From 5d69a524f81f234b3fbc41d49ba18d6f6886baba Mon Sep 17 00:00:00 2001
From: jcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>
Date: Thu, 3 Aug 2006 04:51:51 +0000
Subject: Houston, we have a trunk.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5
---
 gnuradio-examples/python/Makefile.am               |   22 +
 gnuradio-examples/python/apps/README               |   26 +
 gnuradio-examples/python/apps/hf_explorer/README   |   48 +
 gnuradio-examples/python/apps/hf_explorer/hfx2.py  |  786 +++++++++++++++
 gnuradio-examples/python/apps/hf_explorer/hfx_help |  180 ++++
 gnuradio-examples/python/apps/hf_radio/README.TXT  |   53 +
 gnuradio-examples/python/apps/hf_radio/hfir.sci    |   59 ++
 gnuradio-examples/python/apps/hf_radio/input.py    |   41 +
 gnuradio-examples/python/apps/hf_radio/output.py   |   17 +
 gnuradio-examples/python/apps/hf_radio/radio.py    |  304 ++++++
 gnuradio-examples/python/apps/hf_radio/radio.xml   |  441 +++++++++
 gnuradio-examples/python/apps/hf_radio/ssb_taps    | 1023 ++++++++++++++++++++
 gnuradio-examples/python/apps/hf_radio/ssbagc.py   |   48 +
 gnuradio-examples/python/apps/hf_radio/ssbdemod.py |   97 ++
 gnuradio-examples/python/apps/hf_radio/startup.py  |    1 +
 gnuradio-examples/python/apps/hf_radio/ui.py       |  295 ++++++
 gnuradio-examples/python/audio/Makefile.am         |   32 +
 gnuradio-examples/python/audio/audio_copy.py       |   64 ++
 gnuradio-examples/python/audio/audio_play.py       |   57 ++
 gnuradio-examples/python/audio/audio_to_file.py    |   63 ++
 gnuradio-examples/python/audio/dial_squelch.py     |   89 ++
 gnuradio-examples/python/audio/dial_tone.py        |   57 ++
 gnuradio-examples/python/audio/dialtone_v.py       |   71 ++
 gnuradio-examples/python/audio/mono_tone.py        |   66 ++
 gnuradio-examples/python/audio/multi_tone.py       |   90 ++
 .../python/audio/spectrum_inversion.py             |   48 +
 gnuradio-examples/python/audio/test_resampler.py   |   66 ++
 gnuradio-examples/python/digital_voice/Makefile.am |   23 +
 gnuradio-examples/python/digital_voice/encdec.py   |   58 ++
 gnuradio-examples/python/gmsk2/Makefile.am         |   38 +
 gnuradio-examples/python/gmsk2/README              |   81 ++
 .../python/gmsk2/benchmark_gmsk_rx.py              |  128 +++
 .../python/gmsk2/benchmark_gmsk_tx.py              |  146 +++
 .../python/gmsk2/benchmark_mpsk_rx.py              |  149 +++
 .../python/gmsk2/benchmark_mpsk_tx.py              |  157 +++
 gnuradio-examples/python/gmsk2/bpsk.py             |  256 +++++
 gnuradio-examples/python/gmsk2/dbpsk.py            |  282 ++++++
 gnuradio-examples/python/gmsk2/dqpsk.py            |  280 ++++++
 gnuradio-examples/python/gmsk2/fusb_options.py     |   31 +
 gnuradio-examples/python/gmsk2/gen_whitener.py     |   40 +
 gnuradio-examples/python/gmsk2/gmsk_test.py        |  115 +++
 gnuradio-examples/python/gmsk2/mpsk_test.py        |  125 +++
 gnuradio-examples/python/gmsk2/pick_bitrate.py     |  143 +++
 gnuradio-examples/python/gmsk2/qpsk.py             |  418 ++++++++
 gnuradio-examples/python/gmsk2/qpsk_tester.py      |  127 +++
 gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py |  103 ++
 gnuradio-examples/python/gmsk2/receive_path.py     |  150 +++
 gnuradio-examples/python/gmsk2/rx_voice.py         |  132 +++
 gnuradio-examples/python/gmsk2/transmit_path.py    |  108 +++
 gnuradio-examples/python/gmsk2/tunnel.py           |  300 ++++++
 gnuradio-examples/python/gmsk2/tx_voice.py         |  139 +++
 gnuradio-examples/python/mc4020/Makefile.am        |   28 +
 gnuradio-examples/python/mc4020/fm_demod.py        |  150 +++
 gnuradio-examples/python/mc4020/mc4020_fft.py      |   53 +
 .../python/multi-antenna/multi_fft.py              |  128 +++
 .../python/multi-antenna/multi_file.py             |  136 +++
 .../python/multi-antenna/multi_scope.py            |  138 +++
 gnuradio-examples/python/multi_usrp/Makefile.am    |   28 +
 gnuradio-examples/python/multi_usrp/README         |  260 +++++
 .../python/multi_usrp/multi_usrp_oscope.py         |  343 +++++++
 .../python/multi_usrp/multi_usrp_rx_cfile.py       |  131 +++
 .../python/networking/measurement_slave.py         |  241 +++++
 gnuradio-examples/python/usrp/Makefile.am          |   52 +
 gnuradio-examples/python/usrp/am_rcv.py            |  115 +++
 gnuradio-examples/python/usrp/ayfabtu.dat          |  Bin 0 -> 544640 bytes
 gnuradio-examples/python/usrp/ayfabtu.py           |  169 ++++
 gnuradio-examples/python/usrp/benchmark_usb.py     |  106 ++
 gnuradio-examples/python/usrp/dsb_tx.py            |   51 +
 gnuradio-examples/python/usrp/flexrf_debug.py      |  169 ++++
 gnuradio-examples/python/usrp/flexrf_siggen.py     |  148 +++
 gnuradio-examples/python/usrp/fm_tx4.py            |  171 ++++
 .../python/usrp/fm_tx_2_daughterboards.py          |  160 +++
 gnuradio-examples/python/usrp/max_power.py         |   83 ++
 gnuradio-examples/python/usrp/siggen_min2.py       |   62 ++
 gnuradio-examples/python/usrp/test_counting.py     |   53 +
 gnuradio-examples/python/usrp/test_dft_analysis.py |   72 ++
 gnuradio-examples/python/usrp/test_dft_synth.py    |   79 ++
 .../python/usrp/test_digital_loopback_counting.py  |   65 ++
 .../python/usrp/test_digital_loopback_lfsr.py      |   62 ++
 gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py   |  154 +++
 gnuradio-examples/python/usrp/usrp_fft.py          |  251 +++++
 gnuradio-examples/python/usrp/usrp_fft_old.py      |  110 +++
 gnuradio-examples/python/usrp/usrp_nbfm_ptt.py     |  491 ++++++++++
 gnuradio-examples/python/usrp/usrp_nbfm_rcv.py     |  362 +++++++
 gnuradio-examples/python/usrp/usrp_oscope.py       |  252 +++++
 gnuradio-examples/python/usrp/usrp_rx_cfile.py     |  107 ++
 gnuradio-examples/python/usrp/usrp_rx_nogui.py     |  186 ++++
 gnuradio-examples/python/usrp/usrp_siggen.py       |  180 ++++
 gnuradio-examples/python/usrp/usrp_tv_rcv.py       |  394 ++++++++
 gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py |  179 ++++
 gnuradio-examples/python/usrp/usrp_wfm_rcv.py      |  269 +++++
 .../python/usrp/usrp_wfm_rcv2_nogui.py             |  144 +++
 .../python/usrp/usrp_wfm_rcv_nogui.py              |  153 +++
 gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py  |  311 ++++++
 gnuradio-examples/python/usrp/usrp_wxapt_rcv.py    |  267 +++++
 gnuradio-examples/python/usrp/wfm_rcv_file.py      |   99 ++
 96 files changed, 14835 insertions(+)
 create mode 100644 gnuradio-examples/python/Makefile.am
 create mode 100644 gnuradio-examples/python/apps/README
 create mode 100644 gnuradio-examples/python/apps/hf_explorer/README
 create mode 100755 gnuradio-examples/python/apps/hf_explorer/hfx2.py
 create mode 100644 gnuradio-examples/python/apps/hf_explorer/hfx_help
 create mode 100644 gnuradio-examples/python/apps/hf_radio/README.TXT
 create mode 100644 gnuradio-examples/python/apps/hf_radio/hfir.sci
 create mode 100644 gnuradio-examples/python/apps/hf_radio/input.py
 create mode 100644 gnuradio-examples/python/apps/hf_radio/output.py
 create mode 100755 gnuradio-examples/python/apps/hf_radio/radio.py
 create mode 100644 gnuradio-examples/python/apps/hf_radio/radio.xml
 create mode 100644 gnuradio-examples/python/apps/hf_radio/ssb_taps
 create mode 100644 gnuradio-examples/python/apps/hf_radio/ssbagc.py
 create mode 100644 gnuradio-examples/python/apps/hf_radio/ssbdemod.py
 create mode 100644 gnuradio-examples/python/apps/hf_radio/startup.py
 create mode 100755 gnuradio-examples/python/apps/hf_radio/ui.py
 create mode 100644 gnuradio-examples/python/audio/Makefile.am
 create mode 100755 gnuradio-examples/python/audio/audio_copy.py
 create mode 100755 gnuradio-examples/python/audio/audio_play.py
 create mode 100755 gnuradio-examples/python/audio/audio_to_file.py
 create mode 100755 gnuradio-examples/python/audio/dial_squelch.py
 create mode 100755 gnuradio-examples/python/audio/dial_tone.py
 create mode 100755 gnuradio-examples/python/audio/dialtone_v.py
 create mode 100755 gnuradio-examples/python/audio/mono_tone.py
 create mode 100755 gnuradio-examples/python/audio/multi_tone.py
 create mode 100755 gnuradio-examples/python/audio/spectrum_inversion.py
 create mode 100755 gnuradio-examples/python/audio/test_resampler.py
 create mode 100644 gnuradio-examples/python/digital_voice/Makefile.am
 create mode 100755 gnuradio-examples/python/digital_voice/encdec.py
 create mode 100644 gnuradio-examples/python/gmsk2/Makefile.am
 create mode 100644 gnuradio-examples/python/gmsk2/README
 create mode 100755 gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
 create mode 100755 gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
 create mode 100755 gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py
 create mode 100755 gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
 create mode 100644 gnuradio-examples/python/gmsk2/bpsk.py
 create mode 100644 gnuradio-examples/python/gmsk2/dbpsk.py
 create mode 100644 gnuradio-examples/python/gmsk2/dqpsk.py
 create mode 100644 gnuradio-examples/python/gmsk2/fusb_options.py
 create mode 100755 gnuradio-examples/python/gmsk2/gen_whitener.py
 create mode 100755 gnuradio-examples/python/gmsk2/gmsk_test.py
 create mode 100755 gnuradio-examples/python/gmsk2/mpsk_test.py
 create mode 100644 gnuradio-examples/python/gmsk2/pick_bitrate.py
 create mode 100644 gnuradio-examples/python/gmsk2/qpsk.py
 create mode 100644 gnuradio-examples/python/gmsk2/qpsk_tester.py
 create mode 100644 gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py
 create mode 100644 gnuradio-examples/python/gmsk2/receive_path.py
 create mode 100755 gnuradio-examples/python/gmsk2/rx_voice.py
 create mode 100644 gnuradio-examples/python/gmsk2/transmit_path.py
 create mode 100755 gnuradio-examples/python/gmsk2/tunnel.py
 create mode 100755 gnuradio-examples/python/gmsk2/tx_voice.py
 create mode 100644 gnuradio-examples/python/mc4020/Makefile.am
 create mode 100755 gnuradio-examples/python/mc4020/fm_demod.py
 create mode 100755 gnuradio-examples/python/mc4020/mc4020_fft.py
 create mode 100755 gnuradio-examples/python/multi-antenna/multi_fft.py
 create mode 100755 gnuradio-examples/python/multi-antenna/multi_file.py
 create mode 100755 gnuradio-examples/python/multi-antenna/multi_scope.py
 create mode 100644 gnuradio-examples/python/multi_usrp/Makefile.am
 create mode 100644 gnuradio-examples/python/multi_usrp/README
 create mode 100755 gnuradio-examples/python/multi_usrp/multi_usrp_oscope.py
 create mode 100755 gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py
 create mode 100755 gnuradio-examples/python/networking/measurement_slave.py
 create mode 100644 gnuradio-examples/python/usrp/Makefile.am
 create mode 100755 gnuradio-examples/python/usrp/am_rcv.py
 create mode 100644 gnuradio-examples/python/usrp/ayfabtu.dat
 create mode 100755 gnuradio-examples/python/usrp/ayfabtu.py
 create mode 100755 gnuradio-examples/python/usrp/benchmark_usb.py
 create mode 100755 gnuradio-examples/python/usrp/dsb_tx.py
 create mode 100755 gnuradio-examples/python/usrp/flexrf_debug.py
 create mode 100755 gnuradio-examples/python/usrp/flexrf_siggen.py
 create mode 100755 gnuradio-examples/python/usrp/fm_tx4.py
 create mode 100755 gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py
 create mode 100755 gnuradio-examples/python/usrp/max_power.py
 create mode 100755 gnuradio-examples/python/usrp/siggen_min2.py
 create mode 100755 gnuradio-examples/python/usrp/test_counting.py
 create mode 100755 gnuradio-examples/python/usrp/test_dft_analysis.py
 create mode 100755 gnuradio-examples/python/usrp/test_dft_synth.py
 create mode 100755 gnuradio-examples/python/usrp/test_digital_loopback_counting.py
 create mode 100755 gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py
 create mode 100755 gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_fft.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_fft_old.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_nbfm_ptt.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_nbfm_rcv.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_oscope.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_rx_cfile.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_rx_nogui.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_siggen.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_tv_rcv.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py
 create mode 100755 gnuradio-examples/python/usrp/usrp_wxapt_rcv.py
 create mode 100755 gnuradio-examples/python/usrp/wfm_rcv_file.py

(limited to 'gnuradio-examples/python')

diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am
new file mode 100644
index 0000000000..73b7921b27
--- /dev/null
+++ b/gnuradio-examples/python/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+SUBDIRS = audio mc4020 usrp gmsk2 digital_voice multi_usrp
diff --git a/gnuradio-examples/python/apps/README b/gnuradio-examples/python/apps/README
new file mode 100644
index 0000000000..a3f041bfd7
--- /dev/null
+++ b/gnuradio-examples/python/apps/README
@@ -0,0 +1,26 @@
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+This directory servers as the parent directory for various and sundry
+applications such as scanners, HF radios, etc.  Each subdirectory
+shall have a README file that includes a short description of what the
+application does, and a list of hardware dependencies.  E.g., requires
+a USRP with an xyz daughterboard, connected to a footronics magic box.
diff --git a/gnuradio-examples/python/apps/hf_explorer/README b/gnuradio-examples/python/apps/hf_explorer/README
new file mode 100644
index 0000000000..5f780b3d9e
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_explorer/README
@@ -0,0 +1,48 @@
+hfx.py is meant to be a full-featured Long Wave / Medium Wave
+and Short Wave (250kHz to 30Mhz) AM and Single Sideband receiver.
+It uses the USRP with a Basic RX board, and will need an
+antenna and some preamps, about 30db gain will work. See the
+'Help' menu or hfx_help for more info.
+
+----------------------------------------------------------
+
+hfx2.py is a major revision built about complex fir filter
+coeffecients ability and cleaner python script. Inherits
+most features from hfx.py - Powermate knob supported but
+not required, tooltip frequency display, single click
+tuning, AGC, record to disk, play from disk and record audio.
+New feature is ability to tailor the audio passband with two
+sliders over the spectrum display. The sliders almost align
+with the actual frequency. Preset filter settings for LSB
+(-3000 to 0kHz), USB (0 to +3000kHz), CW (-400 to -800Hz)
+and AM (-5kHz from carrier to +5kHz).
+
+AM now switches in a synchronous PLL detector with the
+carriers at 7.5kHz. The PLL carrier is displayed in the
+bottom display and helps show where on the upper spectrum
+the demodulated signal lies. Everything gets shifted up
+7.5kHz in AM, center frequency, tooltips, etc.  The target
+AM carrier needs to be closely tuned in, it will have a
+hollow sound untill it is locked, and then the PLL carrier
+in the bottom display will jump up and remain relatively 
+constant. There is a slider "AM sync carrier" to play with
+different levels to mix with the signal for demodulation.
+The filter in AM is preset to 2500/12500 (7.5kHz +/- 5kHz)
+and is handy for removing adjacent channel interference.
+Change AM_SYNC_DISPLAY in script for whether to show AM
+Sync carrier or not.
+Run with "-h" for command line help with setting USRP 
+ddc center frequency, decimation, rf data record, playback
+and audio data recording.
+
+There are some controls for controlling a varactor and
+tuning an antenna - just ignore them unless you want
+to build a voltage tuned antenna to track frequency.
+
+There is also code for Web based control of frequency and
+volume - so I can tune the radio with an Ipaq from bed.
+Disabled by default - it takes a web server, some
+directories and scripts to use.
+
+
+
diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx2.py b/gnuradio-examples/python/apps/hf_explorer/hfx2.py
new file mode 100755
index 0000000000..c09f962cf6
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_explorer/hfx2.py
@@ -0,0 +1,786 @@
+#!/usr/bin/env python
+# -*- coding: ANSI_X3.4-1968 -*-
+# generated by wxGlade 0.4 on Tue Mar 14 10:16:06 2006
+#
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+#-----------------------------------------------------------------
+#
+#                 +-->(fft)
+#                 |
+# (src)->(xlate)--+->(audio filter)--+-->(sel_am)-+--------------+
+#                                    |            |              |
+#                                    |          (pll)            |
+#                                    |            |              |
+#                                    |   (pll_carrier_scale)     |
+#                                    |            |              |
+#                                    |   (pll_carrier_filter)    |
+#                                    |            |              |
+#                                    |            +--(fft2)      |
+#                                    |            |              |
+#                                    |       +--(c2f3)--+        |
+#                                    |       |          |        |
+#                                    |   (phaser1)  (phaser2)    |
+#                                    |       |          |        |
+#                                    |       +--(f2c)---+        |
+#                                    |            |              V
+#                                    V            +---------->(am_det)
+#                                  (c2f)                         |
+#                                    |                         (c2f2)
+#                                    |                           |
+#                                    +-->(sel_sb)------------>(combine)
+#                                                                |
+#                                                                V
+#                                  +--------------------------(scale)
+#                                  |                             |
+#                                  |                             |
+#                                  |                            +++
+#                                  V                            | |
+#                                (agc)<--(offset)<--(intr)<---(sqr1)
+#                                  |
+#                                  V
+#                                (dst)
+#                                                       
+#----------------------------------------------------------------------
+#
+# Versions 2.2.1 adds loop antenna automatic tuner
+#
+# 2.3.1 adds web control, made AM Sync display optional,
+# added more comments.
+#
+# 2.4.1 updates usrp interface to support auto subdev
+
+# Web server control disabled by default. Do not enable
+# until directory structure and scripts are in place.
+WEB_CONTROL = False
+
+# Controls display of AM Sync Carrier - turn off for smaller
+# window if not needed
+AM_SYNC_DISPLAY = False
+
+import os, wx, sys, math
+import wx.lib.evtmgr as em
+from gnuradio.wxgui import powermate, fftsink
+from gnuradio import gr, audio, eng_notation, usrp, gru
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+ID_BUTTON_1 = wx.NewId()	# LSB button
+ID_BUTTON_2 = wx.NewId()	# USB
+ID_BUTTON_3 = wx.NewId()	# AM
+ID_BUTTON_4 = wx.NewId()	# CW
+ID_BUTTON_5 = wx.NewId()	# Powermate controls: Upper audio freq cutoff
+ID_BUTTON_6 = wx.NewId()	#  "                  Lower audio freq cutoff
+ID_BUTTON_7 = wx.NewId()	#  "                  Frequency 
+ID_BUTTON_8 = wx.NewId()	#  "                  Volume
+ID_BUTTON_9 = wx.NewId()	#  "                  Time
+ID_BUTTON_10 = wx.NewId()	# Time Seek Forwards
+ID_BUTTON_11 = wx.NewId()	# Time Seek Backwards
+ID_BUTTON_12 = wx.NewId()	# Automatic Antenna Tune (AT) enable
+ID_BUTTON_13 = wx.NewId()	# AT Calibrate point
+ID_BUTTON_14 = wx.NewId()	# AT Reset
+ID_TEXT_1 = wx.NewId()		# Band Center, USRP ddc Freq
+ID_SPIN_1 = wx.NewId()		# Frequency display and control
+ID_SLIDER_1 = wx.NewId()	# Upper audio freq cutoff
+ID_SLIDER_2 = wx.NewId()	# Lower audio freq cutoff
+ID_SLIDER_3 = wx.NewId()	# Frequency 
+ID_SLIDER_4 = wx.NewId()	# Volume
+ID_SLIDER_5 = wx.NewId()	# Programmable Gain Amp, PGA, RF gain
+ID_SLIDER_6 = wx.NewId()	# AM Sync carrier level
+ID_SLIDER_7 = wx.NewId()	# AT control voltage output
+ID_EXIT	= wx.NewId()		# Menu Exit
+
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    If there's a daughterboard on A, select A.
+    If there's a daughterboard on B, select B.
+    Otherwise, select A.
+    """
+    if u.db[0][0].dbid() >= 0:       # dbid is < 0 if there's no d'board or a problem
+        return (0, 0)
+    if u.db[1][0].dbid() >= 0:
+        return (1, 0)
+    return (0, 0)
+
+
+class MyFrame(wx.Frame):
+    def __init__(self, *args, **kwds):
+        # begin wxGlade: MyFrame.__init__
+        kwds["style"] = wx.DEFAULT_FRAME_STYLE
+        wx.Frame.__init__(self, *args, **kwds)
+        
+        # Menu Bar
+        self.frame_1_menubar = wx.MenuBar()
+        self.SetMenuBar(self.frame_1_menubar)
+        wxglade_tmp_menu = wx.Menu()
+        self.Exit = wx.MenuItem(wxglade_tmp_menu, ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL)
+        wxglade_tmp_menu.AppendItem(self.Exit)
+        self.frame_1_menubar.Append(wxglade_tmp_menu, "File")
+        # Menu Bar end
+        self.panel_1 = wx.Panel(self, -1)
+        self.button_1 = wx.Button(self, ID_BUTTON_1, "LSB")
+        self.button_2 = wx.Button(self, ID_BUTTON_2, "USB")
+        self.button_3 = wx.Button(self, ID_BUTTON_3, "AM")
+        self.button_4 = wx.Button(self, ID_BUTTON_4, "CW")
+        self.button_5 = wx.ToggleButton(self, ID_BUTTON_5, "Upper")
+        self.slider_1 = wx.Slider(self, ID_SLIDER_1, 0, -15799, 15799, style=wx.SL_HORIZONTAL|wx.SL_LABELS)
+        self.button_6 = wx.ToggleButton(self, ID_BUTTON_6, "Lower")
+        self.slider_2 = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15799, style=wx.SL_HORIZONTAL|wx.SL_LABELS)
+        self.panel_5 = wx.Panel(self, -1)
+        self.label_1 = wx.StaticText(self, -1, " Band\nCenter")
+        self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXT_1, "")
+        self.panel_6 = wx.Panel(self, -1)
+        self.panel_7 = wx.Panel(self, -1)
+        self.panel_2 = wx.Panel(self, -1)
+        self.button_7 = wx.ToggleButton(self, ID_BUTTON_7, "Freq")
+        self.slider_3 = wx.Slider(self, ID_SLIDER_3, 3000, 0, 6000)
+        self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPIN_1, "", min=0, max=100)
+        self.button_8 = wx.ToggleButton(self, ID_BUTTON_8, "Vol")
+        self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 500)
+        self.slider_5 = wx.Slider(self, ID_SLIDER_5, 0, 0, 20)
+        self.button_9 = wx.ToggleButton(self, ID_BUTTON_9, "Time")
+        self.button_11 = wx.Button(self, ID_BUTTON_11, "Rew")
+        self.button_10 = wx.Button(self, ID_BUTTON_10, "Fwd")
+        self.panel_3 = wx.Panel(self, -1)
+        self.label_2 = wx.StaticText(self, -1, "PGA               ")
+        self.panel_4 = wx.Panel(self, -1)
+        self.panel_8 = wx.Panel(self, -1)
+        self.panel_9 = wx.Panel(self, -1)
+        self.label_3 = wx.StaticText(self, -1, "AM Sync\nCarrier")
+        self.slider_6 = wx.Slider(self, ID_SLIDER_6, 50, 0, 200, style=wx.SL_HORIZONTAL|wx.SL_LABELS)
+        self.label_4 = wx.StaticText(self, -1, "Antenna Tune")
+        self.slider_7 = wx.Slider(self, ID_SLIDER_7, 1575, 950, 2200, style=wx.SL_HORIZONTAL|wx.SL_LABELS)
+        self.panel_10 = wx.Panel(self, -1)
+        self.button_12 = wx.ToggleButton(self, ID_BUTTON_12, "Auto Tune")
+        self.button_13 = wx.Button(self, ID_BUTTON_13, "Calibrate")
+        self.button_14 = wx.Button(self, ID_BUTTON_14, "Reset")
+        self.panel_11 = wx.Panel(self, -1)
+        self.panel_12 = wx.Panel(self, -1)
+
+        self.__set_properties()
+        self.__do_layout()
+        # end wxGlade
+
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option ("-c", "--ddc-freq", type="eng_float", default=3.9e6,
+                           help="set Rx DDC frequency to FREQ", metavar="FREQ")
+        parser.add_option ("-a", "--audio_file", default="",
+                           help="audio output file", metavar="FILE")
+        parser.add_option ("-r", "--radio_file", default="",
+                           help="radio output file", metavar="FILE")
+        parser.add_option ("-i", "--input_file", default="",
+                           help="radio input file", metavar="FILE")
+        parser.add_option ("-d", "--decim", type="int", default=250,
+                           help="USRP decimation")
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,                          help="select USRP Rx side A or B (default=first one with a daughterboard)")
+        (options, args) = parser.parse_args ()
+
+        self.usrp_center = options.ddc_freq
+        usb_rate = 64e6 / options.decim
+        self.slider_range = usb_rate * 0.9375
+        self.f_lo = self.usrp_center - (self.slider_range/2)
+        self.f_hi = self.usrp_center + (self.slider_range/2)
+	self.af_sample_rate = 32000
+	fir_decim = long (usb_rate / self.af_sample_rate)
+
+        # data point arrays for antenna tuner
+        self.xdata = []
+        self.ydata = []
+
+	self.fg = gr.flow_graph()
+
+        # radio variables, initial conditions
+        self.frequency = self.usrp_center
+        # these map the frequency slider (0-6000) to the actual range
+        self.f_slider_offset = self.f_lo
+        self.f_slider_scale = 10000/options.decim
+        self.spin_ctrl_1.SetRange(self.f_lo,self.f_hi)
+        self.text_ctrl_1.SetValue(str(int(self.usrp_center)))
+        self.slider_5.SetValue(0) 
+	self.AM_mode = False
+
+        self.slider_3.SetValue((self.frequency-self.f_slider_offset)/self.f_slider_scale)
+        self.spin_ctrl_1.SetValue(int(self.frequency))
+
+        POWERMATE = True
+        try:
+            self.pm = powermate.powermate(self)
+        except:
+            sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n")
+            POWERMATE = False
+
+        if POWERMATE:
+          powermate.EVT_POWERMATE_ROTATE(self, self.on_rotate)
+          powermate.EVT_POWERMATE_BUTTON(self, self.on_pmButton)
+	self.active_button = 7
+
+        # command line options
+        if options.audio_file == "": SAVE_AUDIO_TO_FILE = False
+        else: SAVE_AUDIO_TO_FILE = True
+        if options.radio_file == "": SAVE_RADIO_TO_FILE = False
+        else: SAVE_RADIO_TO_FILE = True
+        if options.input_file == "": self.PLAY_FROM_USRP = True
+        else: self.PLAY_FROM_USRP = False
+
+        if self.PLAY_FROM_USRP:
+           self.src = usrp.source_c(decim_rate=options.decim)
+	   if options.rx_subdev_spec is None:
+              options.rx_subdev_spec = pick_subdevice(self.src)
+           self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec))
+	   self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec)
+           self.src.tune(0, self.subdev, self.usrp_center)
+           self.tune_offset = 0 # -self.usrp_center - self.src.rx_freq(0)
+
+        else:
+           self.src = gr.file_source (gr.sizeof_gr_complex,options.input_file)
+           self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band
+
+        # save radio data to a file
+        if SAVE_RADIO_TO_FILE:
+           file = gr.file_sink(gr.sizeof_gr_complex, options.radio_file)
+           self.fg.connect (self.src, file)
+
+	# 2nd DDC
+        xlate_taps = gr.firdes.low_pass ( \
+           1.0, usb_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING )
+        self.xlate = gr.freq_xlating_fir_filter_ccf ( \
+           fir_decim, xlate_taps, self.tune_offset, usb_rate )
+
+	# Complex Audio filter
+        audio_coeffs = gr.firdes.complex_band_pass (
+                1.0,    # gain
+                self.af_sample_rate, # sample rate
+                -3000,    # low cutoff
+                0,   # high cutoff
+                100,    # transition
+                gr.firdes.WIN_HAMMING)  # window
+	self.slider_1.SetValue(0)
+	self.slider_2.SetValue(-3000)
+
+        self.audio_filter = gr.fir_filter_ccc ( 1, audio_coeffs)
+
+	# Main +/- 16Khz spectrum display
+        self.fft = fftsink.fft_sink_c (self.fg, self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240))
+
+	# AM Sync carrier 
+	if AM_SYNC_DISPLAY:
+	   self.fft2 = fftsink.fft_sink_c (self.fg, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240))
+
+        c2f = gr.complex_to_float()
+
+	# AM branch
+	self.sel_am = gr.multiply_const_cc(0)
+	# the following frequencies turn out to be in radians/sample
+	# gr.pll_refout_cc(alpha,beta,min_freq,max_freq)
+	# suggested alpha = X, beta = .25 * X * X
+	pll = gr.pll_refout_cc(.5,.0625,(2.*math.pi*7.5e3/self.af_sample_rate),(2.*math.pi*6.5e3/self.af_sample_rate))
+	self.pll_carrier_scale = gr.multiply_const_cc(complex(10,0))
+	am_det = gr.multiply_cc()
+	# these are for converting +7.5kHz to -7.5kHz
+	# for some reason gr.conjugate_cc() adds noise ??
+	c2f2 = gr.complex_to_float()
+	c2f3 = gr.complex_to_float()
+	f2c = gr.float_to_complex()
+	phaser1 = gr.multiply_const_ff(1)
+	phaser2 = gr.multiply_const_ff(-1)
+
+	# filter for pll generated carrier
+        pll_carrier_coeffs = gr.firdes.complex_band_pass (
+                2.0,    # gain
+                self.af_sample_rate, # sample rate
+                7400,    # low cutoff
+                7600,   # high cutoff
+                100,    # transition
+                gr.firdes.WIN_HAMMING)  # window
+
+        self.pll_carrier_filter = gr.fir_filter_ccc ( 1, pll_carrier_coeffs)
+
+	self.sel_sb = gr.multiply_const_ff(1)
+	combine = gr.add_ff()
+
+	#AGC
+	sqr1 = gr.multiply_ff()
+	intr = gr.iir_filter_ffd ( [.004, 0], [0, .999] )
+	offset = gr.add_const_ff(1)
+	agc = gr.divide_ff()
+
+
+        self.scale = gr.multiply_const_ff(0.00001)
+        dst = audio.sink(long(self.af_sample_rate))
+
+        self.fg.connect(self.src,self.xlate,self.fft)
+        self.fg.connect(self.xlate,self.audio_filter,self.sel_am,(am_det,0))
+	self.fg.connect(self.sel_am,pll,self.pll_carrier_scale,self.pll_carrier_filter,c2f3)
+	self.fg.connect((c2f3,0),phaser1,(f2c,0))
+	self.fg.connect((c2f3,1),phaser2,(f2c,1))
+	self.fg.connect(f2c,(am_det,1))
+	self.fg.connect(am_det,c2f2,(combine,0))
+	self.fg.connect(self.audio_filter,c2f,self.sel_sb,(combine,1))
+	if AM_SYNC_DISPLAY:
+	  self.fg.connect(self.pll_carrier_filter,self.fft2)
+	self.fg.connect(combine,self.scale)
+	self.fg.connect(self.scale,(sqr1,0))
+	self.fg.connect(self.scale,(sqr1,1))
+	self.fg.connect(sqr1, intr, offset, (agc, 1))
+	self.fg.connect(self.scale,(agc, 0))
+	self.fg.connect(agc,dst)
+
+	if SAVE_AUDIO_TO_FILE:
+	  f_out = gr.file_sink(gr.sizeof_short,options.audio_file)
+	  sc1 = gr.multiply_const_ff(64000)
+	  f2s1 = gr.float_to_short()
+	  self.fg.connect(agc,sc1,f2s1,f_out)
+
+        self.fg.start()
+
+        # for mouse position reporting on fft display
+        em.eventManager.Register(self.Mouse, wx.EVT_MOTION, self.fft.win)
+        # and left click to re-tune
+        em.eventManager.Register(self.Click, wx.EVT_LEFT_DOWN, self.fft.win)
+
+        # start a timer to check for web commands
+        if WEB_CONTROL:
+	   self.timer = UpdateTimer(self, 1000) # every 1000 mSec, 1 Sec
+
+
+	wx.EVT_BUTTON(self,ID_BUTTON_1,self.set_lsb)
+	wx.EVT_BUTTON(self,ID_BUTTON_2,self.set_usb)
+	wx.EVT_BUTTON(self,ID_BUTTON_3,self.set_am)
+	wx.EVT_BUTTON(self,ID_BUTTON_4,self.set_cw)
+	wx.EVT_BUTTON(self,ID_BUTTON_10,self.fwd)
+	wx.EVT_BUTTON(self,ID_BUTTON_11,self.rew)
+        wx.EVT_BUTTON(self, ID_BUTTON_13, self.AT_calibrate)
+        wx.EVT_BUTTON(self, ID_BUTTON_14, self.AT_reset)
+	wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_5,self.on_button)
+	wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_6,self.on_button)
+	wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_7,self.on_button)
+	wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_8,self.on_button)
+	wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_9,self.on_button)
+        wx.EVT_SLIDER(self,ID_SLIDER_1,self.set_filter)
+        wx.EVT_SLIDER(self,ID_SLIDER_2,self.set_filter)
+        wx.EVT_SLIDER(self,ID_SLIDER_3,self.slide_tune)
+        wx.EVT_SLIDER(self,ID_SLIDER_4,self.set_volume)
+	wx.EVT_SLIDER(self,ID_SLIDER_5,self.set_pga)
+	wx.EVT_SLIDER(self,ID_SLIDER_6,self.am_carrier)
+        wx.EVT_SLIDER(self,ID_SLIDER_7,self.antenna_tune)
+        wx.EVT_SPINCTRL(self,ID_SPIN_1,self.spin_tune)
+
+        wx.EVT_MENU(self, ID_EXIT,  self.TimeToQuit)
+
+    def __set_properties(self):
+        # begin wxGlade: MyFrame.__set_properties
+        self.SetTitle("HF Explorer 2")
+        self.slider_1.SetMinSize((450, 38))
+        self.slider_2.SetMinSize((450, 38))
+        self.panel_2.SetMinSize((640, 240))
+        self.button_7.SetValue(1)
+        self.slider_3.SetMinSize((450, 19))
+        self.slider_4.SetMinSize((275, 19))
+        self.slider_5.SetMinSize((275, 19))
+	if AM_SYNC_DISPLAY:
+           self.panel_9.SetMinSize((640, 240))
+        self.slider_6.SetMinSize((300, 38))
+        self.slider_7.SetMinSize((400, 38))
+        # end wxGlade
+
+    def __do_layout(self):
+        # begin wxGlade: MyFrame.__do_layout
+        sizer_1 = wx.BoxSizer(wx.VERTICAL)
+        grid_sizer_1 = wx.FlexGridSizer(11, 2, 0, 0)
+        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_6 = wx.BoxSizer(wx.VERTICAL)
+        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
+        grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
+        sizer_2.Add(self.button_1, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_2.Add(self.button_2, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_2.Add(self.button_3, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_2.Add(self.button_4, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.button_5, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.slider_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.button_6, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.slider_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0)
+        sizer_6.Add(self.panel_5, 1, wx.EXPAND, 0)
+        sizer_6.Add(self.label_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0)
+        sizer_6.Add(self.text_ctrl_1, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_6.Add(self.panel_6, 1, wx.EXPAND, 0)
+        sizer_6.Add(self.panel_7, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(sizer_6, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.button_7, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_3.Add(self.slider_3, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_3.Add(self.spin_ctrl_1, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.button_8, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_4.Add(self.slider_4, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_4.Add(self.slider_5, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(sizer_4, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.button_9, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_5.Add(self.button_11, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_5.Add(self.button_10, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_5.Add(self.panel_3, 1, wx.EXPAND, 0)
+        sizer_5.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_5.Add(self.panel_4, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(sizer_5, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.panel_8, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.panel_9, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.label_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.slider_6, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.label_4, 0, wx.ALIGN_BOTTOM|wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.slider_7, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.panel_10, 1, wx.EXPAND, 0)
+        sizer_7.Add(self.button_12, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_7.Add(self.button_13, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_7.Add(self.button_14, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_7.Add(self.panel_11, 1, wx.EXPAND, 0)
+        sizer_7.Add(self.panel_12, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(sizer_7, 1, wx.EXPAND, 0)
+        sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0)
+        self.SetAutoLayout(True)
+        self.SetSizer(sizer_1)
+        sizer_1.Fit(self)
+        sizer_1.SetSizeHints(self)
+        self.Layout()
+        # end wxGlade
+
+    # Menu exit
+    def TimeToQuit(self, event):
+        self.fg.stop()
+        self.Close(True)
+
+    # Powermate being turned
+    def on_rotate(self, event):
+	if self.active_button == 5:
+	   self.slider_1.SetValue(self.slider_1.GetValue()+event.delta)
+           if self.slider_2.GetValue() > (self.slider_1.GetValue() - 200) :
+              self.slider_2.SetValue(self.slider_1.GetValue() - 200)
+	   self.filter()
+	if self.active_button == 6:
+	   self.slider_2.SetValue(self.slider_2.GetValue()+event.delta)
+	   if self.slider_1.GetValue() < (self.slider_2.GetValue() + 200) :
+	      self.slider_1.SetValue(self.slider_2.GetValue() + 200)
+	   self.filter()
+	if self.active_button == 7:
+           new = max(0, min(6000, self.slider_3.GetValue() + event.delta))
+           self.slider_3.SetValue(new)
+           self.frequency = (self.f_slider_scale * new) + self.f_slider_offset
+           self.spin_ctrl_1.SetValue(self.frequency)
+	   if self.AM_mode == False:
+             self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset))
+	   else:
+	     self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3))
+	   if self.button_12.GetValue():
+	      self.auto_antenna_tune()
+	if self.active_button == 8:
+           new = max(0, min(500, self.slider_4.GetValue() + event.delta))
+           self.slider_4.SetValue(new)
+           self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.)))
+	if self.active_button == 9:
+           if self.PLAY_FROM_USRP == False:
+              if event.delta == -1:
+                 self.src.seek(-1000000,gr.SEEK_CUR)
+              elif event.delta == 1:
+                 self.src.seek(1000000,gr.SEEK_CUR)
+
+
+    # Powermate pressed to switch controlled function
+    def on_pmButton(self, event):
+	if event.value == 0:
+	   if self.active_button == 5:
+	      self.active_button = 6
+	      self.button_5.SetValue(False)
+	      self.button_6.SetValue(True)
+	   elif self.active_button == 6:
+	      self.active_button = 7
+	      self.button_6.SetValue(False)
+	      self.button_7.SetValue(True)
+	   elif self.active_button == 7:
+	      self.active_button = 8
+	      self.button_7.SetValue(False)
+	      self.button_8.SetValue(True)
+	   elif self.active_button == 8:
+	      self.active_button = 9
+	      self.button_8.SetValue(False)
+	      self.button_9.SetValue(True)
+	   elif self.active_button == 9:
+	      self.active_button = 5
+	      self.button_9.SetValue(False)
+	      self.button_5.SetValue(True)
+
+    # Clicking one PM control button turns the rest off
+    def on_button(self, event):
+	id = event.GetId()
+	if id == ID_BUTTON_5:
+	   self.active_button = 5
+	   self.button_6.SetValue(False)
+	   self.button_7.SetValue(False)
+	   self.button_8.SetValue(False)
+	   self.button_9.SetValue(False)
+	if id == ID_BUTTON_6:
+	   self.active_button = 6
+           self.button_5.SetValue(False)
+           self.button_7.SetValue(False)
+           self.button_8.SetValue(False)
+           self.button_9.SetValue(False)
+        if id == ID_BUTTON_7:
+           self.active_button = 7
+           self.button_5.SetValue(False)
+           self.button_6.SetValue(False)
+           self.button_8.SetValue(False)
+           self.button_9.SetValue(False)
+        if id == ID_BUTTON_8:
+           self.active_button = 8
+           self.button_5.SetValue(False)
+           self.button_6.SetValue(False)
+           self.button_7.SetValue(False)
+           self.button_9.SetValue(False)
+        if id == ID_BUTTON_9:
+           self.active_button = 9
+           self.button_5.SetValue(False)
+           self.button_6.SetValue(False)
+           self.button_7.SetValue(False)
+           self.button_8.SetValue(False)
+
+    # Make sure filter settings are legal
+    def set_filter(self, event):
+        slider = event.GetId()
+        slider1 = self.slider_1.GetValue()
+        slider2 = self.slider_2.GetValue()
+        if slider == ID_SLIDER_1:
+           if slider2 > (self.slider_1.GetValue() - 200) :
+              self.slider_2.SetValue(slider1 - 200)
+        elif slider == ID_SLIDER_2:
+           if slider1 < (self.slider_2.GetValue() + 200) :
+              self.slider_1.SetValue(slider2 + 200)
+	self.filter()
+
+    # Calculate taps and apply
+    def filter(self):
+        audio_coeffs = gr.firdes.complex_band_pass (
+                1.0,    # gain
+                self.af_sample_rate, # sample rate
+                self.slider_2.GetValue(),    # low cutoff
+                self.slider_1.GetValue(),   # high cutoff
+                100,    # transition
+                gr.firdes.WIN_HAMMING)  # window
+        self.audio_filter.set_taps(audio_coeffs)
+
+    def set_lsb(self, event):
+	self.AM_mode = False
+	self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset))
+	self.sel_sb.set_k(1)
+	self.sel_am.set_k(0)
+	self.slider_1.SetValue(0)
+	self.slider_2.SetValue(-3000)
+	self.filter()
+
+    def set_usb(self, event):
+	self.AM_mode = False
+	self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset))
+	self.sel_sb.set_k(1)
+	self.sel_am.set_k(0)
+	self.slider_1.SetValue(3000)
+	self.slider_2.SetValue(0)
+	self.filter()
+
+    def set_am(self, event):
+	self.AM_mode = True
+	self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3))
+	self.sel_sb.set_k(0)
+	self.sel_am.set_k(1)
+	self.slider_1.SetValue(12500)
+	self.slider_2.SetValue(2500)
+	self.filter()
+
+    def set_cw(self, event):
+	self.AM_mode = False
+	self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset))
+	self.AM_mode = False
+	self.sel_sb.set_k(1)
+	self.sel_am.set_k(0)
+	self.slider_1.SetValue(-400)
+	self.slider_2.SetValue(-800)
+	self.filter()
+
+    def set_volume(self, event):
+        self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.)))
+
+    def set_pga(self,event):
+	if self.PLAY_FROM_USRP:
+	   self.subdev.set_gain(self.slider_5.GetValue())
+
+    def slide_tune(self, event):
+        self.frequency = (self.f_slider_scale * self.slider_3.GetValue()) + self.f_slider_offset
+	if self.AM_mode == False:
+          self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset))
+	else:
+	  self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3))
+        self.spin_ctrl_1.SetValue(self.frequency)
+	if self.button_12.GetValue():
+	   self.auto_antenna_tune()
+
+    def spin_tune(self, event):
+	self.frequency = self.spin_ctrl_1.GetValue()
+	if self.AM_mode == False:
+           self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset))
+	else:
+	   self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3))
+        self.slider_3.SetValue(int((self.frequency-self.f_slider_offset)/self.f_slider_scale))
+	if self.button_12.GetValue():
+	   self.auto_antenna_tune()
+
+    # Seek forwards in file
+    def fwd(self, event):
+	if self.PLAY_FROM_USRP == False:
+	   self.src.seek(10000000,gr.SEEK_CUR)
+
+    # Seek backwards in file
+    def rew(self, event):
+	if self.PLAY_FROM_USRP == False:
+	   self.src.seek(-10000000,gr.SEEK_CUR)
+
+    # Mouse over fft display - show frequency in tooltip
+    def Mouse(self,event):
+	if self.AM_mode:
+	   fRel = ( event.GetX() - 330. ) / 14.266666 - 7.5
+	else:
+	   fRel = ( event.GetX() - 330. ) / 14.266666 
+        self.fft.win.SetToolTip(wx.ToolTip(eng_notation.num_to_str(self.frequency + (fRel*1e3))))
+
+    # Mouse clicked on fft display - change frequency 
+    def Click(self,event):
+        fRel = ( event.GetX() - 330. ) / 14.266666
+	if self.AM_mode == False:
+           self.frequency = self.frequency + (fRel*1e3)
+	else:
+	   self.frequency = self.frequency + (fRel*1e3) - 7.5e3
+        self.spin_ctrl_1.SetValue(int(self.frequency))
+        self.slider_3.SetValue(int((self.frequency-self.f_slider_offset)/self.f_slider_scale))
+        if self.AM_mode == False:
+	   self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset ))
+	else:
+	   self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3))
+
+    # Set power of AM sync carrier
+    def am_carrier(self,event):
+	scale = math.pow(10,(self.slider_6.GetValue())/50.)
+	self.pll_carrier_scale.set_k(complex(scale,0))
+
+    # Reset AT data and start calibrate over
+    def AT_reset(self, event):
+        self.xdata = []
+        self.ydata = []
+
+    # Save AT setting for a particular frequency
+    def AT_calibrate(self, event):
+        self.xdata.append(float(self.frequency))
+        self.ydata.append(self.slider_7.GetValue())
+        if len(self.xdata) > 1:
+          self.m = []
+          self.b = []
+          for i in range(0,len(self.xdata)-1):
+            self.m.append( (self.ydata[i+1] - self.ydata[i]) / (self.xdata[i+1] - self.xdata[i]) )
+            self.b.append( self.ydata[i] - self.m[i] * self.xdata[i] )
+
+    # Lookup calibrated points and calculate interpolated antenna tune voltage.
+    # This is to automatically tune a narrowband loop antenna when the freq
+    # is changed, to keep signals peaked.
+    def auto_antenna_tune(self):
+        for i in range(0,len(self.xdata)-1):
+          if (self.frequency > self.xdata[i]) & (self.frequency < self.xdata[i+1]):
+            self.slider_7.SetValue(self.m[i]*self.frequency + self.b[i])
+        self.antenna_tune(0)
+
+    # Slider to set loop antenna capacitance
+    def antenna_tune(self, evt):
+        if self.PLAY_FROM_USRP:
+           self.src.write_aux_dac(0,3,self.slider_7.GetValue())
+
+    # Timer events - check for web commands
+    def OnUpdate(self):
+      cmds = os.listdir("/var/www/cgi-bin/commands/")
+      if cmds!=[]:
+        if cmds[0]=='chfreq':
+          fd=open("/var/www/cgi-bin/commands/chfreq","r")
+          new=fd.readline()
+          fd.close()
+          if new!='':
+            os.unlink("/var/www/cgi-bin/commands/chfreq")
+            if ( int(new) >= self.f_lo ) & ( int(new) <= self.f_hi ):
+               self.frequency = int(new)
+               self.slider_3.SetValue(( self.frequency - self.f_slider_offset) / self.f_slider_scale )
+               self.spin_ctrl_1.SetValue(self.frequency)
+               if self.button_12.GetValue():
+                 self.auto_antenna_tune()
+               if self.AM_mode:
+                 self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset - 7.5e3 ))
+               else:
+                 self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset ))
+
+        if cmds[0]=='chvolume':
+          fd=open("/var/www/cgi-bin/commands/chvolume","r")
+          new=fd.readline()
+          fd.close()
+          if new!='':
+            os.unlink("/var/www/cgi-bin/commands/chvolume")
+            if ( int(new) >= 0 ) & ( int(new) <= 500 ):
+               self.volume = int(new)
+               self.slider_4.SetValue(self.volume)
+               self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.)))
+
+      else: # no new web commands, update state
+        fh = open("/var/www/cgi-bin/state/freq","w")
+        fh.write(str(int(self.frequency))+'\n')
+        fh.close()
+        fh = open("/var/www/cgi-bin/state/volume","w")
+        fh.write(str(self.slider_4.GetValue())+'\n')
+        fh.close()
+
+
+# end of class MyFrame
+
+# wx.Timer to check for web updates
+class UpdateTimer(wx.Timer):
+    def __init__(self, target, dur=1000):
+        wx.Timer.__init__(self)
+        self.target = target
+        self.Start(dur)
+
+    def Notify(self):
+        """Called every timer interval"""
+        if self.target:
+            self.target.OnUpdate()
+
+
+class MyApp(wx.App):
+  def OnInit(self):
+    frame = MyFrame(None, -1, "HF Explorer 2")
+    frame.Show(True)
+    self.SetTopWindow(frame)
+    return True
+
+app = MyApp(0)
+app.MainLoop()
+
diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx_help b/gnuradio-examples/python/apps/hf_explorer/hfx_help
new file mode 100644
index 0000000000..9a52dd2bb0
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_explorer/hfx_help
@@ -0,0 +1,180 @@
+
+		HF Explorer Help
+
+	-----------------------------------------------------------------------
+
+ Command Line Switches:
+
+	-c	DDC center frequency, set band.
+		-c 7.2e6 or -c 7.2M for 40 meter ham band.
+		Default is 3.9e6 80 meter ham band.
+		Example:
+
+		hfx.py -c 9500k 
+
+		starts up in the 31 meter band.
+
+	-a	Audio output file. Output file for 32kHz two channel
+		signed word audio. Two channels are used for
+		independent sideband. This file can be converted
+		to a wav file with sox. Example:
+
+		sox -c 2 -r 3200 file.sw file.wav
+
+		sox needs the .sw extension to indicate file type.
+		If not specified no audio file is created.
+
+	-r	Radio output file. File to write RF data to for later
+		demodulation. Records the entire band to disk, width
+		determined by sample rate/decimation. Be sure to
+		note the decimation and center freq for later use!
+		Example:
+
+		hfx.py -c 900e3 -d 80 -r rf_data_AM-c900e3-d80
+
+		writes a pre-demod rf file centered on 900kHz with a
+		bandwidth of 800kHz (That's 80 AM stations!). The
+		center and decimation could be put in the filename for
+		proper use later.
+		If not specified no rf data file is created.
+		At default 250 decimation disk usage is about
+		8Gb / hour.
+
+	-i	Radio input file. Use to play back a previously
+		recorded rf data file. Example:
+
+		hfx.py -c 900e3 -d 80 -i rf_data_AM-c900e3-d80
+
+		plays back the previously recorded band, no
+		usrp hardware needed. Tune about the 800kHz wide band.
+		When playing a recorded file, time controls
+		fast-forward and rewind are available.
+		
+	-d	Decimation. Sets sample rate and bandwidth.
+		This is the factor that the usrp sample rate, 64e6,
+		is divided by. Default is 250 for 256kHz bandwidth
+		which is enough to record a ham band without 
+		eating up disk space too fast. The 64e6 sample
+		rate limits the upper practical frequency to 32MHz.
+		The Basic RX transformer limits the lower frequency
+		to about 200kHz. 
+
+
+ Powermate Knob:
+
+	A Powermate knob is recommended but not necessary. If a knob
+	is used, it is in one of 3 or 4 modes controlling frequency,
+	volume, filter and (if playing a recorded file) time.
+	Pushing the knob switches mode and the buttons on the HFX panel
+	change to show which mode is in effect. Then just turn the knob
+	to set frequency, volume, filter or go fast forward or rewind.
+
+
+ Bandswitch:
+
+        Across the top are a set of predefined bands and buttons
+        to rapidly switch to the center of that band. To change a band,
+        type the frequency in Hz into the box under "Center Frequency",
+        then press "Set" on the left, then the button you want to
+        program. From then on (untill the program is exited) pushing
+        that button takes you to that band.  To make a band button
+        permenant edit the hfx.py script with whatever frequency you
+        want assigned to what button.
+
+
+ Frequency:
+
+	There are 6 ways to set the frequency.
+	1) Move the slider with the mouse
+	2) Use the Spin Control up/down arrows (very fine 1Hz control)
+	3) Type the frequency in Hz into the Spin Control
+	4) Turn the Powermate knob
+	5) Web control.
+	6) Clicking on the FFT display to set demod center. This is very
+	   convenient for tuning +-15kHz when you see a signal on the
+	   display. If in Lower Sideband, clicking just to the right of
+	   a signal will tune to it immediately. Clicking several times
+	   on the far right right or left of the display will rapidly
+	   tune up or down the band.
+
+
+ Volume:
+
+	Move the volume slider with the mouse, or push the Powermate knob
+	untill the volume button is active, or click on the volume button,
+	then turn the knob. Volume can also be set by web control if web
+	control is setup and enabled.
+
+
+ Filter:
+
+	Similar to volume, switches in any of 30 audio filters from 600
+	to 3600Hz in Sideband or up to 5kHz in AM.
+
+
+ Mode:
+
+	Demodulation modes are chosen by clicking on the buttons for
+	Lower Sideband, Upper Sideband, or AM.
+
+
+ PGA:
+
+	PGA slider sets the rf gain in the Analog-to-Digital converter
+	before digitizing. 0 to 20db gain easily shows up on the FFT
+	display.
+
+
+ Time:
+
+	When playing back a recorded RF data file, you can enjoy the
+	freedom of rewinding or fast-forwarding. Replay a weak signal
+	or skip through annoying AM commercials.
+
+
+ Antennas and Preamps:
+
+	The USRP Basic RX board is not sensitive enough for anything but
+	the strongest signals. In my experience about 40 db of small
+	signal gain is required to make the HFX as sensitive as other
+	receivers. Some working amplifiers are the Ramsey PR-2 with 20db
+	gain, fairly low noise and more bandwidth than we can use here.
+	Also the amp modules from Advanced Receiver Research are nice.
+	I use an ARR 7-7.4MHz GaAsFET 29db amp with .5db noise at the
+	apex of a 40 meter dipole with excellent results. Another
+	amp I like is a Minicircuits ZHL-32A 29db amp but they are
+	expensive and hard to find. Also it may help to use some filters
+	to keep strong local signals from the ADC, or limit rf input
+	to the band of interest, etc.  
+	Resonant outdoor antennas, like a dipole, in a low-noise (away
+	from consumer electronics) environment are nice.  Long random wires
+	with a tuner work. I like a small indoor tuned loop made from 10ft
+	of 1/4" copper tube, a 365pf tuning cap and a pickup loop connected
+	to rg-58. 
+
+
+ Web Control:
+
+	To control your radio remotely, ensure you have a web server
+	(Apache, etc) working and a compatible directory structure in
+	place. Directories /var/www/cgi-bin/commands and
+	/var/www/cgi-bin/state must already exist. You will need a
+	home page with forms and a set of scripts to put commands in
+	and put the current state on the home page. email me for further
+	help. Setting WEB_CONTROL to True in hfx.py turns on the timers
+	that check for commands and update the state.
+
+
+ IF Output:
+
+	There is a provision for outputting un-demodulated complex 
+	through the audio out in stereo for use with Digital Radio
+	Mondial (DRM) or using a seperate demodulation program like
+	SDRadio (by I2PHD).
+	Set IF_OUTPUT to True in weaver_isb_am1_usrp4.py.
+
+
+ --Good luck and happy LW/MW/SW Exploring.
+	Chuck
+        chuckek@musicriver.homeunix.com
+
diff --git a/gnuradio-examples/python/apps/hf_radio/README.TXT b/gnuradio-examples/python/apps/hf_radio/README.TXT
new file mode 100644
index 0000000000..df8a901e41
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/README.TXT
@@ -0,0 +1,53 @@
+The files in this directory implement a fairly simple HF radio that works
+with the basic rx daughter board on the USRP.
+
+Many thanks to the Gnu Radio folks for a great new way to waste large blocks 
+of time in infinitely tweaking a huge number of free parameters.
+
+Start the receiver by running the radio.py in this directory. Or from the 
+Python prompt type "from radio import *" and you'll get the prompt back
+with the receiver running. You can then poke around to see what's going on.
+
+There are two spectrum displays. One is the output of the USRP and displays
+about 300KHz of bandwidth centered at the current tuning freq. The other
+displays the output spectrum of the demodulator.
+
+The demodulator does AM demod using the complex modulus block from gr. It 
+does SSB demod using the frequency translating fir filter as a complex
+hilbert transformer. The taps for this filter were generated using a program
+called Scilab and the Scilab program in the file hfir.sci. More details in
+the associated files.
+
+Tune the receiver using the spin buttons under the big frequency display.
+
+The agc block is a roll your own. The standard agc in the newer CVS updates
+seems to work but doesn't seem to have adjustable time constants or provide
+access to internal signal nodes which are used for the RSSI.
+
+The AGC authority (a sort of gain parameter) and the reference level used
+in the power to dB computagion can be adjusted using the spin buttons.
+
+The audio bandwidth can be similarly adjusted from about 50Hz to 10KHz.
+
+The GUI layout was produced using wxGlade. The file radio.xml is the GUI
+specification. It will produce a file called ui.py which is subclassed
+by classes defined in radio.py. The ui.py is purely generated by wxGlade
+all app specific code for the GUI is in radio.py. 
+
+Most of the actual signal processing code is built up in the other included
+files using the hierarchical block facilities. This organization should
+make it easier to tweak to your heart's content.
+
+Known bugs weakness and other
+
+wxPython and wxGlade seem to conspire to insure that the layout can never
+be exactly what you have in mind.
+
+Some of the controls don't behave as one might like. wx spin controls 
+and spin boxes only support integers so it is rather a nuisance to make
+units come out nice. In the process of development I came up with a reasonable
+kluge so there is a mixture of approaches.
+
+Enjoy.
+
+M. Revnell 2006-Jan-06
diff --git a/gnuradio-examples/python/apps/hf_radio/hfir.sci b/gnuradio-examples/python/apps/hf_radio/hfir.sci
new file mode 100644
index 0000000000..a2d5e2a620
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/hfir.sci
@@ -0,0 +1,59 @@
+// designs a complex tap fir filter akin to the hilbert transformer.
+//
+// The hilbert transformer is classified as a linear phase fir
+// with allpass magnitude response and 90 degree phase response for
+// positive frequencies and -90 degrees phase for negative frequencies.
+// Or, if you prefer, normalized frequencies between .5 and 1 since
+// negative frequencies don't really have much meaning outside the complex
+// domain.
+//
+// Normally one would use the hilbert transformer in one leg of a complex
+// processing block and a compensating delay in the other.
+//
+// This one differs in the following respects:
+//  It is low pass with a cutoff of .078125
+//  The filter is a lowpass kaiser windowed filter with parameter 3
+//  The phase response is 45 degrees for positive frequencies and -45
+//   for negative frequencies.
+//  The coefficent set is used in one path and the same coefficients
+//   are used time reversed in the other. This results in the net effect
+//   of +/- 90 degrees as in the usual hilbert application.
+//
+// The coefficient set can be used in the gnuradio frequency translating
+// fir filter for ssb demodulation.
+//
+// This isn't as computationally efficient as using the hilbert transformer
+// and compensating delay but fascinating none the less.
+//
+// This program is for the scilab language a very powerful free math 
+// package similar to Matlab with infinitely better price/performace.
+//
+// compute the prototype lowpass fir
+// length is 255 (odd) for the same symmetry reasons as the hilbert transformer
+
+len = 1023;
+l2 = floor(len/2);
+md = l2 + 1;
+l3 = md + 1;
+
+h = wfir( 'lp', len, [10.0/256 0], 'kr', [3 0] );
+
+H = fft(h);
+
+H(1:l2)=H(1:l2)*exp(%i*%pi/4);
+H(md)=0+%i*0;
+H(l3:len)=H(l3:len)*exp(-%i*%pi/4);
+
+j=real(ifft(H));
+k(1:len)=j(len:-1:1);
+x=j+%i.*k;
+X=fft(x);
+plot(abs(X))
+
+f = file('open','taps')
+for i=(1:len)
+  fprintf( f, '%f%+fj', j(i), k(i) )
+end
+
+file('close',f)
+
diff --git a/gnuradio-examples/python/apps/hf_radio/input.py b/gnuradio-examples/python/apps/hf_radio/input.py
new file mode 100644
index 0000000000..3a62a68cc7
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/input.py
@@ -0,0 +1,41 @@
+# Basic USRP setup and control.
+# It's only ever been tried with a basic rx daughter card.
+#
+# Imagine that the gnuradio boilerplate is here.
+#
+# M. Revnell 2005-Dec
+ 
+from gnuradio import gr, gru, optfir
+from gnuradio import usrp
+import usrp_dbid
+import math
+
+# Put special knowlege of usrp here.
+
+class input:
+    def __init__( self, decim ):
+        self.freq = -2.5e6
+        self.src = usrp.source_c( )
+        self.subdev = usrp.pick_subdev( self.src,
+                                        (usrp_dbid.BASIC_RX,
+                                         usrp_dbid.TV_RX))
+
+        print self.subdev
+
+        self.subdevice = usrp.selected_subdev( self.src,
+                                               self.subdev )
+
+        self.mux = usrp.determine_rx_mux_value( self.src,
+                                                self.subdev )
+        self.decim = decim
+
+        self.adc_rate = self.src.adc_rate()
+        self.usrp_rate = self.adc_rate / self.decim
+        self.src.set_decim_rate( self.decim )
+        self.src.set_mux( self.mux )
+        usrp.tune( self.src, 0, self.subdevice, self.freq )
+
+    def set_freq( self, x ):
+        r = usrp.tune( self.src, 0, self.subdevice, -x )
+        if r:
+            self.freq = -x
diff --git a/gnuradio-examples/python/apps/hf_radio/output.py b/gnuradio-examples/python/apps/hf_radio/output.py
new file mode 100644
index 0000000000..dc9caf5288
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/output.py
@@ -0,0 +1,17 @@
+# Audio output with a volume control.
+#
+# M. Revnell 2005-Dec
+
+from gnuradio import gr, gru
+from gnuradio import audio
+
+class output( gr.hier_block ):
+    def __init__( self, fg, rate ):
+        self.out = audio.sink( rate )
+        self.vol = gr.multiply_const_ff( 0.1 )
+        fg.connect( self.vol, self.out )
+        gr.hier_block.__init__(self, fg, self.vol, None )
+
+    def set( self, val ):
+        self.vol.set_k( val )
+        
diff --git a/gnuradio-examples/python/apps/hf_radio/radio.py b/gnuradio-examples/python/apps/hf_radio/radio.py
new file mode 100755
index 0000000000..9f444b9169
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/radio.py
@@ -0,0 +1,304 @@
+#!/usr/bin/env python
+
+# GUI interactions and high level connections handled here.
+#
+# Interacts with classes defined by wxGlade in ui.py.
+#
+# The usual gnuradio copyright boilerplate incorperated here by reference.
+#
+# M. Revnell 2006-Jan
+
+from threading import *
+import wx
+import wx.lib.evtmgr as em
+import time
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.wxgui import fftsink
+from gnuradio.wxgui import waterfallsink
+from gnuradio.wxgui import scopesink
+
+from input    import *
+from output   import *
+from ssbdemod import *
+from ssbagc   import *
+from ui       import *
+from math     import log10
+
+class graph( gr.hier_block ):
+    def __init__( self, fg ):
+        self.graph        = fg
+        self.fe_decim     = 250
+        self.src          = input( self.fe_decim )
+        self.adc_rate     = self.src.adc_rate
+        self.fe_rate      = self.adc_rate / self.fe_decim
+        self.filter_decim = 1
+        self.audio_decim  = 16
+        self.demod_rate   = self.fe_rate / self.filter_decim
+        self.audio_rate   = self.demod_rate / self.audio_decim
+
+        self.demod        = ssb_demod( fg, self.demod_rate, self.audio_rate )
+        self.agc          = agc( fg )
+        #self.agc          = gr.agc_ff()
+        self.out          = output( fg, self.audio_rate )
+
+        fg.connect( self.src.src,
+                    self.demod,
+                    self.agc,
+                    self.out )
+
+        gr.hier_block.__init__( self, fg, None, None )
+
+    def tune( self, freq ):
+        fe_target = -freq
+        self.src.set_freq( fe_target )
+        fe_freq = self.src.src.rx_freq( 0 )
+        demod_cf = fe_target - fe_freq
+        self.demod.tune( demod_cf )
+
+class radio_frame( ui_frame ):
+    def __init__( self, block, *args, **kwds ):
+        ui_frame.__init__( self, *args, **kwds )
+        self.block = block
+        self.freq_disp.SetRange(0, 30e6)
+        f = self.block.src.freq
+        self.freq_disp.SetValue( -f )
+        self.volume.SetRange( 0, 20 )
+        self.pga.SetRange( 0, 20 )
+        self.rssi_range = 1
+        self.rssi.SetRange( self.rssi_range )
+        self.agc_max.SetValue( str( self.rssi_range ) )
+        self.spin_e0.SetValue( 50 )
+        self.spin_e1.SetValue( 50 )
+        self.spin_e2.SetValue( 50 )
+        self.spin_e3.SetValue( 50 )
+        self.spin_e4.SetValue( 50 )
+        self.spin_e5.SetValue( 50 )
+        self.spin_e6.SetValue( 50 )
+        bw = 3.3e3
+        self.bandwidth.SetValue( str( bw ) )
+        self.block.demod.set_bw( bw )
+        self.bw_spin.SetValue( 5 )
+        agc_gain = self.block.agc.gain.k()
+        self.agc_gain_s.SetValue( 5 )
+        self.agc_gain.SetValue( str( agc_gain ) )
+        agc_ref = self.block.agc.offs.k()
+        self.agc_ref.SetValue( str( agc_ref ) )
+        self.agc_ref_s.SetValue( 5 )
+
+        self.fespectrum = fftsink.fft_sink_c(
+            self.block.graph,
+            self.fe_panel,
+            fft_size=512,
+            sample_rate = block.fe_rate,
+            baseband_freq = 0,
+            average = False,
+            size = ( 680, 140 ) )
+
+        self.ifspectrum = fftsink.fft_sink_c(
+            self.block.graph,
+            self.if_panel,
+            fft_size=512,
+            sample_rate = block.audio_rate,
+            baseband_freq = 0,
+            average = False,
+            size = ( 680, 140 ) )
+
+        em.eventManager.Register( self.fe_mouse,
+                                  wx.EVT_MOTION,
+                                  self.fespectrum.win )
+
+        em.eventManager.Register( self.fe_click,
+                                  wx.EVT_LEFT_DOWN,
+                                  self.fespectrum.win )
+
+        block.graph.connect( block.src.src, self.fespectrum )
+        block.graph.connect( block.demod.xlate, self.ifspectrum )
+
+    def agc_ref_up( self, event ):
+        self.agc_ref_s.SetValue( 5 )
+        r = float( self.agc_ref.GetValue() )
+        r = r + 5
+        self.agc_ref.SetValue( str( r ) )
+        self.block.agc.offs.set_k( r )
+        
+    def agc_ref_down( self, event ):
+        self.agc_ref_s.SetValue( 5 )
+        r = float( self.agc_ref.GetValue() )
+        r = r - 5
+        self.agc_ref.SetValue( str( r ) )
+        self.block.agc.offs.set_k( r )
+
+    def agc_gain_up( self, event ):
+        self.agc_gain_s.SetValue( 5 )
+        g = float(self.agc_gain.GetValue())
+        g = g + 10
+        self.agc_gain.SetValue( str( g ) )
+        self.block.agc.gain.set_k( g )
+
+    def agc_gain_down( self, event ):
+        self.agc_gain_s.SetValue( 5 )
+        g = float(self.agc_gain.GetValue())
+        g = g - 10
+        self.agc_gain.SetValue( str( g ) )
+        self.block.agc.gain.set_k( g )
+
+    def fe_mouse( self, event ):
+        f = int(self.freq_disp.GetValue())
+        f = f+((event.GetX()-346.)*(400./610.))*1000
+        self.fespectrum.win.SetToolTip(
+            wx.ToolTip( eng_notation.num_to_str(f)))
+
+    def fe_click( self, event ):
+        f = int(self.freq_disp.GetValue())
+        f = f+((event.GetX()-346.)*(400./610.))*1000
+        self.tune( f )
+
+    def setrssi( self, level ):
+        if level < 0:
+            level = 0
+        if level > self.rssi_range:
+            self.rssi_range = level
+            self.rssi.SetRange( level )
+            self.agc_max.SetValue( str( level ))
+        self.rssi.SetValue( level )
+        self.agc_level.SetValue( str( level ))
+
+    def tune_evt( self, event ):
+        f = self.freq_disp.GetValue()
+        self.tune( f )
+        
+    def tune( self, frequency ):
+        self.freq_disp.SetValue( frequency )
+        self.block.tune( frequency )
+
+    def up_e0( self, event ):
+        self.spin_e0.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e0 )
+
+    def down_e0( self, event ):
+        self.spin_e0.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e0 )
+
+    def up_e1( self, event ):
+        self.spin_e1.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e1 )
+
+    def down_e1( self, event ):
+        self.spin_e1.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e1 )
+
+    def up_e2( self, event ):
+        self.spin_e2.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e2 )
+
+    def down_e2( self, event ):
+        self.spin_e2.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e2 )
+
+    def up_e3( self, event ):
+        self.spin_e3.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e3 )
+
+    def down_e3( self, event ):
+        self.spin_e3.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e3 )
+
+    def up_e4( self, event ):
+        self.spin_e4.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e4 )
+
+    def down_e4( self, event ):
+        self.spin_e4.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e4 )
+
+    def up_e5( self, event ):
+        self.spin_e5.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e5 )
+
+    def down_e5( self, event ):
+        self.spin_e5.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e5 )
+
+    def up_e6( self, event ):
+        self.spin_e6.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() + 1e6 )
+
+    def down_e6( self, event ):
+        self.spin_e6.SetValue( 50 )
+        self.tune( self.freq_disp.GetValue() - 1e6 )
+
+    def event_pga( self, event ):
+        self.block.src.src.set_pga( 0, self.pga.GetValue())
+        
+    def event_vol( self, event ):
+        self.block.out.set( self.volume.GetValue()/20.0 )
+
+    def set_usb( self, event ):
+        self.block.demod.upper_sb()
+        
+    def set_lsb( self, event ):
+        self.block.demod.lower_sb()
+
+    def set_am( self, event ):
+        self.block.demod.set_am()
+
+    def bw_up( self, event ):
+        self.bw_spin.SetValue( 5 )
+        bw = float(self.bandwidth.GetValue())
+        bw = bw + 20.0
+        if bw > 10e3:
+            bw = 10e3
+        self.bandwidth.SetValue( str( bw ) )
+        self.block.demod.set_bw( bw )
+
+    def bw_down( self, event ):
+        self.bw_spin.SetValue( 5 )
+        bw = float(self.bandwidth.GetValue())
+        bw = bw - 20.0
+        if bw < 50:
+            bw = 50
+        self.bandwidth.SetValue( str( bw ) )
+        self.block.demod.set_bw( bw )
+
+
+class radio( wx.App ):
+    def OnInit( self ):
+        self.graph = gr.flow_graph()
+        self.block = graph( self.graph )
+        self.frame = radio_frame( self.block, None, -1, "Title" )
+        self.frame.Show( True )
+        self.SetTopWindow( self.frame )
+        return True
+
+a=radio( 0 )
+
+l=gr.probe_signal_f()
+#l=gr.probe_avg_mag_sqrd_f(1,.001)
+a.graph.connect(a.block.agc.offs,l )
+#a.graph.connect(a.block.demod,l)
+
+def main_function():
+    global a
+    a.MainLoop()
+
+
+def rssi_function():
+    global a
+    global l
+    while 1:
+        level = l.level()
+        wx.CallAfter( a.frame.setrssi, level )
+        time.sleep( .1 )
+
+thread1 = Thread( target = main_function )
+thread2 = Thread( target = rssi_function )
+
+thread1.start()
+thread2.start()
+
+a.graph.start()
+
diff --git a/gnuradio-examples/python/apps/hf_radio/radio.xml b/gnuradio-examples/python/apps/hf_radio/radio.xml
new file mode 100644
index 0000000000..81daa19b0d
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/radio.xml
@@ -0,0 +1,441 @@
+<?xml version="1.0"?>
+<!-- generated by wxGlade 0.4 on Fri Jan  6 09:51:36 2006 -->
+
+<application path="/root/radio/ui.py" name="" class="" option="0" language="python" top_window="" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.6">
+    <object class="ui_frame" name="frame_1" base="EditFrame">
+        <style>wxDEFAULT_FRAME_STYLE</style>
+        <title>frame_1</title>
+        <object class="wxStaticBoxSizer" name="sizer_1" base="EditStaticBoxSizer">
+            <orient>wxVERTICAL</orient>
+            <label>sizer_1</label>
+            <object class="sizeritem">
+                <flag>wxEXPAND</flag>
+                <border>0</border>
+                <option>1</option>
+                <object class="wxBoxSizer" name="sizer_2" base="EditBoxSizer">
+                    <orient>wxHORIZONTAL</orient>
+                    <object class="sizeritem">
+                        <flag>wxEXPAND</flag>
+                        <border>0</border>
+                        <option>1</option>
+                        <object class="wxBoxSizer" name="sizer_3" base="EditBoxSizer">
+                            <orient>wxVERTICAL</orient>
+                            <object class="sizeritem">
+                                <flag>wxEXPAND|wxADJUST_MINSIZE</flag>
+                                <border>0</border>
+                                <option>1</option>
+                                <object class="wxSpinCtrl" name="freq_disp" base="EditSpinCtrl">
+                                    <font>
+                                        <size>32</size>
+                                        <family>default</family>
+                                        <style>normal</style>
+                                        <weight>normal</weight>
+                                        <underlined>0</underlined>
+                                        <face></face>
+                                    </font>
+                                    <events>
+                                        <handler event="EVT_SPINCTRL">tune_evt</handler>
+                                    </events>
+                                </object>
+                            </object>
+                            <object class="sizeritem">
+                                <flag>wxEXPAND</flag>
+                                <border>0</border>
+                                <option>1</option>
+                                <object class="wxGridSizer" name="grid_sizer_1" base="EditGridSizer">
+                                    <hgap>0</hgap>
+                                    <rows>2</rows>
+                                    <cols>3</cols>
+                                    <vgap>0</vgap>
+                                    <object class="sizeritem">
+                                        <flag>wxEXPAND</flag>
+                                        <border>0</border>
+                                        <option>1</option>
+                                        <object class="wxGridSizer" name="grid_sizer_2" base="EditGridSizer">
+                                            <hgap>0</hgap>
+                                            <rows>1</rows>
+                                            <cols>7</cols>
+                                            <vgap>0</vgap>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e6" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e6</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e6</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e5" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e5</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e5</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e4" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e4</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e4</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e3" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e3</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e3</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e2" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e2</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e2</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e1" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e1</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e1</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="spin_e0" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">up_e0</handler>
+                                                        <handler event="EVT_SPIN_DOWN">down_e0</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxEXPAND</flag>
+                                        <border>0</border>
+                                        <option>1</option>
+                                        <object class="wxPanel" name="panel_1" base="EditPanel">
+                                            <style>wxTAB_TRAVERSAL</style>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxEXPAND</flag>
+                                        <border>0</border>
+                                        <option>1</option>
+                                        <object class="wxPanel" name="panel_2" base="EditPanel">
+                                            <style>wxTAB_TRAVERSAL</style>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxButton" name="button_lsb" base="EditButton">
+                                            <label>LSB</label>
+                                            <events>
+                                                <handler event="EVT_BUTTON">set_lsb</handler>
+                                            </events>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxButton" name="button_usb" base="EditButton">
+                                            <label>USB</label>
+                                            <events>
+                                                <handler event="EVT_BUTTON">set_usb</handler>
+                                            </events>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxButton" name="button_am" base="EditButton">
+                                            <label>AM</label>
+                                            <events>
+                                                <handler event="EVT_BUTTON">set_am</handler>
+                                            </events>
+                                        </object>
+                                    </object>
+                                </object>
+                            </object>
+                        </object>
+                    </object>
+                    <object class="sizeritem">
+                        <flag>wxEXPAND</flag>
+                        <border>0</border>
+                        <option>1</option>
+                        <object class="wxBoxSizer" name="sizer_4" base="EditBoxSizer">
+                            <orient>wxVERTICAL</orient>
+                            <object class="sizeritem">
+                                <flag>wxEXPAND</flag>
+                                <border>0</border>
+                                <option>1</option>
+                                <object class="wxGridSizer" name="grid_sizer_3" base="EditGridSizer">
+                                    <hgap>0</hgap>
+                                    <rows>2</rows>
+                                    <cols>4</cols>
+                                    <vgap>0</vgap>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_1" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                            <label>VOLUME</label>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_2" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                            <label>PGA</label>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxTextCtrl" name="agc_level" base="EditTextCtrl">
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_6" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxSpinCtrl" name="volume" base="EditSpinCtrl">
+                                            <events>
+                                                <handler event="EVT_SPINCTRL">event_vol</handler>
+                                            </events>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxSpinCtrl" name="pga" base="EditSpinCtrl">
+                                            <events>
+                                                <handler event="EVT_SPINCTRL">event_pga</handler>
+                                            </events>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxTextCtrl" name="agc_max" base="EditTextCtrl">
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_7" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                        </object>
+                                    </object>
+                                </object>
+                            </object>
+                            <object class="sizeritem">
+                                <flag>wxEXPAND</flag>
+                                <border>0</border>
+                                <option>1</option>
+                                <object class="wxGridSizer" name="grid_sizer_4" base="EditGridSizer">
+                                    <hgap>0</hgap>
+                                    <rows>2</rows>
+                                    <cols>4</cols>
+                                    <vgap>0</vgap>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_4" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                            <label>AGC AUTHORITY</label>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_5" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                            <label>AGC REF LVL</label>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_3" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                            <label>BANDWIDTH</label>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_8" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxEXPAND</flag>
+                                        <border>0</border>
+                                        <option>1</option>
+                                        <object class="wxBoxSizer" name="sizer_6" base="EditBoxSizer">
+                                            <orient>wxHORIZONTAL</orient>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxTextCtrl" name="agc_gain" base="EditTextCtrl">
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="agc_gain_s" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">agc_gain_up</handler>
+                                                        <handler event="EVT_SPIN_DOWN">agc_gain_down</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxEXPAND</flag>
+                                        <border>0</border>
+                                        <option>1</option>
+                                        <object class="wxBoxSizer" name="sizer_7" base="EditBoxSizer">
+                                            <orient>wxHORIZONTAL</orient>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxTextCtrl" name="agc_ref" base="EditTextCtrl">
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="agc_ref_s" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">agc_ref_up</handler>
+                                                        <handler event="EVT_SPIN_DOWN">agc_ref_down</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxEXPAND</flag>
+                                        <border>0</border>
+                                        <option>1</option>
+                                        <object class="wxBoxSizer" name="sizer_5" base="EditBoxSizer">
+                                            <orient>wxHORIZONTAL</orient>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxTextCtrl" name="bandwidth" base="EditTextCtrl">
+                                                </object>
+                                            </object>
+                                            <object class="sizeritem">
+                                                <flag>wxADJUST_MINSIZE</flag>
+                                                <border>0</border>
+                                                <option>0</option>
+                                                <object class="wxSpinButton" name="bw_spin" base="EditSpinButton">
+                                                    <events>
+                                                        <handler event="EVT_SPIN_UP">bw_up</handler>
+                                                        <handler event="EVT_SPIN_DOWN">bw_down</handler>
+                                                    </events>
+                                                </object>
+                                            </object>
+                                        </object>
+                                    </object>
+                                    <object class="sizeritem">
+                                        <flag>wxADJUST_MINSIZE</flag>
+                                        <border>0</border>
+                                        <option>0</option>
+                                        <object class="wxStaticText" name="label_9" base="EditStaticText">
+                                            <attribute>1</attribute>
+                                        </object>
+                                    </object>
+                                </object>
+                            </object>
+                            <object class="sizeritem">
+                                <flag>wxEXPAND|wxADJUST_MINSIZE</flag>
+                                <border>0</border>
+                                <option>1</option>
+                                <object class="wxGauge" name="rssi" base="EditGauge">
+                                    <foreground>#ff0000</foreground>
+                                    <style>wxGA_HORIZONTAL|wxGA_SMOOTH</style>
+                                    <range>10</range>
+                                    <size>315, 10</size>
+                                </object>
+                            </object>
+                        </object>
+                    </object>
+                </object>
+            </object>
+            <object class="sizeritem">
+                <flag>wxEXPAND</flag>
+                <border>0</border>
+                <option>1</option>
+                <object class="wxPanel" name="fe_panel" base="EditPanel">
+                    <style>wxTAB_TRAVERSAL</style>
+                </object>
+            </object>
+            <object class="sizeritem">
+                <flag>wxEXPAND</flag>
+                <border>0</border>
+                <option>1</option>
+                <object class="wxPanel" name="if_panel" base="EditPanel">
+                    <style>wxTAB_TRAVERSAL</style>
+                </object>
+            </object>
+        </object>
+    </object>
+</application>
diff --git a/gnuradio-examples/python/apps/hf_radio/ssb_taps b/gnuradio-examples/python/apps/hf_radio/ssb_taps
new file mode 100644
index 0000000000..0ef3bbf267
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/ssb_taps
@@ -0,0 +1,1023 @@
+-0.000035-0.000009j
+-0.000066-0.000020j
+-0.000080-0.000044j
+-0.000084-0.000071j
+-0.000077-0.000100j
+-0.000063-0.000127j
+-0.000041-0.000150j
+-0.000013-0.000167j
+0.000020-0.000177j
+0.000054-0.000180j
+0.000089-0.000174j
+0.000121-0.000161j
+0.000150-0.000140j
+0.000173-0.000113j
+0.000188-0.000081j
+0.000196-0.000046j
+0.000194-0.000011j
+0.000184+0.000022j
+0.000165+0.000052j
+0.000139+0.000077j
+0.000107+0.000093j
+0.000071+0.000102j
+0.000034+0.000101j
+-0.000002+0.000090j
+-0.000036+0.000070j
+-0.000064+0.000042j
+-0.000086+0.000006j
+-0.000098-0.000034j
+-0.000101-0.000077j
+-0.000093-0.000120j
+-0.000076-0.000161j
+-0.000049-0.000197j
+-0.000014-0.000227j
+0.000026-0.000248j
+0.000071-0.000259j
+0.000117-0.000259j
+0.000162-0.000249j
+0.000203-0.000228j
+0.000237-0.000199j
+0.000263-0.000162j
+0.000279-0.000120j
+0.000284-0.000075j
+0.000278-0.000031j
+0.000260+0.000010j
+0.000232+0.000045j
+0.000196+0.000073j
+0.000153+0.000090j
+0.000106+0.000095j
+0.000059+0.000089j
+0.000014+0.000071j
+-0.000027+0.000041j
+-0.000059+0.000002j
+-0.000082-0.000046j
+-0.000093-0.000098j
+-0.000091-0.000152j
+-0.000077-0.000206j
+-0.000050-0.000255j
+-0.000012-0.000298j
+0.000034-0.000330j
+0.000088-0.000351j
+0.000145-0.000359j
+0.000202-0.000354j
+0.000256-0.000335j
+0.000304-0.000304j
+0.000343-0.000262j
+0.000370-0.000213j
+0.000384-0.000158j
+0.000384-0.000102j
+0.000369-0.000048j
+0.000341+0.000002j
+0.000302+0.000042j
+0.000252+0.000072j
+0.000196+0.000088j
+0.000137+0.000089j
+0.000078+0.000075j
+0.000024+0.000047j
+-0.000023+0.000005j
+-0.000059-0.000048j
+-0.000082-0.000109j
+-0.000090-0.000175j
+-0.000081-0.000242j
+-0.000058-0.000306j
+-0.000019-0.000364j
+0.000032-0.000411j
+0.000093-0.000445j
+0.000161-0.000465j
+0.000232-0.000467j
+0.000301-0.000453j
+0.000365-0.000423j
+0.000419-0.000379j
+0.000461-0.000323j
+0.000487-0.000259j
+0.000497-0.000190j
+0.000489-0.000121j
+0.000464-0.000056j
+0.000423+0.000001j
+0.000369+0.000046j
+0.000304+0.000076j
+0.000233+0.000089j
+0.000160+0.000083j
+0.000089+0.000060j
+0.000025+0.000018j
+-0.000027-0.000038j
+-0.000065-0.000107j
+-0.000086-0.000185j
+-0.000088-0.000266j
+-0.000071-0.000347j
+-0.000035-0.000422j
+0.000019-0.000487j
+0.000086-0.000538j
+0.000164-0.000573j
+0.000248-0.000588j
+0.000334-0.000582j
+0.000415-0.000557j
+0.000488-0.000513j
+0.000548-0.000452j
+0.000592-0.000379j
+0.000616-0.000297j
+0.000619-0.000213j
+0.000600-0.000130j
+0.000561-0.000054j
+0.000504+0.000010j
+0.000432+0.000058j
+0.000350+0.000086j
+0.000261+0.000093j
+0.000173+0.000078j
+0.000090+0.000040j
+0.000017-0.000017j
+-0.000040-0.000092j
+-0.000078-0.000180j
+-0.000095-0.000275j
+-0.000088-0.000374j
+-0.000058-0.000469j
+-0.000006-0.000555j
+0.000065-0.000627j
+0.000152-0.000681j
+0.000250-0.000712j
+0.000352-0.000720j
+0.000454-0.000703j
+0.000548-0.000663j
+0.000630-0.000601j
+0.000694-0.000521j
+0.000737-0.000428j
+0.000755-0.000327j
+0.000748-0.000225j
+0.000715-0.000128j
+0.000659-0.000042j
+0.000582+0.000028j
+0.000490+0.000077j
+0.000387+0.000101j
+0.000280+0.000099j
+0.000175+0.000070j
+0.000080+0.000015j
+-0.000001-0.000063j
+-0.000061-0.000159j
+-0.000097-0.000268j
+-0.000106-0.000385j
+-0.000087-0.000501j
+-0.000040-0.000611j
+0.000032-0.000708j
+0.000125-0.000786j
+0.000235-0.000839j
+0.000354-0.000866j
+0.000477-0.000863j
+0.000595-0.000831j
+0.000702-0.000772j
+0.000792-0.000688j
+0.000859-0.000585j
+0.000898-0.000469j
+0.000907-0.000347j
+0.000886-0.000227j
+0.000835-0.000115j
+0.000757-0.000019j
+0.000657+0.000055j
+0.000540+0.000102j
+0.000415+0.000119j
+0.000287+0.000103j
+0.000165+0.000056j
+0.000058-0.000020j
+-0.000029-0.000122j
+-0.000090-0.000243j
+-0.000121-0.000378j
+-0.000118-0.000517j
+-0.000082-0.000653j
+-0.000014-0.000778j
+0.000082-0.000885j
+0.000201-0.000966j
+0.000337-0.001017j
+0.000481-0.001034j
+0.000626-0.001016j
+0.000762-0.000965j
+0.000882-0.000882j
+0.000978-0.000772j
+0.001044-0.000643j
+0.001076-0.000501j
+0.001072-0.000355j
+0.001032-0.000215j
+0.000958-0.000089j
+0.000854+0.000016j
+0.000726+0.000091j
+0.000582+0.000133j
+0.000431+0.000138j
+0.000281+0.000105j
+0.000143+0.000035j
+0.000024-0.000068j
+-0.000068-0.000199j
+-0.000126-0.000350j
+-0.000147-0.000513j
+-0.000128-0.000677j
+-0.000070-0.000834j
+0.000024-0.000974j
+0.000150-0.001089j
+0.000300-0.001171j
+0.000465-0.001216j
+0.000637-0.001219j
+0.000805-0.001182j
+0.000960-0.001105j
+0.001091-0.000993j
+0.001191-0.000853j
+0.001253-0.000692j
+0.001274-0.000521j
+0.001252-0.000350j
+0.001188-0.000189j
+0.001085-0.000049j
+0.000950+0.000062j
+0.000790+0.000136j
+0.000614+0.000168j
+0.000435+0.000156j
+0.000261+0.000099j
+0.000105+0.000000j
+-0.000024-0.000136j
+-0.000117-0.000301j
+-0.000169-0.000486j
+-0.000175-0.000680j
+-0.000134-0.000872j
+-0.000048-0.001051j
+0.000079-0.001206j
+0.000240-0.001326j
+0.000426-0.001406j
+0.000626-0.001439j
+0.000829-0.001424j
+0.001022-0.001361j
+0.001195-0.001252j
+0.001336-0.001106j
+0.001437-0.000929j
+0.001491-0.000733j
+0.001496-0.000529j
+0.001449-0.000330j
+0.001354-0.000148j
+0.001217+0.000005j
+0.001044+0.000120j
+0.000846+0.000188j
+0.000635+0.000206j
+0.000424+0.000170j
+0.000226+0.000083j
+0.000053-0.000053j
+-0.000084-0.000228j
+-0.000176-0.000434j
+-0.000216-0.000659j
+-0.000201-0.000889j
+-0.000131-0.001111j
+-0.000009-0.001312j
+0.000158-0.001480j
+0.000362-0.001604j
+0.000590-0.001677j
+0.000829-0.001694j
+0.001066-0.001653j
+0.001286-0.001556j
+0.001477-0.001408j
+0.001626-0.001219j
+0.001724-0.001000j
+0.001765-0.000762j
+0.001746-0.000522j
+0.001668-0.000293j
+0.001534-0.000090j
+0.001353+0.000075j
+0.001135+0.000190j
+0.000893+0.000247j
+0.000642+0.000243j
+0.000396+0.000176j
+0.000172+0.000049j
+-0.000017-0.000131j
+-0.000159-0.000355j
+-0.000244-0.000609j
+-0.000266-0.000880j
+-0.000222-0.001151j
+-0.000114-0.001406j
+0.000053-0.001630j
+0.000270-0.001810j
+0.000524-0.001934j
+0.000802-0.001994j
+0.001087-0.001987j
+0.001362-0.001911j
+0.001611-0.001772j
+0.001819-0.001576j
+0.001973-0.001336j
+0.002063-0.001065j
+0.002084-0.000779j
+0.002033-0.000497j
+0.001914-0.000236j
+0.001732-0.000011j
+0.001498+0.000162j
+0.001225+0.000272j
+0.000931+0.000312j
+0.000633+0.000277j
+0.000349+0.000168j
+0.000097-0.000009j
+-0.000107-0.000246j
+-0.000250-0.000528j
+-0.000322-0.000841j
+-0.000316-0.001166j
+-0.000233-0.001484j
+-0.000076-0.001775j
+0.000148-0.002024j
+0.000426-0.002213j
+0.000743-0.002332j
+0.001080-0.002373j
+0.001418-0.002332j
+0.001736-0.002211j
+0.002017-0.002017j
+0.002241-0.001760j
+0.002397-0.001457j
+0.002473-0.001124j
+0.002464-0.000783j
+0.002371-0.000453j
+0.002198-0.000156j
+0.001954+0.000091j
+0.001654+0.000269j
+0.001316+0.000369j
+0.000959+0.000381j
+0.000606+0.000303j
+0.000279+0.000139j
+-0.000003-0.000103j
+-0.000220-0.000411j
+-0.000359-0.000768j
+-0.000408-0.001152j
+-0.000365-0.001542j
+-0.000229-0.001915j
+-0.000006-0.002248j
+0.000292-0.002522j
+0.000648-0.002719j
+0.001042-0.002826j
+0.001452-0.002837j
+0.001853-0.002750j
+0.002223-0.002569j
+0.002537-0.002304j
+0.002778-0.001971j
+0.002930-0.001588j
+0.002984-0.001179j
+0.002933-0.000770j
+0.002782-0.000384j
+0.002538-0.000046j
+0.002215+0.000222j
+0.001831+0.000402j
+0.001410+0.000481j
+0.000976+0.000452j
+0.000557+0.000316j
+0.000179+0.000077j
+-0.000134-0.000252j
+-0.000362-0.000654j
+-0.000490-0.001105j
+-0.000506-0.001580j
+-0.000407-0.002052j
+-0.000197-0.002492j
+0.000113-0.002875j
+0.000508-0.003176j
+0.000966-0.003377j
+0.001460-0.003464j
+0.001963-0.003432j
+0.002444-0.003281j
+0.002876-0.003019j
+0.003231-0.002659j
+0.003488-0.002224j
+0.003631-0.001739j
+0.003649-0.001233j
+0.003540-0.000737j
+0.003309-0.000282j
+0.002969+0.000103j
+0.002539+0.000393j
+0.002044+0.000568j
+0.001515+0.000614j
+0.000982+0.000525j
+0.000480+0.000304j
+0.000039-0.000039j
+-0.000311-0.000487j
+-0.000547-0.001016j
+-0.000652-0.001595j
+-0.000615-0.002193j
+-0.000436-0.002773j
+-0.000122-0.003301j
+0.000311-0.003746j
+0.000842-0.004081j
+0.001440-0.004282j
+0.002071-0.004338j
+0.002700-0.004243j
+0.003289-0.004000j
+0.003803-0.003622j
+0.004210-0.003132j
+0.004485-0.002556j
+0.004610-0.001930j
+0.004574-0.001291j
+0.004379-0.000679j
+0.004034-0.000133j
+0.003558+0.000313j
+0.002977+0.000627j
+0.002327+0.000787j
+0.001647+0.000779j
+0.000977+0.000598j
+0.000360+0.000250j
+-0.000163-0.000249j
+-0.000559-0.000872j
+-0.000799-0.001587j
+-0.000864-0.002354j
+-0.000744-0.003129j
+-0.000442-0.003866j
+0.000031-0.004522j
+0.000651-0.005057j
+0.001385-0.005437j
+0.002193-0.005637j
+0.003030-0.005643j
+0.003848-0.005451j
+0.004597-0.005069j
+0.005234-0.004519j
+0.005718-0.003830j
+0.006019-0.003044j
+0.006114-0.002206j
+0.005997-0.001368j
+0.005669-0.000583j
+0.005147+0.000099j
+0.004460+0.000631j
+0.003647+0.000975j
+0.002757+0.001105j
+0.001842+0.001003j
+0.000961+0.000668j
+0.000168+0.000111j
+-0.000482-0.000643j
+-0.000944-0.001555j
+-0.001183-0.002578j
+-0.001176-0.003656j
+-0.000912-0.004727j
+-0.000397-0.005728j
+0.000346-0.006601j
+0.001284-0.007292j
+0.002368-0.007755j
+0.003540-0.007959j
+0.004735-0.007886j
+0.005885-0.007535j
+0.006922-0.006922j
+0.007782-0.006078j
+0.008412-0.005050j
+0.008769-0.003898j
+0.008825-0.002691j
+0.008572-0.001504j
+0.008016-0.000412j
+0.007185+0.000510j
+0.006123+0.001196j
+0.004891+0.001591j
+0.003560+0.001657j
+0.002212+0.001372j
+0.000933+0.000734j
+-0.000192-0.000236j
+-0.001083-0.001500j
+-0.001672-0.002998j
+-0.001905-0.004655j
+-0.001747-0.006384j
+-0.001182-0.008090j
+-0.000222-0.009676j
+0.001101-0.011045j
+0.002732-0.012114j
+0.004593-0.012810j
+0.006591-0.013081j
+0.008621-0.012896j
+0.010571-0.012253j
+0.012328-0.011175j
+0.013785-0.009712j
+0.014847-0.007941j
+0.015438-0.005962j
+0.015507-0.003893j
+0.015029-0.001863j
+0.014011-0.000011j
+0.012494+0.001529j
+0.010549+0.002630j
+0.008277+0.003179j
+0.005809+0.003090j
+0.003294+0.002304j
+0.000896+0.000795j
+-0.001212-0.001423j
+-0.002859-0.004299j
+-0.003886-0.007744j
+-0.004151-0.011630j
+-0.003539-0.015799j
+-0.001969-0.020066j
+0.000601-0.024225j
+0.004168-0.028064j
+0.008684-0.031367j
+0.014056-0.033927j
+0.020145-0.035558j
+0.026775-0.036101j
+0.033735-0.035433j
+0.040789-0.033475j
+0.047684-0.030197j
+0.054164-0.025619j
+0.059974-0.019815j
+0.064878-0.012907j
+0.068665-0.005067j
+0.071159+0.003494j
+0.072228+0.012531j
+0.071791+0.021776j
+0.069818+0.030947j
+0.066339+0.039761j
+0.061435+0.047944j
+0.055243+0.055243j
+0.047944+0.061435j
+0.039761+0.066339j
+0.030947+0.069818j
+0.021776+0.071791j
+0.012531+0.072228j
+0.003494+0.071159j
+-0.005067+0.068665j
+-0.012907+0.064878j
+-0.019815+0.059974j
+-0.025619+0.054164j
+-0.030197+0.047684j
+-0.033475+0.040789j
+-0.035433+0.033735j
+-0.036101+0.026775j
+-0.035558+0.020145j
+-0.033927+0.014056j
+-0.031367+0.008684j
+-0.028064+0.004168j
+-0.024225+0.000601j
+-0.020066-0.001969j
+-0.015799-0.003539j
+-0.011630-0.004151j
+-0.007744-0.003886j
+-0.004299-0.002859j
+-0.001423-0.001212j
+0.000795+0.000896j
+0.002304+0.003294j
+0.003090+0.005809j
+0.003179+0.008277j
+0.002630+0.010549j
+0.001529+0.012494j
+-0.000011+0.014011j
+-0.001863+0.015029j
+-0.003893+0.015507j
+-0.005962+0.015438j
+-0.007941+0.014847j
+-0.009712+0.013785j
+-0.011175+0.012328j
+-0.012253+0.010571j
+-0.012896+0.008621j
+-0.013081+0.006591j
+-0.012810+0.004593j
+-0.012114+0.002732j
+-0.011045+0.001101j
+-0.009676-0.000222j
+-0.008090-0.001182j
+-0.006384-0.001747j
+-0.004655-0.001905j
+-0.002998-0.001672j
+-0.001500-0.001083j
+-0.000236-0.000192j
+0.000734+0.000933j
+0.001372+0.002212j
+0.001657+0.003560j
+0.001591+0.004891j
+0.001196+0.006123j
+0.000510+0.007185j
+-0.000412+0.008016j
+-0.001504+0.008572j
+-0.002691+0.008825j
+-0.003898+0.008769j
+-0.005050+0.008412j
+-0.006078+0.007782j
+-0.006922+0.006922j
+-0.007535+0.005885j
+-0.007886+0.004735j
+-0.007959+0.003540j
+-0.007755+0.002368j
+-0.007292+0.001284j
+-0.006601+0.000346j
+-0.005728-0.000397j
+-0.004727-0.000912j
+-0.003656-0.001176j
+-0.002578-0.001183j
+-0.001555-0.000944j
+-0.000643-0.000482j
+0.000111+0.000168j
+0.000668+0.000961j
+0.001003+0.001842j
+0.001105+0.002757j
+0.000975+0.003647j
+0.000631+0.004460j
+0.000099+0.005147j
+-0.000583+0.005669j
+-0.001368+0.005997j
+-0.002206+0.006114j
+-0.003044+0.006019j
+-0.003830+0.005718j
+-0.004519+0.005234j
+-0.005069+0.004597j
+-0.005451+0.003848j
+-0.005643+0.003030j
+-0.005637+0.002193j
+-0.005437+0.001385j
+-0.005057+0.000651j
+-0.004522+0.000031j
+-0.003866-0.000442j
+-0.003129-0.000744j
+-0.002354-0.000864j
+-0.001587-0.000799j
+-0.000872-0.000559j
+-0.000249-0.000163j
+0.000250+0.000360j
+0.000598+0.000977j
+0.000779+0.001647j
+0.000787+0.002327j
+0.000627+0.002977j
+0.000313+0.003558j
+-0.000133+0.004034j
+-0.000679+0.004379j
+-0.001291+0.004574j
+-0.001930+0.004610j
+-0.002556+0.004485j
+-0.003132+0.004210j
+-0.003622+0.003803j
+-0.004000+0.003289j
+-0.004243+0.002700j
+-0.004338+0.002071j
+-0.004282+0.001440j
+-0.004081+0.000842j
+-0.003746+0.000311j
+-0.003301-0.000122j
+-0.002773-0.000436j
+-0.002193-0.000615j
+-0.001595-0.000652j
+-0.001016-0.000547j
+-0.000487-0.000311j
+-0.000039+0.000039j
+0.000304+0.000480j
+0.000525+0.000982j
+0.000614+0.001515j
+0.000568+0.002044j
+0.000393+0.002539j
+0.000103+0.002969j
+-0.000282+0.003309j
+-0.000737+0.003540j
+-0.001233+0.003649j
+-0.001739+0.003631j
+-0.002224+0.003488j
+-0.002659+0.003231j
+-0.003019+0.002876j
+-0.003281+0.002444j
+-0.003432+0.001963j
+-0.003464+0.001460j
+-0.003377+0.000966j
+-0.003176+0.000508j
+-0.002875+0.000113j
+-0.002492-0.000197j
+-0.002052-0.000407j
+-0.001580-0.000506j
+-0.001105-0.000490j
+-0.000654-0.000362j
+-0.000252-0.000134j
+0.000077+0.000179j
+0.000316+0.000557j
+0.000452+0.000976j
+0.000481+0.001410j
+0.000402+0.001831j
+0.000222+0.002215j
+-0.000046+0.002538j
+-0.000384+0.002782j
+-0.000770+0.002933j
+-0.001179+0.002984j
+-0.001588+0.002930j
+-0.001971+0.002778j
+-0.002304+0.002537j
+-0.002569+0.002223j
+-0.002750+0.001853j
+-0.002837+0.001452j
+-0.002826+0.001042j
+-0.002719+0.000648j
+-0.002522+0.000292j
+-0.002248-0.000006j
+-0.001915-0.000229j
+-0.001542-0.000365j
+-0.001152-0.000408j
+-0.000768-0.000359j
+-0.000411-0.000220j
+-0.000103-0.000003j
+0.000139+0.000279j
+0.000303+0.000606j
+0.000381+0.000959j
+0.000369+0.001316j
+0.000269+0.001654j
+0.000091+0.001954j
+-0.000156+0.002198j
+-0.000453+0.002371j
+-0.000783+0.002464j
+-0.001124+0.002473j
+-0.001457+0.002397j
+-0.001760+0.002241j
+-0.002017+0.002017j
+-0.002211+0.001736j
+-0.002332+0.001418j
+-0.002373+0.001080j
+-0.002332+0.000743j
+-0.002213+0.000426j
+-0.002024+0.000148j
+-0.001775-0.000076j
+-0.001484-0.000233j
+-0.001166-0.000316j
+-0.000841-0.000322j
+-0.000528-0.000250j
+-0.000246-0.000107j
+-0.000009+0.000097j
+0.000168+0.000349j
+0.000277+0.000633j
+0.000312+0.000931j
+0.000272+0.001225j
+0.000162+0.001498j
+-0.000011+0.001732j
+-0.000236+0.001914j
+-0.000497+0.002033j
+-0.000779+0.002084j
+-0.001065+0.002063j
+-0.001336+0.001973j
+-0.001576+0.001819j
+-0.001772+0.001611j
+-0.001911+0.001362j
+-0.001987+0.001087j
+-0.001994+0.000802j
+-0.001934+0.000524j
+-0.001810+0.000270j
+-0.001630+0.000053j
+-0.001406-0.000114j
+-0.001151-0.000222j
+-0.000880-0.000266j
+-0.000609-0.000244j
+-0.000355-0.000159j
+-0.000131-0.000017j
+0.000049+0.000172j
+0.000176+0.000396j
+0.000243+0.000642j
+0.000247+0.000893j
+0.000190+0.001135j
+0.000075+0.001353j
+-0.000090+0.001534j
+-0.000293+0.001668j
+-0.000522+0.001746j
+-0.000762+0.001765j
+-0.001000+0.001724j
+-0.001219+0.001626j
+-0.001408+0.001477j
+-0.001556+0.001286j
+-0.001653+0.001066j
+-0.001694+0.000829j
+-0.001677+0.000590j
+-0.001604+0.000362j
+-0.001480+0.000158j
+-0.001312-0.000009j
+-0.001111-0.000131j
+-0.000889-0.000201j
+-0.000659-0.000216j
+-0.000434-0.000176j
+-0.000228-0.000084j
+-0.000053+0.000053j
+0.000083+0.000226j
+0.000170+0.000424j
+0.000206+0.000635j
+0.000188+0.000846j
+0.000120+0.001044j
+0.000005+0.001217j
+-0.000148+0.001354j
+-0.000330+0.001449j
+-0.000529+0.001496j
+-0.000733+0.001491j
+-0.000929+0.001437j
+-0.001106+0.001336j
+-0.001252+0.001195j
+-0.001361+0.001022j
+-0.001424+0.000829j
+-0.001439+0.000626j
+-0.001406+0.000426j
+-0.001326+0.000240j
+-0.001206+0.000079j
+-0.001051-0.000048j
+-0.000872-0.000134j
+-0.000680-0.000175j
+-0.000486-0.000169j
+-0.000301-0.000117j
+-0.000136-0.000024j
+0.000000+0.000105j
+0.000099+0.000261j
+0.000156+0.000435j
+0.000168+0.000614j
+0.000136+0.000790j
+0.000062+0.000950j
+-0.000049+0.001085j
+-0.000189+0.001188j
+-0.000350+0.001252j
+-0.000521+0.001274j
+-0.000692+0.001253j
+-0.000853+0.001191j
+-0.000993+0.001091j
+-0.001105+0.000960j
+-0.001182+0.000805j
+-0.001219+0.000637j
+-0.001216+0.000465j
+-0.001171+0.000300j
+-0.001089+0.000150j
+-0.000974+0.000024j
+-0.000834-0.000070j
+-0.000677-0.000128j
+-0.000513-0.000147j
+-0.000350-0.000126j
+-0.000199-0.000068j
+-0.000068+0.000024j
+0.000035+0.000143j
+0.000105+0.000281j
+0.000138+0.000431j
+0.000133+0.000582j
+0.000091+0.000726j
+0.000016+0.000854j
+-0.000089+0.000958j
+-0.000215+0.001032j
+-0.000355+0.001072j
+-0.000501+0.001076j
+-0.000643+0.001044j
+-0.000772+0.000978j
+-0.000882+0.000882j
+-0.000965+0.000762j
+-0.001016+0.000626j
+-0.001034+0.000481j
+-0.001017+0.000337j
+-0.000966+0.000201j
+-0.000885+0.000082j
+-0.000778-0.000014j
+-0.000653-0.000082j
+-0.000517-0.000118j
+-0.000378-0.000121j
+-0.000243-0.000090j
+-0.000122-0.000029j
+-0.000020+0.000058j
+0.000056+0.000165j
+0.000103+0.000287j
+0.000119+0.000415j
+0.000102+0.000540j
+0.000055+0.000657j
+-0.000019+0.000757j
+-0.000115+0.000835j
+-0.000227+0.000886j
+-0.000347+0.000907j
+-0.000469+0.000898j
+-0.000585+0.000859j
+-0.000688+0.000792j
+-0.000772+0.000702j
+-0.000831+0.000595j
+-0.000863+0.000477j
+-0.000866+0.000354j
+-0.000839+0.000235j
+-0.000786+0.000125j
+-0.000708+0.000032j
+-0.000611-0.000040j
+-0.000501-0.000087j
+-0.000385-0.000106j
+-0.000268-0.000097j
+-0.000159-0.000061j
+-0.000063-0.000001j
+0.000015+0.000080j
+0.000070+0.000175j
+0.000099+0.000280j
+0.000101+0.000387j
+0.000077+0.000490j
+0.000028+0.000582j
+-0.000042+0.000659j
+-0.000128+0.000715j
+-0.000225+0.000748j
+-0.000327+0.000755j
+-0.000428+0.000737j
+-0.000521+0.000694j
+-0.000601+0.000630j
+-0.000663+0.000548j
+-0.000703+0.000454j
+-0.000720+0.000352j
+-0.000712+0.000250j
+-0.000681+0.000152j
+-0.000627+0.000065j
+-0.000555-0.000006j
+-0.000469-0.000058j
+-0.000374-0.000088j
+-0.000275-0.000095j
+-0.000180-0.000078j
+-0.000092-0.000040j
+-0.000017+0.000017j
+0.000040+0.000090j
+0.000078+0.000173j
+0.000093+0.000261j
+0.000086+0.000350j
+0.000058+0.000432j
+0.000010+0.000504j
+-0.000054+0.000561j
+-0.000130+0.000600j
+-0.000213+0.000619j
+-0.000297+0.000616j
+-0.000379+0.000592j
+-0.000452+0.000548j
+-0.000513+0.000488j
+-0.000557+0.000415j
+-0.000582+0.000334j
+-0.000588+0.000248j
+-0.000573+0.000164j
+-0.000538+0.000086j
+-0.000487+0.000019j
+-0.000422-0.000035j
+-0.000347-0.000071j
+-0.000266-0.000088j
+-0.000185-0.000086j
+-0.000107-0.000065j
+-0.000038-0.000027j
+0.000018+0.000025j
+0.000060+0.000089j
+0.000083+0.000160j
+0.000089+0.000233j
+0.000076+0.000304j
+0.000046+0.000369j
+0.000001+0.000423j
+-0.000056+0.000464j
+-0.000121+0.000489j
+-0.000190+0.000497j
+-0.000259+0.000487j
+-0.000323+0.000461j
+-0.000379+0.000419j
+-0.000423+0.000365j
+-0.000453+0.000301j
+-0.000467+0.000232j
+-0.000465+0.000161j
+-0.000445+0.000093j
+-0.000411+0.000032j
+-0.000364-0.000019j
+-0.000306-0.000058j
+-0.000242-0.000081j
+-0.000175-0.000090j
+-0.000109-0.000082j
+-0.000048-0.000059j
+0.000005-0.000023j
+0.000047+0.000024j
+0.000075+0.000078j
+0.000089+0.000137j
+0.000088+0.000196j
+0.000072+0.000252j
+0.000042+0.000302j
+0.000002+0.000341j
+-0.000048+0.000369j
+-0.000102+0.000384j
+-0.000158+0.000384j
+-0.000213+0.000370j
+-0.000262+0.000343j
+-0.000304+0.000304j
+-0.000335+0.000256j
+-0.000354+0.000202j
+-0.000359+0.000145j
+-0.000351+0.000088j
+-0.000330+0.000034j
+-0.000298-0.000012j
+-0.000255-0.000050j
+-0.000206-0.000077j
+-0.000152-0.000091j
+-0.000098-0.000093j
+-0.000046-0.000082j
+0.000002-0.000059j
+0.000041-0.000027j
+0.000071+0.000014j
+0.000089+0.000059j
+0.000095+0.000106j
+0.000090+0.000153j
+0.000073+0.000196j
+0.000045+0.000232j
+0.000010+0.000260j
+-0.000031+0.000278j
+-0.000075+0.000284j
+-0.000120+0.000279j
+-0.000162+0.000263j
+-0.000199+0.000237j
+-0.000228+0.000203j
+-0.000249+0.000162j
+-0.000259+0.000117j
+-0.000259+0.000071j
+-0.000248+0.000026j
+-0.000227-0.000014j
+-0.000197-0.000049j
+-0.000161-0.000076j
+-0.000120-0.000093j
+-0.000077-0.000101j
+-0.000034-0.000098j
+0.000006-0.000086j
+0.000042-0.000064j
+0.000070-0.000036j
+0.000090-0.000002j
+0.000101+0.000034j
+0.000102+0.000071j
+0.000093+0.000107j
+0.000077+0.000139j
+0.000052+0.000165j
+0.000022+0.000184j
+-0.000011+0.000194j
+-0.000046+0.000196j
+-0.000081+0.000188j
+-0.000113+0.000173j
+-0.000140+0.000150j
+-0.000161+0.000121j
+-0.000174+0.000089j
+-0.000180+0.000054j
+-0.000177+0.000020j
+-0.000167-0.000013j
+-0.000150-0.000041j
+-0.000127-0.000063j
+-0.000100-0.000077j
+-0.000071-0.000084j
+-0.000044-0.000080j
+-0.000020-0.000066j
+-0.000009-0.000035j
diff --git a/gnuradio-examples/python/apps/hf_radio/ssbagc.py b/gnuradio-examples/python/apps/hf_radio/ssbagc.py
new file mode 100644
index 0000000000..fdf40bc6b0
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/ssbagc.py
@@ -0,0 +1,48 @@
+# post detection agc processing
+#
+# Imagine that the usual gnuradio copyright stuff is right here.
+#
+# This agc strategy is copied more or less verbatim from
+# weaver_isb_am1_usrp3.py by cswiger.
+#
+# Thanks.
+#
+# Then modified in a variety of ways.
+#
+# There doesn't appear to be a way to hook multiple blocks to the
+# input port when building a hier block like this. Thus the
+# split below.
+#
+# Basic operation.
+# Power is estimated by squaring the input.
+# Low pass filter using a 1 pole iir.
+# The time constant can be tweaked by changing the taps.
+# Currently there is no implementation to change this while operating
+#   a potentially useful addition.
+# The log block turns this into dB
+# gain adjusts the agc authority.
+#
+# M. Revnell 2006-Jan
+
+from gnuradio import gr, gru
+
+class agc( gr.hier_block ):
+    def __init__( self, fg ):
+        self.split = gr.multiply_const_ff( 1 )
+        self.sqr   = gr.multiply_ff( )
+        self.int0  = gr.iir_filter_ffd( [.004, 0], [0, .999] )
+        self.offs  = gr.add_const_ff( -30 )
+        self.gain  = gr.multiply_const_ff( 70 )
+        self.log   = gr.nlog10_ff( 10, 1 )
+        self.agc   = gr.divide_ff( )
+
+        fg.connect(   self.split,        ( self.agc,   0 ) )
+        fg.connect(   self.split,        ( self.sqr,   0 ) )
+        fg.connect(   self.split,        ( self.sqr,   1 ) )
+        fg.connect(   self.sqr,            self.int0       )
+        fg.connect(   self.int0,           self.log        )
+        fg.connect(   self.log,            self.offs       )
+        fg.connect(   self.offs,           self.gain       )
+        fg.connect(   self.gain,         ( self.agc,   1 ) )
+
+        gr.hier_block.__init__( self, fg, self.split, self.agc )
diff --git a/gnuradio-examples/python/apps/hf_radio/ssbdemod.py b/gnuradio-examples/python/apps/hf_radio/ssbdemod.py
new file mode 100644
index 0000000000..c73567b666
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/ssbdemod.py
@@ -0,0 +1,97 @@
+# This tries to push the hilbert transform for ssb demod back into the
+# freq. xlating filter.
+#
+# The usual gnuradio copyright notice is hereby included by reference.
+#
+# The starting point for this was weaver_isb_am1_usrp3.py.
+#
+# The tap coefficients for freq_xlating_fir_filter_ccf were generated
+# externally and are read from a file because I didn't want to learn how
+# to make fir filters with arbitrary phase response using python numeric
+# facilities.
+#
+# They were generated using Scilab which I am already familiar with.
+# M. Revnell Jan 06
+
+from gnuradio import gr, gru
+from gnuradio import audio
+from gnuradio import usrp
+
+class ssb_demod( gr.hier_block ):
+    def __init__( self, fg, if_rate, af_rate ):
+
+        self.if_rate  = if_rate
+        self.af_rate  = af_rate
+        self.if_decim = if_rate / af_rate
+        self.sideband = 1
+
+        self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()])
+        
+        self.audio_taps = gr.firdes.low_pass(
+            1.0,
+            self.af_rate,
+            3e3,
+            600,
+            gr.firdes.WIN_HAMMING )
+
+        self.xlate = gr.freq_xlating_fir_filter_ccc(
+            self.if_decim,
+            self.xlate_taps,
+            0,
+            self.if_rate )
+
+        self.split = gr.complex_to_float()
+
+        self.lpf = gr.fir_filter_fff(
+            1, self.audio_taps )
+
+        self.sum   = gr.add_ff( )
+        self.am_sel = gr.multiply_const_ff( 0 )
+        self.sb_sel = gr.multiply_const_ff( 1 )
+        self.mixer  = gr.add_ff()
+        self.am_det = gr.complex_to_mag()
+                
+        fg.connect(   self.xlate,       self.split      )
+        fg.connect( ( self.split,0 ), ( self.sum,0    ) )
+        fg.connect( ( self.split,1 ), ( self.sum,1    ) )
+        fg.connect(    self.sum,        self.sb_sel     )
+        fg.connect(    self.xlate,      self.am_det     )
+        fg.connect(    self.sb_sel,   ( self.mixer, 0 ) )
+        fg.connect(    self.am_det,     self.am_sel     )
+        fg.connect(    self.am_sel,   ( self.mixer, 1 ) )
+        fg.connect(    self.mixer,      self.lpf        )
+        
+        gr.hier_block.__init__( self, fg, self.xlate, self.lpf )
+
+    def upper_sb( self ):
+        self.xlate.set_taps([v.conjugate() for v in self.xlate_taps])    
+        self.sb_sel.set_k( 1.0 )
+        self.am_sel.set_k( 0.0 )
+
+    def lower_sb( self ):
+        self.xlate.set_taps(self.xlate_taps)
+        self.sb_sel.set_k( 1.0 )
+        self.am_sel.set_k( 0.0 )
+        
+    def set_am( self ):
+        taps = gr.firdes.low_pass( 1.0,
+                                   self.if_rate,
+                                   5e3,
+                                   2e3,
+                                   gr.firdes.WIN_HAMMING )
+        self.xlate.set_taps( taps )
+        self.sb_sel.set_k( 0.0 )
+        self.am_sel.set_k( 1.0 )
+
+    def set_bw( self, bw ):
+        self.audio_taps = gr.firdes.low_pass(
+            1.0,
+            self.af_rate,
+            bw,
+            600,
+            gr.firdes.WIN_HAMMING )
+        self.lpf.set_taps( self.audio_taps )
+
+    def tune( self, freq ):
+        self.xlate.set_center_freq( freq )
+
diff --git a/gnuradio-examples/python/apps/hf_radio/startup.py b/gnuradio-examples/python/apps/hf_radio/startup.py
new file mode 100644
index 0000000000..093369b577
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/startup.py
@@ -0,0 +1 @@
+from radio import *
diff --git a/gnuradio-examples/python/apps/hf_radio/ui.py b/gnuradio-examples/python/apps/hf_radio/ui.py
new file mode 100755
index 0000000000..71b73c128e
--- /dev/null
+++ b/gnuradio-examples/python/apps/hf_radio/ui.py
@@ -0,0 +1,295 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+# generated by wxGlade 0.4 on Mon Jan  2 19:02:03 2006
+
+import wx
+
+class ui_frame(wx.Frame):
+    def __init__(self, *args, **kwds):
+        # begin wxGlade: ui_frame.__init__
+        kwds["style"] = wx.DEFAULT_FRAME_STYLE
+        wx.Frame.__init__(self, *args, **kwds)
+        self.sizer_1_staticbox = wx.StaticBox(self, -1, "sizer_1")
+        self.freq_disp = wx.SpinCtrl(self, -1, "", min=0, max=100)
+        self.spin_e6 = wx.SpinButton(self, -1 )
+        self.spin_e5 = wx.SpinButton(self, -1 )
+        self.spin_e4 = wx.SpinButton(self, -1 )
+        self.spin_e3 = wx.SpinButton(self, -1 )
+        self.spin_e2 = wx.SpinButton(self, -1 )
+        self.spin_e1 = wx.SpinButton(self, -1 )
+        self.spin_e0 = wx.SpinButton(self, -1 )
+        self.panel_1 = wx.Panel(self, -1)
+        self.panel_2 = wx.Panel(self, -1)
+        self.button_lsb = wx.Button(self, -1, "LSB")
+        self.button_usb = wx.Button(self, -1, "USB")
+        self.button_am = wx.Button(self, -1, "AM")
+        self.label_1 = wx.StaticText(self, -1, "VOLUME")
+        self.label_2 = wx.StaticText(self, -1, "PGA")
+        self.agc_level = wx.TextCtrl(self, -1, "")
+        self.label_6 = wx.StaticText(self, -1, "")
+        self.volume = wx.SpinCtrl(self, -1, "", min=0, max=100)
+        self.pga = wx.SpinCtrl(self, -1, "", min=0, max=100)
+        self.agc_max = wx.TextCtrl(self, -1, "")
+        self.label_7 = wx.StaticText(self, -1, "")
+        self.label_4 = wx.StaticText(self, -1, "AGC AUTHORITY")
+        self.label_5 = wx.StaticText(self, -1, "AGC REF LVL")
+        self.label_3 = wx.StaticText(self, -1, "BANDWIDTH")
+        self.label_8 = wx.StaticText(self, -1, "")
+        self.agc_gain = wx.TextCtrl(self, -1, "")
+        self.agc_gain_s = wx.SpinButton(self, -1 )
+        self.agc_ref = wx.TextCtrl(self, -1, "")
+        self.agc_ref_s = wx.SpinButton(self, -1 )
+        self.bandwidth = wx.TextCtrl(self, -1, "")
+        self.bw_spin = wx.SpinButton(self, -1 )
+        self.label_9 = wx.StaticText(self, -1, "")
+        self.rssi = wx.Gauge(self, -1, 10, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH)
+        self.fe_panel = wx.Panel(self, -1)
+        self.if_panel = wx.Panel(self, -1)
+
+        self.__set_properties()
+        self.__do_layout()
+
+        self.Bind(wx.EVT_SPINCTRL, self.tune_evt, self.freq_disp)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e6, self.spin_e6)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e6, self.spin_e6)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e5, self.spin_e5)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e5, self.spin_e5)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e4, self.spin_e4)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e4, self.spin_e4)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e3, self.spin_e3)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e3, self.spin_e3)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e2, self.spin_e2)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e2, self.spin_e2)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e1, self.spin_e1)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e1, self.spin_e1)
+        self.Bind(wx.EVT_SPIN_DOWN, self.down_e0, self.spin_e0)
+        self.Bind(wx.EVT_SPIN_UP, self.up_e0, self.spin_e0)
+        self.Bind(wx.EVT_BUTTON, self.set_lsb, self.button_lsb)
+        self.Bind(wx.EVT_BUTTON, self.set_usb, self.button_usb)
+        self.Bind(wx.EVT_BUTTON, self.set_am, self.button_am)
+        self.Bind(wx.EVT_SPINCTRL, self.event_vol, self.volume)
+        self.Bind(wx.EVT_SPINCTRL, self.event_pga, self.pga)
+        self.Bind(wx.EVT_SPIN_DOWN, self.agc_gain_down, self.agc_gain_s)
+        self.Bind(wx.EVT_SPIN_UP, self.agc_gain_up, self.agc_gain_s)
+        self.Bind(wx.EVT_SPIN_DOWN, self.agc_ref_down, self.agc_ref_s)
+        self.Bind(wx.EVT_SPIN_UP, self.agc_ref_up, self.agc_ref_s)
+        self.Bind(wx.EVT_SPIN_DOWN, self.bw_down, self.bw_spin)
+        self.Bind(wx.EVT_SPIN_UP, self.bw_up, self.bw_spin)
+        # end wxGlade
+
+    def __set_properties(self):
+        # begin wxGlade: ui_frame.__set_properties
+        self.SetTitle("frame_1")
+        self.freq_disp.SetFont(wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
+        self.rssi.SetMinSize((315, 10))
+        self.rssi.SetForegroundColour(wx.Colour(255, 0, 0))
+        # end wxGlade
+
+    def __do_layout(self):
+        # begin wxGlade: ui_frame.__do_layout
+        sizer_1 = wx.StaticBoxSizer(self.sizer_1_staticbox, wx.VERTICAL)
+        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_4 = wx.BoxSizer(wx.VERTICAL)
+        grid_sizer_4 = wx.GridSizer(2, 4, 0, 0)
+        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
+        grid_sizer_3 = wx.GridSizer(2, 4, 0, 0)
+        sizer_3 = wx.BoxSizer(wx.VERTICAL)
+        grid_sizer_1 = wx.GridSizer(2, 3, 0, 0)
+        grid_sizer_2 = wx.GridSizer(1, 7, 0, 0)
+        sizer_3.Add(self.freq_disp, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e6, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e5, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e4, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e3, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e2, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e1, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_2.Add(self.spin_e0, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0)
+        grid_sizer_1.Add(self.button_lsb, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.button_usb, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_1.Add(self.button_am, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_3.Add(grid_sizer_1, 1, wx.EXPAND, 0)
+        sizer_2.Add(sizer_3, 1, wx.EXPAND, 0)
+        grid_sizer_3.Add(self.label_1, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.agc_level, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.label_6, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.volume, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.pga, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.agc_max, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_3.Add(self.label_7, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_4.Add(grid_sizer_3, 1, wx.EXPAND, 0)
+        grid_sizer_4.Add(self.label_4, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_4.Add(self.label_5, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_4.Add(self.label_3, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_4.Add(self.label_8, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_6.Add(self.agc_gain, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_6.Add(self.agc_gain_s, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_4.Add(sizer_6, 1, wx.EXPAND, 0)
+        sizer_7.Add(self.agc_ref, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_7.Add(self.agc_ref_s, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_4.Add(sizer_7, 1, wx.EXPAND, 0)
+        sizer_5.Add(self.bandwidth, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_5.Add(self.bw_spin, 0, wx.ADJUST_MINSIZE, 0)
+        grid_sizer_4.Add(sizer_5, 1, wx.EXPAND, 0)
+        grid_sizer_4.Add(self.label_9, 0, wx.ADJUST_MINSIZE, 0)
+        sizer_4.Add(grid_sizer_4, 1, wx.EXPAND, 0)
+        sizer_4.Add(self.rssi, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        sizer_2.Add(sizer_4, 1, wx.EXPAND, 0)
+        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
+        sizer_1.Add(self.fe_panel, 1, wx.EXPAND, 0)
+        sizer_1.Add(self.if_panel, 1, wx.EXPAND, 0)
+        self.SetAutoLayout(True)
+        self.SetSizer(sizer_1)
+        sizer_1.Fit(self)
+        sizer_1.SetSizeHints(self)
+        self.Layout()
+        # end wxGlade
+
+    def down_e6(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e6' not implemented"
+        event.Skip()
+
+    def up_e6(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e6' not implemented"
+        event.Skip()
+
+    def down_e5(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e5' not implemented"
+        event.Skip()
+
+    def up_e5(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e5' not implemented"
+        event.Skip()
+
+    def down_e4(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e4' not implemented"
+        event.Skip()
+
+    def up_e4(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e4' not implemented"
+        event.Skip()
+
+    def down_e3(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e3' not implemented"
+        event.Skip()
+
+    def up_e3(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e3' not implemented"
+        event.Skip()
+
+    def down_e2(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e2' not implemented"
+        event.Skip()
+
+    def up_e2(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e2' not implemented"
+        event.Skip()
+
+    def down_e1(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e1' not implemented"
+        event.Skip()
+
+    def up_e1(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e1' not implemented"
+        event.Skip()
+
+    def down_e0(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `down_e0' not implemented"
+        event.Skip()
+
+    def up_e0(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `up_e0' not implemented"
+        event.Skip()
+
+    def event_vol(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `event_vol' not implemented"
+        event.Skip()
+
+    def event_pga(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `event_pga' not implemented"
+        event.Skip()
+
+    def set_lsb(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `set_lsb' not implemented"
+        event.Skip()
+
+    def set_usb(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `set_usb' not implemented"
+        event.Skip()
+
+    def set_am(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `set_am' not implemented"
+        event.Skip()
+
+    def set_bw(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `set_bw' not implemented"
+        event.Skip()
+
+    def tune_evt(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `tune_evt' not implemented"
+        event.Skip()
+
+    def bw_down(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `bw_down' not implemented"
+        event.Skip()
+
+    def bw_up(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `bw_up' not implemented"
+        event.Skip()
+
+    def agc_gain_down(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `agc_gain_down' not implemented"
+        event.Skip()
+
+    def agc_gain_up(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `agc_gain_up' not implemented"
+        event.Skip()
+
+    def agc_ref_down(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `agc_ref_down' not implemented"
+        event.Skip()
+
+    def agc_ref_up(self, event): # wxGlade: ui_frame.<event_handler>
+        print "Event handler `agc_ref_up' not implemented"
+        event.Skip()
+
+# end of class ui_frame
+
+
+class RadioFrame(wx.Frame):
+    def __init__(self, *args, **kwds):
+        # content of this block not found: did you rename this class?
+        pass
+
+    def __set_properties(self):
+        # content of this block not found: did you rename this class?
+        pass
+
+    def __do_layout(self):
+        # content of this block not found: did you rename this class?
+        pass
+
+# end of class RadioFrame
+
+
+class MyFrame(wx.Frame):
+    def __init__(self, *args, **kwds):
+        # content of this block not found: did you rename this class?
+        pass
+
+    def __set_properties(self):
+        # content of this block not found: did you rename this class?
+        pass
+
+    def __do_layout(self):
+        # content of this block not found: did you rename this class?
+        pass
+
+# end of class MyFrame
+
+
diff --git a/gnuradio-examples/python/audio/Makefile.am b/gnuradio-examples/python/audio/Makefile.am
new file mode 100644
index 0000000000..27cea62a31
--- /dev/null
+++ b/gnuradio-examples/python/audio/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+EXTRA_DIST = 			\
+	audio_copy.py		\
+	audio_play.py		\
+	audio_to_file.py	\
+	dial_tone.py		\
+	mono_tone.py		\
+	multi_tone.py		\
+	spectrum_inversion.py	\
+	test_resampler.py	
+
+
diff --git a/gnuradio-examples/python/audio/audio_copy.py b/gnuradio-examples/python/audio/audio_copy.py
new file mode 100755
index 0000000000..56fa836d29
--- /dev/null
+++ b/gnuradio-examples/python/audio/audio_copy.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-I", "--audio-input", type="string", default="",
+                          help="pcm input device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
+                          help="set sample rate to RATE (48000)")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = int(options.sample_rate)
+        src = audio.source (sample_rate, options.audio_input)
+        dst = audio.sink (sample_rate, options.audio_output)
+
+        # Determine the maximum number of outputs on the source and
+        # maximum number of inputs on the sink, then connect together
+        # the most channels we can without overlap
+        nchan = min (src.output_signature().max_streams(),
+                     dst.input_signature().max_streams())
+
+        for i in range (nchan):
+            self.connect ((src, i), (dst, i))
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
+    
diff --git a/gnuradio-examples/python/audio/audio_play.py b/gnuradio-examples/python/audio/audio_play.py
new file mode 100755
index 0000000000..e70b0f942d
--- /dev/null
+++ b/gnuradio-examples/python/audio/audio_play.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-F", "--filename", type="string", default="audio.dat",
+                          help="read input from FILE")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
+                          help="set sample rate to RATE (48000)")
+        parser.add_option("-R", "--repeat", action="store_true", default=False)
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = int(options.sample_rate)
+        src = gr.file_source (gr.sizeof_float, options.filename, options.repeat)
+        dst = audio.sink (sample_rate, options.audio_output)
+        self.connect(src, dst)
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/audio/audio_to_file.py b/gnuradio-examples/python/audio/audio_to_file.py
new file mode 100755
index 0000000000..74e1ea7ac3
--- /dev/null
+++ b/gnuradio-examples/python/audio/audio_to_file.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        usage="%prog: [options] output_filename"
+        parser = OptionParser(option_class=eng_option, usage=usage)
+        parser.add_option("-I", "--audio-input", type="string", default="",
+                          help="pcm input device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
+                          help="set sample rate to RATE (48000)")
+        parser.add_option("-N", "--nsamples", type="eng_float", default=None,
+                          help="number of samples to collect [default=+inf]")
+     
+        (options, args) = parser.parse_args ()
+        if len(args) != 1:
+            parser.print_help()
+            raise SystemExit, 1
+        filename = args[0]
+
+        sample_rate = int(options.sample_rate)
+        src = audio.source (sample_rate, options.audio_input)
+        dst = gr.file_sink (gr.sizeof_float, filename)
+
+        if options.nsamples is None:
+            self.connect((src, 0), dst)
+        else:
+            head = gr.head(gr.sizeof_float, int(options.nsamples))
+            self.connect((src, 0), head, dst)
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/audio/dial_squelch.py b/gnuradio-examples/python/audio/dial_squelch.py
new file mode 100755
index 0000000000..d947e58604
--- /dev/null
+++ b/gnuradio-examples/python/audio/dial_squelch.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, audio, eng_option
+from gnuradio.eng_option import eng_option
+from math import pi, cos
+from optparse import OptionParser
+
+"""
+This script generates a standard dial tone and then applies a sinusoidal
+envelope to vary it's loudness.  The audio is then passed through the
+power squelch block before it gets sent to the sound card. By varying
+the command line parameters, one can see the effect of differing
+amounts of power averaging, threshold, and attack/decay ramping.
+"""
+
+class app_flow_graph(gr.flow_graph):
+    def __init__(self, options, args):
+        gr.flow_graph.__init__(self)
+	
+	# Create dial tone by adding two sine waves
+	SRC1 = gr.sig_source_f(options.rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0)
+	SRC2 = gr.sig_source_f(options.rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0)
+	ADD = gr.add_ff()
+
+	# Convert to vector stream (and back) to apply raised cosine envelope
+	# You could also do this with a vector_source_f block that repeats.
+	S2V = gr.stream_to_vector(gr.sizeof_float, options.rate)
+	ENV = [0.5-cos(2*pi*x/options.rate)/2 for x in range(options.rate)]
+	MLT = gr.multiply_const_vff(ENV)
+	V2S = gr.vector_to_stream(gr.sizeof_float, options.rate)
+
+	# Run through power squelch with user supplied or default options
+	# Zero output when squelch is invoked
+	SQL = gr.pwr_squelch_ff(options.threshold, options.alpha, options.ramp, False)
+	DST = audio.sink(options.rate)
+
+	# Solder it all together
+	self.connect(SRC1, (ADD, 0))
+	self.connect(SRC2, (ADD, 1))
+	self.connect(ADD, S2V, MLT, V2S, SQL, DST)
+	
+def main():
+    parser = OptionParser(option_class=eng_option)
+    parser.add_option("-r", "--rate", type="int", default=8000, help="set audio output sample rate to RATE", metavar="RATE")
+    parser.add_option("-t", "--threshold", type="eng_float", default=-10.0, help="set power squelch to DB", metavar="DB")
+    parser.add_option("-a", "--alpha", type="eng_float", default=None, help="set alpha to ALPHA", metavar="ALPHA")
+    parser.add_option("-m", "--ramp", type="int", default=None, help="set attack/decay ramp to SAMPLES", metavar="SAMPLES")
+    (options, args) = parser.parse_args()
+
+    if options.alpha == None:
+	options.alpha = 50.0/options.rate
+	
+    if options.ramp == None:
+	options.ramp = options.rate/50	# ~ 20 ms
+
+    print "Using audio rate of", options.rate
+    print "Using threshold of", options.threshold, "db"
+    print "Using alpha of", options.alpha
+    print "Using ramp of", options.ramp, "samples"
+
+    fg = app_flow_graph(options, args)
+
+    try:
+      fg.run()
+    except KeyboardInterrupt:
+      pass
+
+if __name__ == "__main__":
+    main()
diff --git a/gnuradio-examples/python/audio/dial_tone.py b/gnuradio-examples/python/audio/dial_tone.py
new file mode 100755
index 0000000000..3ce84eb596
--- /dev/null
+++ b/gnuradio-examples/python/audio/dial_tone.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
+                          help="set sample rate to RATE (48000)")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = int(options.sample_rate)
+        ampl = 0.1
+
+        src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)
+        src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl)
+        dst = audio.sink (sample_rate, options.audio_output)
+        self.connect (src0, (dst, 0))
+        self.connect (src1, (dst, 1))
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/audio/dialtone_v.py b/gnuradio-examples/python/audio/dialtone_v.py
new file mode 100755
index 0000000000..e704414a9e
--- /dev/null
+++ b/gnuradio-examples/python/audio/dialtone_v.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, audio
+from math import pi, sin
+
+"""
+This test script demonstrates the use of element-wise vector processing
+vs. stream processing.  The example is artificial in that the stream
+version in dial_tone.py is the normal way to do it; in addition, the
+envelope processing here is just for demo purposes and isn't needed.
+"""
+
+# For testing different buffer sizes
+rate = 48000
+
+fg = gr.flow_graph()
+
+# Two streams of floats
+a = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0);
+b = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0);
+
+# Turn them into vectors of length 'size'
+av = gr.stream_to_vector(gr.sizeof_float, rate)
+bv = gr.stream_to_vector(gr.sizeof_float, rate)
+
+# Make a vector adder for float vectors
+adder = gr.add_vff(rate)
+
+# Make a 1 Hz sine envelope
+envelope = [sin(2*pi*x/rate)*0.5 for x in range(rate)]
+multiplier = gr.multiply_const_vff(envelope)
+
+# Make an offset adder
+offset = gr.add_const_vff((0.5,)*rate)
+
+# Turn the vector back into a stream of floats
+result = gr.vector_to_stream(gr.sizeof_float, rate)
+
+# Play it
+sink = audio.sink(rate)
+
+fg.connect(a, av)
+fg.connect(b, bv)
+fg.connect(av, (adder, 0))
+fg.connect(bv, (adder, 1))
+fg.connect(adder, multiplier, offset, result, sink)
+
+try:
+    fg.run()
+except KeyboardInterrupt:
+    pass
diff --git a/gnuradio-examples/python/audio/mono_tone.py b/gnuradio-examples/python/audio/mono_tone.py
new file mode 100755
index 0000000000..84c3b542ee
--- /dev/null
+++ b/gnuradio-examples/python/audio/mono_tone.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+#import os
+#print os.getpid()
+#raw_input('Attach gdb and press Enter: ')
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
+                          help="set sample rate to RATE (48000)")
+        parser.add_option("-D", "--dont-block", action="store_false", default=True,
+                          dest="ok_to_block")
+
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = int(options.sample_rate)
+        ampl = 0.1
+
+        src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 650, ampl)
+
+        dst = audio.sink (sample_rate,
+                          options.audio_output,
+                          options.ok_to_block)
+            
+        self.connect (src0, (dst, 0))
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/audio/multi_tone.py b/gnuradio-examples/python/audio/multi_tone.py
new file mode 100755
index 0000000000..c6f83050e2
--- /dev/null
+++ b/gnuradio-examples/python/audio/multi_tone.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+#import os
+#print os.getpid()
+#raw_input('Attach gdb and press Enter: ')
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
+                          help="set sample rate to RATE (48000)")
+        parser.add_option ("-m", "--max-channels", type="int", default="16",
+                           help="set maximum channels to use")
+        parser.add_option("-D", "--dont-block", action="store_false", default=True,
+                          dest="ok_to_block")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = int(options.sample_rate)
+        limit_channels = options.max_channels
+
+        ampl = 0.1
+
+        # With a tip of the hat to Harry Partch, may he R.I.P.
+        # See "Genesis of a Music".  He was into some very wild tunings...
+        base = 392
+        ratios = { 1 : 1.0,
+                   3 : 3.0/2,
+                   5 : 5.0/4,
+                   7 : 7.0/4,
+                   9 : 9.0/8,
+                   11 : 11.0/8 }
+
+        # progression = (1, 5, 3, 7)
+        # progression = (1, 9, 3, 7)
+        # progression = (3, 7, 9, 11)
+        # progression = (7, 11, 1, 5)
+        progression = (7, 11, 1, 5, 9)
+
+        dst = audio.sink (sample_rate,
+                          options.audio_output,
+                          options.ok_to_block)
+    
+        max_chan = dst.input_signature().max_streams()
+        if (max_chan == -1) or (max_chan > limit_channels):
+            max_chan = limit_channels
+
+        for i in range (max_chan):
+            quo, rem = divmod (i, len (progression))
+            freq = base * ratios[progression[rem]] * (quo + 1)
+            src = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, freq, ampl)
+            self.connect (src, (dst, i))
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/audio/spectrum_inversion.py b/gnuradio-examples/python/audio/spectrum_inversion.py
new file mode 100755
index 0000000000..9bb87aa4b1
--- /dev/null
+++ b/gnuradio-examples/python/audio/spectrum_inversion.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+#
+# Gang - Here's a simple script that demonstrates spectrum inversion
+# using the multiply by [1,-1] method (mixing with Nyquist frequency).
+# Requires nothing but a sound card, and sounds just like listening
+# to a SSB signal on the wrong sideband.
+#
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-I", "--audio-input", type="string", default="",
+                          help="pcm input device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-r", "--sample-rate", type="eng_float", default=8000,
+                          help="set sample rate to RATE (8000)")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = int(options.sample_rate)
+        src = audio.source (sample_rate, options.audio_input)
+        dst = audio.sink (sample_rate, options.audio_output)
+
+	vec1 = [1, -1]
+	vsource = gr.vector_source_f(vec1, True)
+	multiply = gr.multiply_ff()
+
+	self.connect(src, (multiply, 0))
+	self.connect(vsource, (multiply, 1))
+	self.connect(multiply, dst)
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/audio/test_resampler.py b/gnuradio-examples/python/audio/test_resampler.py
new file mode 100755
index 0000000000..6c9e5a7608
--- /dev/null
+++ b/gnuradio-examples/python/audio/test_resampler.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-i", "--input-rate", type="eng_float", default=8000,
+                          help="set input sample rate to RATE (%default)")
+        parser.add_option("-o", "--output-rate", type="eng_float", default=48000,
+                          help="set output sample rate to RATE (%default)")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        input_rate = int(options.input_rate)
+        output_rate = int(options.output_rate)
+
+        interp = gru.lcm(input_rate, output_rate) / input_rate
+        decim = gru.lcm(input_rate, output_rate) / output_rate
+
+        print "interp =", interp
+        print "decim  =", decim
+
+        ampl = 0.1
+        src0 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 650, ampl)
+        rr = blks.rational_resampler_fff(self, interp, decim)
+        dst = audio.sink (output_rate, options.audio_output)
+        self.connect (src0, rr, (dst, 0))
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/digital_voice/Makefile.am b/gnuradio-examples/python/digital_voice/Makefile.am
new file mode 100644
index 0000000000..ed88c22d90
--- /dev/null
+++ b/gnuradio-examples/python/digital_voice/Makefile.am
@@ -0,0 +1,23 @@
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+EXTRA_DIST = 					\
+	encdec.py				
diff --git a/gnuradio-examples/python/digital_voice/encdec.py b/gnuradio-examples/python/digital_voice/encdec.py
new file mode 100755
index 0000000000..11936a4b9c
--- /dev/null
+++ b/gnuradio-examples/python/digital_voice/encdec.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, blks
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-I", "--audio-input", type="string", default="",
+                          help="pcm input device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        sample_rate = 8000
+        src = audio.source(sample_rate, options.audio_input)
+        tx = blks.digital_voice_tx(self)
+        if_gain = gr.multiply_const_cc(10000)
+        # channel simulator here...
+        rx = blks.digital_voice_rx(self)
+        dst = audio.sink(sample_rate, options.audio_output)
+
+        self.connect(src, tx, if_gain, rx, dst)
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/Makefile.am b/gnuradio-examples/python/gmsk2/Makefile.am
new file mode 100644
index 0000000000..cf2ffb39ea
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/Makefile.am
@@ -0,0 +1,38 @@
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+EXTRA_DIST =			\
+	benchmark_gmsk_rx.py	\
+	benchmark_gmsk_tx.py	\
+	benchmark_mpsk_rx.py	\
+	benchmark_mpsk_tx.py	\
+	fusb_options.py		\
+	gen_whitener.py		\
+	gmsk_test.py		\
+	pick_bitrate.py		\
+	receive_path.py		\
+	transmit_path.py	\
+	tunnel_ip_null_mac.py	
+
+
+
+
+
diff --git a/gnuradio-examples/python/gmsk2/README b/gnuradio-examples/python/gmsk2/README
new file mode 100644
index 0000000000..b3c343e4bb
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/README
@@ -0,0 +1,81 @@
+Quick overview of what's here:
+
+* gmsk_test.py: stand-alone program that exercises the GMSK packet tx
+and rx code.  The two halves are connected with a simulated noisy
+channel.  It's easy to add extra instrumentation to log various internal 
+states.  We used a variant of this code to get this working in the
+first place. 
+
+* benchmark_gmsk_tx.py: generates packets of the size you
+specify and sends them across the air using the USRP.  Known to work
+well using the USRP with the Flex 400 transceiver daughterboard.
+You can specify the bitrate to use with the -r <bitrate> command line
+parameter.  The default is 500k.  Some machines will do 1M or more.
+
+* benchmark_gmsk_rx.py: the receiver half of benchmark_gmsk_tx.py.
+Command line arguments are pretty much the same as tx.  Works well
+with a USRP and Flex 400 transceiver daughterboard.  Will also work
+with TVRX daugherboard, but you'll need to fiddle with the gain.  See
+below.  Prints a summary of each packet received and keeps a running
+total of packets received, and how many of them were error free.
+There are two levels of error reporting going on.  If the access code
+(PN code) and header of a packet were properly detected, then you'll
+get an output line.  If the CRC32 of the payload was correct you get
+"ok = True", else "ok = False".  The "pktno" is extracted from the
+received packet.  If there are skipped numbers, you're missing some
+packets.  Be sure you've got a suitable antenna connected to the TX/RX
+port on each board.  A "70 cm" / 420 MHz antenna for a ham
+handi-talkie works great.  These are available at ham radio supplies,
+etc.  The boards need to be at least 3m apart.  You can also try
+experimenting with the rx gain (-g <gain> command line option).
+
+Generally speaking, I start the rx first on one machine, and then fire
+up the tx on the other machine.  The tx also supports a discontinous
+transmission mode where it sends bursts of 5 packets and then waits 1
+second.  This is useful for ensuring that all the receiver control
+loops lock up fast enough.
+
+* tunnel.py: This program provides a framework for building your own
+MACs.  It creates a "TAP" interface in the kernel, typically gr0,
+and sends and receives ethernet frames through it.  See
+/usr/src/linux/Documentation/networking/tuntap.txt and/or Google for
+"universal tun tap".  The Linux 2.6 kernel includes the tun module, you
+don't have to build it.  You may have to "modprobe tun" if it's not
+loaded by default.  If /dev/net/tun doesn't exist, try "modprobe tun".
+
+To run this program you'll need to be root or running with the
+appropriate capability to open the tun interface.  You'll need to fire
+up two copies on different machines.  Once each is running you'll need
+to ifconfig the gr0 interface to set the IP address.
+
+This will allow two machines to talk, but anything beyond the two
+machines depends on your networking setup.  Left as an exercise...
+
+On machine A:
+
+  $ su
+  # ./tunnel.py --freq 423.0M --bitrate 500k
+  # # in another window on A, also as root...
+  # ifconfig gr0 10.10.10.1
+
+
+On machine B:
+
+  $ su
+  # ./tunnel.py --freq 423.0M --bitrate 500k
+  # # in another window on B, also as root...
+  # ifconfig gr0 10.10.10.2
+
+Now, on machine A you shold be able to ping machine B:
+
+  $ ping 10.10.10.2
+
+and you should see some output for each packet in the
+tunnel.py window if you used the -v option.
+
+Likewise, on machine B:
+
+  $ ping 10.10.10.1
+
+This now uses a carrier sense MAC, so you should be able to ssh
+between the machines, web browse, etc.
diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py b/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
new file mode 100755
index 0000000000..d1f70c5462
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random
+import struct
+
+# from current dir
+from receive_path import receive_path
+import fusb_options
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, demod_class, rx_subdev_spec,
+                 bitrate, decim_rate, spb,
+                 rx_callback, options, demod_kwargs):
+        gr.flow_graph.__init__(self)
+        self.rxpath = receive_path(self, demod_class, rx_subdev_spec,
+                                   bitrate, decim_rate, spb,
+                                   rx_callback, options, demod_kwargs)
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+global n_rcvd, n_right
+
+def main():
+    global n_rcvd, n_right
+
+    n_rcvd = 0
+    n_right = 0
+    
+    def rx_callback(ok, payload):
+        global n_rcvd, n_right
+        (pktno,) = struct.unpack('!H', payload[0:2])
+        n_rcvd += 1
+        if ok:
+            n_right += 1
+
+        print "ok = %r  pktno = %4d  n_rcvd = %4d  n_right = %4d" % (
+            ok, pktno, n_rcvd, n_right)
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Rx side A or B")
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                      help="set Rx frequency to FREQ [default=%default]",
+                      metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=None,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-g", "--rx-gain", type="eng_float", default=27,
+                      help="set rx gain")
+    parser.add_option("-S", "--spb", type="int", default=None,
+                      help="set samples/baud [default=%default]")
+    parser.add_option("-d", "--decim", type="intx", default=None,
+                      help="set fpga decim rate to DECIM [default=%default]")
+    fusb_options.add_options(parser)
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    demod_kwargs = { } # placeholder    
+    
+    # build the graph
+    fg = my_graph(blks.gmsk2_demod,
+                  options.rx_subdev_spec, options.bitrate,
+                  options.decim, options.spb, rx_callback,
+                  options, demod_kwargs)
+
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),)
+    print "spb:     %3d" % (fg.rxpath.spb(),)
+    print "decim:   %3d" % (fg.rxpath.decim(),)
+
+    ok = fg.rxpath.set_freq(options.freq)
+    if not ok:
+        print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),)
+        raise SystemExit
+    
+    fg.rxpath.set_gain(options.rx_gain)
+    print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: Failed to enable realtime scheduling."
+
+    fg.start()        # start flow graph
+    fg.wait()         # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py b/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
new file mode 100755
index 0000000000..2994003a02
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random
+import time
+import struct
+import sys
+
+# from current dir
+from transmit_path import transmit_path
+import fusb_options
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, mod_class, tx_subdev_spec,
+                 bitrate, interp_rate, spb, gain,
+                 options, mod_kwargs):
+        gr.flow_graph.__init__(self)
+        self.txpath = transmit_path(self, mod_class, tx_subdev_spec,
+                                    bitrate, interp_rate, spb, gain,
+                                    options, mod_kwargs)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    def send_pkt(payload='', eof=False):
+        return fg.txpath.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        print "ok = %r, payload = '%s'" % (ok, payload)
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Tx side A or B")
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                      help="set Tx and Rx frequency to FREQ [default=%default]",
+                      metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=None,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-S", "--spb", type="int", default=None,
+                      help="set samples/baud [default=%default]")
+    parser.add_option("-i", "--interp", type="intx", default=None,
+                      help="set fpga interpolation rate to INTERP [default=%default]")
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("", "--bt", type="float", default=0.3,
+                      help="set bandwidth-time product [default=%default]")
+    parser.add_option("-g", "--gain", type="eng_float", default=100.0,
+                      help="transmitter gain [default=%default]")
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("","--discontinuous", action="store_true", default=False,
+                      help="enable discontinous transmission (bursts of 5 packets)")
+    fusb_options.add_options(parser)
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    pkt_size = int(options.size)
+
+    mod_kwargs = {
+        'bt' : options.bt,
+        }
+
+    # build the graph
+    fg = my_graph(blks.gmsk2_mod, options.tx_subdev_spec,
+                  options.bitrate, options.interp, options.spb, options.gain,
+                  options, mod_kwargs)
+
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
+    print "spb:     %3d" % (fg.txpath.spb(),)
+    print "interp:  %3d" % (fg.txpath.interp(),)
+
+    ok = fg.txpath.set_freq(options.freq)
+    if not ok:
+        print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),)
+        raise SystemExit
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: failed to enable realtime scheduling"
+
+    fg.start()                       # start flow graph
+
+    # generate and send packets
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+
+    while n < nbytes:
+        send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
+        n += pkt_size
+        sys.stderr.write('.')
+        if options.discontinuous and pktno % 5 == 4:
+            time.sleep(1)
+        pktno += 1
+        
+    send_pkt(eof=True)
+    fg.wait()                       # wait for it to finish
+    fg.txpath.set_auto_tr(False)
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py b/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py
new file mode 100755
index 0000000000..ad6218b698
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+#
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random
+import struct
+
+# from current dir
+from bpsk import bpsk_demod
+from dbpsk import dbpsk_demod
+from dqpsk import dqpsk_demod
+from receive_path import receive_path
+import fusb_options
+
+if 1:
+    import os
+    print os.getpid()
+    raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, demod_class, rx_subdev_spec,
+                 bitrate, decim_rate, spb,
+                 rx_callback, options, demod_kwargs):
+        gr.flow_graph.__init__(self)
+        self.rxpath = receive_path(self, demod_class, rx_subdev_spec,
+                                   bitrate, decim_rate, spb,
+                                   rx_callback, options, demod_kwargs)
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+global n_rcvd, n_right
+
+def main():
+    global n_rcvd, n_right
+
+    n_rcvd = 0
+    n_right = 0
+    
+    def rx_callback(ok, payload):
+        global n_rcvd, n_right
+        (pktno,) = struct.unpack('!H', payload[0:2])
+        n_rcvd += 1
+        if ok:
+            n_right += 1
+
+        print "ok = %r  pktno = %4d  n_rcvd = %4d  n_right = %4d" % (
+            ok, pktno, n_rcvd, n_right)
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Rx side A or B")
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                      help="set Rx frequency to FREQ [default=%default]",
+                      metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=None,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-S", "--spb", type="int", default=None,
+                      help="set samples/baud [default=%default]")
+    parser.add_option("-d", "--decim", type="intx", default=None,
+                      help="set fpga decim rate to DECIM [default=%default]")
+    parser.add_option("-m", "--modulation", type="string", default='dbpsk',
+                      help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]")
+    parser.add_option("", "--excess-bw", type="float", default=0.3,
+                      help="set RRC excess bandwith factor [default=%default]")
+    parser.add_option("-g", "--gain", type="eng_float", default=27,
+                      help="set rx gain")
+    parser.add_option("","--log", action="store_true", default=False,
+                      help="enable diagnostic logging")
+    fusb_options.add_options(parser)
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    demod_kwargs = {
+            'excess_bw' : options.excess_bw,
+            }
+
+    #FIXME: Needs to be worked in to overall structure; this will be fixed
+    #       once static class definitions for modulations are defined
+    if(options.modulation=='bpsk'):
+        modulation=bpsk_demod
+    elif(options.modulation=='dbpsk'):
+        modulation=dbpsk_demod
+    else:
+        modulation=dqpsk_demod
+
+    # build the graph
+    fg = my_graph(modulation,
+                  options.rx_subdev_spec, options.bitrate,
+                  options.decim, options.spb,
+                  rx_callback, options, demod_kwargs)
+
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),)
+    print "spb:     %3d" % (fg.rxpath.spb(),)
+    print "decim:   %3d" % (fg.rxpath.decim(),)
+
+    ok = fg.rxpath.set_freq(options.freq)
+    if not ok:
+        print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),)
+        raise SystemExit
+    
+    fg.rxpath.set_gain(options.gain)
+    print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: Failed to enable realtime scheduling."
+
+    fg.start()        # start flow graph
+    fg.wait()         # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py b/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
new file mode 100755
index 0000000000..7b37da7fef
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+#
+# Copyright 2005, 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random, time, struct, sys
+
+# from current dir
+from bpsk  import bpsk_mod
+from dbpsk import dbpsk_mod
+from dqpsk import dqpsk_mod
+from transmit_path import transmit_path
+import fusb_options
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, mod_class, tx_subdev_spec,
+                 bitrate, interp_rate, spb, gain,
+                 options, mod_kwargs):
+        gr.flow_graph.__init__(self)
+        self.txpath = transmit_path(self, mod_class, tx_subdev_spec,
+                                    bitrate, interp_rate, spb, gain,
+                                    options, mod_kwargs)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    def send_pkt(payload='', eof=False):
+        return fg.txpath.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        print "ok = %r, payload = '%s'" % (ok, payload)
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Tx side A or B")
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                      help="set Tx and Rx frequency to FREQ [default=%default]",
+                      metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=None,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-S", "--spb", type="int", default=None,
+                      help="set samples/baud [default=%default]")
+    parser.add_option("-i", "--interp", type="intx", default=None,
+                      help="set fpga interpolation rate to INTERP [default=%default]")
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("-m", "--modulation", type="string", default='dbpsk',
+                      help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]")
+    parser.add_option("", "--excess-bw", type="float", default=0.3,
+                      help="set RRC excess bandwith factor [default=%default]")
+    parser.add_option("-g", "--gain", type="eng_float", default=100.0,
+                      help="transmitter gain [default=%default]")
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("","--discontinuous", action="store_true", default=False,
+                      help="enable discontinous transmission (bursts of 5 packets)")
+    fusb_options.add_options(parser)
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    pkt_size = int(options.size)
+
+    mod_kwargs = {
+        'excess_bw' : options.excess_bw,
+        }
+
+    #FIXME: rework when static class defintions are ready for the modulation types
+    if(options.modulation=='bpsk'):
+        modulation=bpsk_mod
+    elif( options.modulation=='dbpsk'):
+        modulation=dbpsk_mod
+    else:
+        modulation=dqpsk_mod
+
+    # build the graph
+    fg = my_graph(modulation,
+                  options.tx_subdev_spec, options.bitrate, options.interp,
+                  options.spb, options.gain,
+                  options, mod_kwargs)
+
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
+    print "spb:     %3d" % (fg.txpath.spb(),)
+    print "interp:  %3d" % (fg.txpath.interp(),)
+
+    ok = fg.txpath.set_freq(options.freq)
+    if not ok:
+        print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),)
+        raise SystemExit
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: failed to enable realtime scheduling"
+
+    fg.start()                       # start flow graph
+
+    # generate and send packets
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+
+    while n < nbytes:
+        send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
+        n += pkt_size
+        sys.stderr.write('.')
+        if options.discontinuous and pktno % 5 == 4:
+            time.sleep(1)
+        pktno += 1
+        
+    send_pkt(eof=True)
+    fg.wait()                       # wait for it to finish
+    fg.txpath.set_auto_tr(False)
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/bpsk.py b/gnuradio-examples/python/gmsk2/bpsk.py
new file mode 100644
index 0000000000..14cea7b102
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/bpsk.py
@@ -0,0 +1,256 @@
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+BPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import cmath
+import Numeric
+from pprint import pprint
+
+_use_gray_code = True
+
+def make_constellation(m):
+    return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
+        
+# Common definition of constellations for Tx and Rx
+constellation = {
+    2 : make_constellation(2),           # BPSK
+    4 : make_constellation(4),           # QPSK
+    8 : make_constellation(8)            # 8PSK
+    }
+
+if 0:
+    print "const(2) ="
+    pprint(constellation[2])
+    print "const(4) ="
+    pprint(constellation[4])
+    print "const(8) ="
+    pprint(constellation[8])
+
+
+if _use_gray_code:
+    # -----------------------
+    # Do Gray code
+    # -----------------------
+    # binary to gray coding
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 7, 6, 4, 5)
+        }
+    
+    # gray to binary
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 6, 7, 5, 4)
+        }
+else:
+    # -----------------------
+    # Don't Gray code
+    # -----------------------
+    # identity mapping
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+    
+    # identity mapping
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#            mPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+
+class bpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb, excess_bw):
+        """
+	Hierarchical block for RRC-filtered BPSK modulation.
+
+	The input is a byte stream (unsigned char) and the
+	output is the complex modulated signal at baseband.
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: integer
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+	"""
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, "sbp must be an integer >= 2"
+        self.spb = spb
+
+	ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+        
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity])
+
+        # pulse shaping filter
+	self.rrc_taps = gr.firdes.root_raised_cosine(
+		spb,		# gain  (spb since we're interpolating by spb)
+		spb,            # sampling rate
+		1.0,		# symbol rate
+		excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+	self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+	# Connect
+        fg.connect(self.bytes2chunks, self.chunks2symbols, self.rrc_filter)
+
+        if 1:
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            
+	# Initialize base class
+	gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static method.  RTFM
+
+
+class bpsk_demod__coherent_detection_of_psk(gr.hier_block):
+    def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05):
+        """
+	Hierarchical block for RRC-filtered BPSK demodulation
+
+	The input is the complex modulated signal at baseband.
+	The output is a stream of bits packed 1 bit per byte (LSB)
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: float
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+	"""
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull it from higher layer?
+        costas_order = 2
+        costas_alpha *= 15   # 2nd order loop needs more gain
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+                   self.slicer, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.preamp, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static method.  RTFM
+
+
+bpsk_demod = bpsk_demod__coherent_detection_of_psk
+
diff --git a/gnuradio-examples/python/gmsk2/dbpsk.py b/gnuradio-examples/python/gmsk2/dbpsk.py
new file mode 100644
index 0000000000..213e90c611
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/dbpsk.py
@@ -0,0 +1,282 @@
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+differential BPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import cmath
+import Numeric
+from pprint import pprint
+
+_use_gray_code = True
+
+def make_constellation(m):
+    return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
+        
+# Common definition of constellations for Tx and Rx
+constellation = {
+    2 : make_constellation(2),           # BPSK
+    4 : make_constellation(4),           # QPSK
+    8 : make_constellation(8)            # 8PSK
+    }
+
+if 0:
+    print "const(2) ="
+    pprint(constellation[2])
+    print "const(4) ="
+    pprint(constellation[4])
+    print "const(8) ="
+    pprint(constellation[8])
+
+
+if _use_gray_code:
+    # -----------------------
+    # Do Gray code
+    # -----------------------
+    # binary to gray coding
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 7, 6, 4, 5)
+        }
+    
+    # gray to binary
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 6, 7, 5, 4)
+        }
+else:
+    # -----------------------
+    # Don't Gray code
+    # -----------------------
+    # identity mapping
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+    
+    # identity mapping
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#            BPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+
+class dbpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb, excess_bw):
+        """
+	Hierarchical block for RRC-filtered QPSK modulation.
+
+	The input is a byte stream (unsigned char) and the
+	output is the complex modulated signal at baseband.
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: integer
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+	"""
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, "sbp must be an integer >= 2"
+        self.spb = spb
+
+	ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        self.bits_per_symbol = bits_per_symbol
+        print "bits_per_symbol =", bits_per_symbol
+        
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        if True:
+            self.gray_coder = gr.map_bb(binary_to_gray[arity])
+        else:
+            self.gray_coder = None
+
+        self.diffenc = gr.diff_encoder_bb(arity)
+        
+        self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity])
+
+        # pulse shaping filter
+	self.rrc_taps = gr.firdes.root_raised_cosine(
+		spb,		# gain  (spb since we're interpolating by spb)
+		spb,            # sampling rate
+		1.0,		# symbol rate
+		excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+	self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+	# Connect
+        if self.gray_coder:
+            fg.connect(self.bytes2chunks, self.gray_coder)
+            t = self.gray_coder
+        else:
+            t = self.bytes2chunks
+
+        fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter)
+        
+        if 1:
+            fg.connect(self.gray_coder,
+                       gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+            fg.connect(self.diffenc,
+                       gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+            
+	# Initialize base class
+	gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static method.  RTFM
+
+
+
+class dbpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05):
+        """
+	Hierarchical block for RRC-filtered BPSK demodulation
+
+	The input is the complex modulated signal at baseband.
+	The output is a stream of bits packed 1 bit per byte (LSB)
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: float
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+	"""
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1, 1000)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull it from higher layer?
+        costas_order = 2
+        costas_alpha *= 15   # 2nd order loop needs more gain
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.diffdec = gr.diff_phasor_cc()
+        #self.diffdec = gr.diff_decoder_bb(arity)
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+                   self.diffdec, self.slicer, self.gray_decoder, self.unpack)
+        #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+        #           self.slicer, self.diffdec, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.diffdec,
+                       gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat"))
+            #fg.connect(self.diffdec,
+            #          gr.file_sink(gr.sizeof_char, "diffdec.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.preamp, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static method.  RTFM
+
+
+dbpsk_demod = dbpsk_demod__coherent_detection_of_differentially_encoded_psk
+
diff --git a/gnuradio-examples/python/gmsk2/dqpsk.py b/gnuradio-examples/python/gmsk2/dqpsk.py
new file mode 100644
index 0000000000..490dc6f739
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/dqpsk.py
@@ -0,0 +1,280 @@
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+differential QPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import cmath
+import Numeric
+from pprint import pprint
+
+_use_gray_code = True
+
+def make_constellation(m):
+    return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
+        
+# Common definition of constellations for Tx and Rx
+constellation = {
+    2 : make_constellation(2),           # BPSK
+    4 : make_constellation(4),           # QPSK
+    8 : make_constellation(8)            # 8PSK
+    }
+
+if 0:
+    print "const(2) ="
+    pprint(constellation[2])
+    print "const(4) ="
+    pprint(constellation[4])
+    print "const(8) ="
+    pprint(constellation[8])
+
+
+if _use_gray_code:
+    # -----------------------
+    # Do Gray code
+    # -----------------------
+    # binary to gray coding
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 7, 6, 4, 5)
+        }
+    
+    # gray to binary
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 6, 7, 5, 4)
+        }
+else:
+    # -----------------------
+    # Don't Gray code
+    # -----------------------
+    # identity mapping
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+    
+    # identity mapping
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#            QPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+
+class dqpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb, excess_bw):
+        """
+	Hierarchical block for RRC-filtered QPSK modulation.
+
+	The input is a byte stream (unsigned char) and the
+	output is the complex modulated signal at baseband.
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: integer
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+	"""
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, "sbp must be an integer >= 2"
+        self.spb = spb
+
+	ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+        
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        if True:
+            self.gray_coder = gr.map_bb(binary_to_gray[arity])
+        else:
+            self.gray_coder = None
+
+        self.diffenc = gr.diff_encoder_bb(arity)
+        
+        self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity])
+
+        # pulse shaping filter
+	self.rrc_taps = gr.firdes.root_raised_cosine(
+		spb,		# gain  (spb since we're interpolating by spb)
+		spb,            # sampling rate
+		1.0,		# symbol rate
+		excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+	self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+	# Connect
+        if self.gray_coder:
+            fg.connect(self.bytes2chunks, self.gray_coder)
+            t = self.gray_coder
+        else:
+            t = self.bytes2chunks
+
+        fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter)
+        
+        if 1:
+            fg.connect(self.gray_coder,
+                       gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+            fg.connect(self.diffenc,
+                       gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+            
+	# Initialize base class
+	gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an instance
+        return 2
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static method.  RTFM
+
+
+
+class dqpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05):
+        """
+	Hierarchical block for RRC-filtered QPSK demodulation
+
+	The input is the complex modulated signal at baseband.
+	The output is a stream of bits packed 1 bit per byte (LSB)
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: float
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+	"""
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull it from higher layer?
+        costas_order = 4
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.diffdec = gr.diff_phasor_cc()
+        #self.diffdec = gr.diff_decoder_bb(arity)
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+                   self.diffdec, self.slicer, self.gray_decoder, self.unpack)
+        #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+        #           self.slicer, self.diffdec, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.diffdec,
+                       gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat"))
+            #fg.connect(self.diffdec,
+            #          gr.file_sink(gr.sizeof_char, "diffdec.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.preamp, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an instance
+        return 2
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static method.  RTFM
+
+
+dqpsk_demod = dqpsk_demod__coherent_detection_of_differentially_encoded_psk
+
diff --git a/gnuradio-examples/python/gmsk2/fusb_options.py b/gnuradio-examples/python/gmsk2/fusb_options.py
new file mode 100644
index 0000000000..0d04e30c77
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/fusb_options.py
@@ -0,0 +1,31 @@
+#
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+def add_options(parser):
+    """
+    Add Fast USB specifc options to command line parser.
+    
+    @param parser: instance of OptionParser
+    """
+    parser.add_option("-B", "--fusb-block-size", type="int", default=0,
+                      help="specify fast usb block size [default=%default]")
+    parser.add_option("-N", "--fusb-nblocks", type="int", default=0,
+                      help="specify number of fast usb blocks [default=%default]")
diff --git a/gnuradio-examples/python/gmsk2/gen_whitener.py b/gnuradio-examples/python/gmsk2/gen_whitener.py
new file mode 100755
index 0000000000..93aea2b821
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/gen_whitener.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser(option_class=eng_option)
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        src = gr.lfsr_32k_source_s()
+        head = gr.head(gr.sizeof_short, 2048)
+        self.dst = gr.vector_sink_s()
+        self.connect(src, head, self.dst)
+
+if __name__ == '__main__':
+    try:
+        fg = my_graph()
+        fg.run()
+        f = sys.stdout
+        i = 0
+        for s in fg.dst.data():
+            f.write("%3d, " % (s & 0xff,))
+            f.write("%3d, " % ((s >> 8) & 0xff,))
+            i = i+2
+            if i % 16 == 0:
+                f.write('\n')
+                    
+    except KeyboardInterrupt:
+        pass
+    
+    
diff --git a/gnuradio-examples/python/gmsk2/gmsk_test.py b/gnuradio-examples/python/gmsk2/gmsk_test.py
new file mode 100755
index 0000000000..7ae69a0a94
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/gmsk_test.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import random
+import struct
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, rx_callback, spb, bt, SNR, freq_error):
+        gr.flow_graph.__init__(self)
+
+        fg = self
+
+        # Tuning Parameters
+        gain_mu = 0.002*spb
+        omega = spb*(1+freq_error)
+
+        # transmitter
+        self.packet_transmitter = blks.gmsk2_mod_pkts(fg, spb=spb, bt=bt)
+
+        # add some noise
+        add = gr.add_cc()
+        noise = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0))
+
+        # channel filter
+        rx_filt_taps = gr.firdes.low_pass(1,spb,0.8,0.1,gr.firdes.WIN_HANN)
+        rx_filt = gr.fir_filter_ccf(1,rx_filt_taps)
+
+        # receiver
+        self.packet_receiver = blks.gmsk2_demod_pkts(fg, callback=rx_callback,
+                                                     spb=spb, gain_mu=gain_mu,
+                                                     freq_error=freq_error, omega=omega)
+
+        fg.connect (self.packet_transmitter, (add,0))
+        fg.connect (noise, (add,1))
+        fg.connect(add, rx_filt, self.packet_receiver)
+
+
+class stats(object):
+    def __init__(self):
+        self.npkts = 0
+        self.nright = 0
+        
+def main():
+    st = stats()
+    
+    def send_pkt(payload='', eof=False):
+        fg.packet_transmitter.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        st.npkts += 1
+        if ok:
+            st.nright += 1
+        if len(payload) <= 16:
+            print "ok = %5r  payload = '%s'  %d/%d" % (ok, payload, st.nright, st.npkts)
+        else:
+            (pktno,) = struct.unpack('!H', payload[0:2])
+            print "ok = %5r  pktno = %4d  len(payload) = %4d  %d/%d" % (ok, pktno, len(payload),
+                                                                        st.nright, st.npkts)
+
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("","--spb", type=int, default=4,
+                      help="set samples per baud to SPB [default=%default]")
+    parser.add_option("", "--bt", type="eng_float", default=0.3,
+                      help="set bandwidth time product for Gaussian filter [default=%default]")
+    parser.add_option("", "--snr", type="eng_float", default=20,
+                      help="set SNR in dB for simulation [default=%default]")
+    parser.add_option("", "--freq-error", type="eng_float", default=0,
+                      help="set frequency error for simulation [default=%default]")
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    pkt_size = int(options.size)
+
+    fg = my_graph(rx_callback, options.spb, options.bt, options.snr, options.freq_error)
+    fg.start()
+
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+
+    send_pkt('Hello World')
+
+    # generate and send packets
+    while n < nbytes:
+        send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
+        n += pkt_size
+        pktno += 1
+
+    send_pkt('Goodbye World')
+    send_pkt(eof=True)             # tell modulator we're not sending any more pkts
+
+    fg.wait()
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/mpsk_test.py b/gnuradio-examples/python/gmsk2/mpsk_test.py
new file mode 100755
index 0000000000..1f257d9c5d
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/mpsk_test.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import random
+import struct
+from mpsk_pkt import *
+import cmath
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, rx_callback, spb, excess_bw, SNR, freq_error, arity):
+        gr.flow_graph.__init__(self)
+
+        fg = self
+
+        # Tuning Parameters
+        gain_mu = 0.05/spb
+
+        # transmitter
+        self.packet_transmitter = \
+          mpsk_mod_pkts(fg, spb=spb, excess_bw=excess_bw, diff=True, arity=arity)
+
+        # ----------------------------------------------------------------
+        #                       Channel model
+        # ----------------------------------------------------------------
+
+        awgn = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0))
+        add = gr.add_cc()            # add some noise
+        fg.connect(awgn, (add,1))
+        radians = 17*pi/180
+        phase_rotate = gr.multiply_const_cc(cmath.exp(radians * 1j))
+
+        # ----------------------------------------------------------------
+
+        # channel filter
+        rx_filt_taps = gr.firdes.low_pass(1,spb,0.8,0.1,gr.firdes.WIN_HANN)
+        #rx_filt_taps = (1,)
+        rx_filt = gr.fir_filter_ccf(1,rx_filt_taps)
+
+        # receiver
+        self.packet_receiver = \
+            mpsk_demod_pkts(fg, callback=rx_callback,
+                            excess_bw=excess_bw, arity=arity, diff=True,
+                            costas_alpha=.005, gain_mu=gain_mu, spb=spb)
+        
+        fg.connect (self.packet_transmitter, (add,0))
+        fg.connect(add, phase_rotate, rx_filt, self.packet_receiver)
+
+
+class stats(object):
+    def __init__(self):
+        self.npkts = 0
+        self.nright = 0
+        
+def main():
+    st = stats()
+    
+    def send_pkt(payload='', eof=False):
+        fg.packet_transmitter.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        st.npkts += 1
+        if ok:
+            st.nright += 1
+        if len(payload) <= 16:
+            print "ok = %5r  payload = '%s'  %d/%d" % (ok, payload, st.nright, st.npkts)
+        else:
+            (pktno,) = struct.unpack('!H', payload[0:2])
+            print "ok = %5r  pktno = %4d  len(payload) = %4d  %d/%d" % (ok, pktno, len(payload),
+                                                                        st.nright, st.npkts)
+
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("","--spb", type=int, default=4,
+                      help="set samples per baud to SPB [default=%default]")
+    parser.add_option("", "--excess-bw", type="eng_float", default=0.4,
+                      help="set excess bandwidth for RRC filter [default=%default]")
+    parser.add_option("", "--snr", type="eng_float", default=40,
+                      help="set SNR in dB for simulation [default=%default]")
+    parser.add_option("", "--m-arity", type=int, default=4,
+                      help="PSK arity [default=%default]")
+    parser.add_option("", "--freq-error", type="eng_float", default=0,
+                      help="set frequency error for simulation [default=%default]")
+
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    pkt_size = int(options.size)
+
+    fg = my_graph(rx_callback, options.spb, options.excess_bw, options.snr,
+                  options.freq_error, options.m_arity)
+    fg.start()
+
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+
+    send_pkt('Hello World')
+
+    # generate and send packets
+    while n < nbytes:
+        send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
+        n += pkt_size
+        pktno += 1
+
+    send_pkt('Goodbye World')
+    send_pkt(eof=True)             # tell modulator we're not sending any more pkts
+
+    fg.wait()
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/pick_bitrate.py b/gnuradio-examples/python/gmsk2/pick_bitrate.py
new file mode 100644
index 0000000000..b35991caf3
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/pick_bitrate.py
@@ -0,0 +1,143 @@
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+_default_bitrate = 500e3
+
+_valid_spbs = (2,3,4,5,6,7)
+
+def _gen_tx_info(converter_rate):
+    results = []
+    for spb in _valid_spbs:
+        for interp in range(16, 512 + 1, 4):
+            bitrate = converter_rate / interp / spb
+            results.append((bitrate, spb, interp))
+    results.sort()
+    return results
+
+def _gen_rx_info(converter_rate):
+    results = []
+    for spb in _valid_spbs:
+        for decim in range(8, 256 + 1, 2):
+            bitrate = converter_rate / decim / spb
+            results.append((bitrate, spb, decim))
+    results.sort()
+    return results
+    
+def _filter_info(info, samples_per_baud, xrate):
+    if samples_per_baud is not None:
+        info = [x for x in info if x[1] == samples_per_baud]
+    if xrate is not None:
+        info = [x for x in info if x[2] == xrate]
+    return info
+
+def _pick_best(target_bitrate, bits_per_symbol, info):
+    """
+    @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate)
+    """
+    if len(info) == 0:
+        raise RuntimeError, "info is zero length!"
+
+    if target_bitrate is None:     # return the fastest one
+        return info[-1]
+    
+    # convert bit rate to symbol rate
+    target_symbolrate = target_bitrate / bits_per_symbol
+    
+    # Find the closest matching symbol rate.
+    # In the event of a tie, the one with the lowest samples_per_baud wins.
+    # (We already sorted them, so the first one is the one we take)
+
+    best = info[0]
+    best_delta = abs(target_symbolrate - best[0])
+    for x in info[1:]:
+        delta = abs(target_symbolrate - x[0])
+        if delta < best_delta:
+            best_delta = delta
+            best = x
+
+    # convert symbol rate back to bit rate
+    return ((best[0] * bits_per_symbol),) + best[1:]
+
+def _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud,
+                  xrate, converter_rate, gen_info):
+    """
+    @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate)
+    """
+    if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1:
+        raise ValueError, "bits_per_symbol must be an int >= 1"
+    
+    if samples_per_baud is not None and xrate is not None:  # completely determined
+        return (float(converter_rate) / xrate / samples_per_baud,
+                samples_per_baud, xrate)
+
+    if bitrate is None and samples_per_baud is None and xrate is None:
+        bitrate = _default_bitrate
+
+    # now we have a target bitrate and possibly an xrate or
+    # samples_per_baud constraint, but not both of them.
+
+    return _pick_best(bitrate, bits_per_symbol,
+                      _filter_info(gen_info(converter_rate), samples_per_baud, xrate))
+    
+# ---------------------------------------------------------------------------------------
+
+def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_baud,
+                    interp_rate, converter_rate=128e6):
+    """
+    Given the 4 input parameters, return at configuration that matches
+
+    @param bitrate: desired bitrate or None
+    @type bitrate: number or None
+    @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3
+    @type bits_per_symbol: integer >= 1
+    @param samples_per_baud: samples/baud (aka samples/symbol)
+    @type samples_per_baud: number or None
+    @param interp_rate: USRP interpolation factor
+    @type interp_rate: integer or None
+    @param converter_rate: converter sample rate in Hz
+    @type converter_rate: number
+
+    @returns tuple (bitrate, samples_per_baud, interp_rate)
+    """
+    return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud,
+                         interp_rate, converter_rate, _gen_tx_info)
+
+
+def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_baud,
+                    decim_rate, converter_rate=64e6):
+    """
+    Given the 4 input parameters, return at configuration that matches
+
+    @param bitrate: desired bitrate or None
+    @type bitrate: number or None
+    @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3
+    @type bits_per_symbol: integer >= 1
+    @param samples_per_baud: samples/baud (aka samples/symbol)
+    @type samples_per_baud: number or None
+    @param decim_rate: USRP decimation factor
+    @type decim_rate: integer or None
+    @param converter_rate: converter sample rate in Hz
+    @type converter_rate: number
+
+    @returns tuple (bitrate, samples_per_baud, decim_rate)
+    """
+    return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud,
+                         decim_rate, converter_rate, _gen_rx_info)
diff --git a/gnuradio-examples/python/gmsk2/qpsk.py b/gnuradio-examples/python/gmsk2/qpsk.py
new file mode 100644
index 0000000000..6ca7f0e61a
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/qpsk.py
@@ -0,0 +1,418 @@
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+PSK and differential PSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import cmath
+import Numeric
+from pprint import pprint
+
+_use_gray_code = True
+
+def make_constellation(m):
+    return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
+        
+# Common definition of constellations for Tx and Rx
+constellation = {
+    2 : make_constellation(2),           # BPSK
+    4 : make_constellation(4),           # QPSK
+    8 : make_constellation(8)            # 8PSK
+    }
+
+if 0:
+    print "const(2) ="
+    pprint(constellation[2])
+    print "const(4) ="
+    pprint(constellation[4])
+    print "const(8) ="
+    pprint(constellation[8])
+
+
+if _use_gray_code:
+    # -----------------------
+    # Do Gray code
+    # -----------------------
+    # binary to gray coding
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 7, 6, 4, 5)
+        }
+    
+    # gray to binary
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 3, 2),
+        8 : (0, 1, 3, 2, 6, 7, 5, 4)
+        }
+else:
+    # -----------------------
+    # Don't Gray code
+    # -----------------------
+    # identity mapping
+    binary_to_gray = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+    
+    # identity mapping
+    gray_to_binary = {
+        2 : (0, 1),
+        4 : (0, 1, 2, 3),
+        8 : (0, 1, 2, 3, 4, 5, 6, 7)
+        }
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#            mPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+
+class mpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb, arity, excess_bw, diff=False):
+        """
+	Hierarchical block for RRC-filtered PSK modulation.
+
+	The input is a byte stream (unsigned char) and the
+	output is the complex modulated signal at baseband.
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: integer
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+        @param arity: whick PSK: 2, 4, 8
+        @type arity: int in {2, 4, 8}
+        @param diff: differential PSK if true
+        @type diff: bool
+	"""
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, "sbp must be an integer >= 2"
+        self.spb = spb
+
+        if not arity in (2, 4):
+            raise ValueError, "n must be 2, 4, or 8"
+
+	ntaps = 11 * spb
+
+        bits_per_symbol = int(gru.log2(arity))
+        self.bits_per_symbol = bits_per_symbol
+        print "bits_per_symbol =", bits_per_symbol
+        
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        if True or arity > 2:
+            self.gray_coder = gr.map_bb(binary_to_gray[arity])
+        else:
+            self.gray_coder = None
+
+        if diff:
+            self.diffenc = gr.diff_encoder_bb(arity)
+        else:
+            self.diffenc = None
+
+        self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity])
+
+        # pulse shaping filter
+	self.rrc_taps = gr.firdes.root_raised_cosine(
+		spb,		# gain  (spb since we're interpolating by spb)
+		spb,            # sampling rate
+		1.0,		# symbol rate
+		excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+	self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+	# Connect
+        if self.gray_coder:
+            fg.connect(self.bytes2chunks, self.gray_coder)
+            t = self.gray_coder
+        else:
+            t = self.bytes2chunks
+
+        if diff:
+            fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter)
+        else:
+            fg.connect(t, self.chunks2symbols, self.rrc_filter)
+
+        if 1:
+            fg.connect(self.gray_coder,
+                       gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+            if diff:
+                fg.connect(self.diffenc,
+                           gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+            
+	# Initialize base class
+	gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self):
+        return self.bits_per_symbol
+
+
+class mpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05):
+        """
+	Hierarchical block for RRC-filtered PSK demodulation
+
+	The input is the complex modulated signal at baseband.
+	The output is a stream of bits packed 1 bit per byte (LSB)
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: float
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+        @param arity: whick PSK: 2, 4, 8
+        @type arity: int in {2, 4, 8}
+        @param diff: differential PSK if true
+        @type diff: bool
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+	"""
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        if not arity in (2, 4):
+            raise ValueError, "n must be 2 or 4"
+
+        if not diff and arity==4:
+            raise NotImplementedError, "non-differential QPSK not supported yet"
+
+        bits_per_symbol = int(gru.log2(arity))
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull it from higher layer?
+        if arity == 2:
+            costas_order = 2
+            costas_alpha *= 15   # 2nd order loop needs more gain
+        else:
+            costas_order = 4
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        if(diff):
+            self.diffdec = gr.diff_phasor_cc()
+            #self.diffdec = gr.diff_decoder_bb(arity)
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        if(diff):
+            fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+                       self.diffdec, self.slicer, self.gray_decoder, self.unpack)
+        else:
+            fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+                       self.slicer, self.gray_decoder, self.unpack)
+
+        #fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+        #           self.slicer, self.diffdec, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            if(diff):
+                fg.connect(self.diffdec,
+                           gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat"))
+                #fg.connect(self.diffdec,
+                #          gr.file_sink(gr.sizeof_char, "diffdec.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.agc, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self):
+        return self.bits_per_symbol
+
+
+#########################################################################
+
+class mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05):
+        """
+	Hierarchical block for RRC-filtered PSK demodulation
+
+	The input is the complex modulated signal at baseband.
+	The output is a stream of bits packed 1 bit per byte (LSB)
+
+	@param fg: flow graph
+	@type fg: flow graph
+	@param spb: samples per baud >= 2
+	@type spb: float
+	@param excess_bw: Root-raised cosine filter excess bandwidth
+	@type excess_bw: float
+        @param arity: whick PSK: 2, 4, 8
+        @type arity: int in {2, 4, 8}
+        @param diff: differential PSK if true
+        @type diff: bool
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+	"""
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        if not arity in (2, 4):
+            raise ValueError, "n must be 2 or 4"
+
+        bits_per_symbol = int(gru.log2(arity))
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull it from higher layer?
+        if arity == 2:
+            costas_order = 2
+            costas_alpha *= 15   # 2nd order loop needs more gain
+        else:
+            costas_order = 4
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery,
+                   self.slicer, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.agc, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self):
+        return self.bits_per_symbol
+
+
+mpsk_demod = mpsk_demod__coherent_detection_of_differentially_encoded_psk
+#mpsk_demod = mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk
diff --git a/gnuradio-examples/python/gmsk2/qpsk_tester.py b/gnuradio-examples/python/gmsk2/qpsk_tester.py
new file mode 100644
index 0000000000..ea7bae2ebc
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/qpsk_tester.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+import random
+from gnuradio import gr
+
+default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC'
+
+def string_to_1_0_list(s):
+    r = []
+    for ch in s:
+        x = ord(ch)
+        for i in range(8):
+            t = (x >> i) & 0x1
+            r.append(t)
+
+    return r
+
+def to_1_0_string(L):
+    return ''.join(map(lambda x: chr(x + ord('0')), L))
+
+code = string_to_1_0_list(default_access_code)
+access_code = to_1_0_string(code)
+
+use_agc        = 0
+use_rrc_tx     = 1
+use_rrc_rx     = 1
+use_sync_loop  = 1
+use_clock_sync = 1
+
+def main():
+    fg = gr.flow_graph()
+
+#    data = (1,2,3,4,5,6,7,8,9)
+    random.seed()
+    data = [random.randint(1,100) for i in range(20000)]
+    data[0] = 0 # you know, for the diff encoding stuff
+    bytes_src = gr.vector_source_b(data,False)
+
+    k = 2
+    spb = 50
+    ntaps = 11*spb
+    excess_bw = 0.9
+    threshold = 12
+    constellation  = (1+0j, 0+1j, -1+0j, 0-1j)
+    
+    bytes2chunks   = gr.packed_to_unpacked_bb(k, gr.GR_MSB_FIRST)
+    diffenc        = gr.diff_encoder_bb(4)
+    chunks2symbols = gr.chunks_to_symbols_bc(constellation)
+
+    if use_rrc_tx:
+        rrc_taps_tx = gr.firdes.root_raised_cosine(spb, spb, 1.0, \
+                                                   excess_bw, ntaps)
+        rrc_tx = gr.interp_fir_filter_ccf(spb, rrc_taps_tx)
+    else:
+        rrc_tx = gr.interp_fir_filter_ccf(1, (1,))
+
+################### CHANNEL MODEL #############################
+
+    phase_rotate = gr.multiply_const_cc(1-0.36j)
+    channel      = gr.add_cc()
+    awgn         = gr.noise_source_c(gr.GR_GAUSSIAN, 0.5)
+    fg.connect(awgn, (channel,1))
+    
+################### CHANNEL MODEL #############################
+
+    if use_agc:
+        agc = gr.agc_cc(1e-4, 1, 1)
+    else:
+        agc = gr.multiply_const_cc(1)
+
+    # Downconverter
+    if use_sync_loop:
+        costas_alpha=0.005
+        beta = costas_alpha*costas_alpha*0.25
+        sync_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 0)
+    else:
+        sync_loop = gr.multiply_const_cc(1)
+
+    if use_rrc_rx:
+        rrc_taps_rx = gr.firdes.root_raised_cosine(1, spb, 1.0, \
+                                                   excess_bw, ntaps)
+        rrc_rx = gr.fir_filter_ccf(1, rrc_taps_rx)
+    else:
+        rrc_rx = gr.fir_filter_ccf(1, (1,))
+   
+    # Sampler
+    if use_clock_sync:
+        mu = 0.05
+        omega = spb
+        gain_mu = 0.05
+        gain_omega = 0.25*gain_mu*gain_mu
+        omega_rel_limit = 0.5
+        clock_sync = gr.clock_recovery_mm_cc(omega, gain_omega, mu, \
+                                             gain_mu, omega_rel_limit)
+        #clock_sync.set_verbose(True);
+    else:
+        clock_sync = gr.fir_filter_ccf(1, (1,))
+
+    diff_phasor = gr.diff_phasor_cc()
+    slicer = gr.constellation_decoder_cb((constellation), (0,1,2,3))
+    unpack = gr.unpack_k_bits_bb(k)
+    access = gr.correlate_access_code_bb(access_code,threshold)
+
+    sink = gr.file_sink(gr.sizeof_char, 'output.dat')
+
+    fg.connect(bytes_src, bytes2chunks, diffenc, chunks2symbols, rrc_tx)
+    fg.connect(rrc_tx, phase_rotate, channel, agc)
+    fg.connect(agc, sync_loop, rrc_rx, clock_sync, diff_phasor, slicer, sink)
+ 
+    test = gr.file_sink(gr.sizeof_gr_complex, 'test.dat')
+    fg.connect(rrc_rx, test)
+
+    fg.connect(chunks2symbols, gr.file_sink(gr.sizeof_gr_complex, 'rrc_tx.dat'))  # into TX RRC
+    fg.connect(channel, gr.file_sink(gr.sizeof_gr_complex, 'channel.dat'))        # Out of TX RRC
+    fg.connect(rrc_rx, gr.file_sink(gr.sizeof_gr_complex, 'rrc_rx.dat'))          # Out of RX RRC -> clock_sync
+    fg.connect(clock_sync, gr.file_sink(gr.sizeof_gr_complex, 'clock_sync.dat'))  # Out of M&M sync loop
+    fg.connect(bytes2chunks, gr.file_sink(gr.sizeof_char, 'source.dat'))
+
+    fg.start()
+    fg.wait()
+
+if __name__ == "__main__":
+    main()
+        
+    
+
+ 
diff --git a/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py b/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py
new file mode 100644
index 0000000000..bf7698a2b2
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+
+import random
+from gnuradio import gr, gru, usrp
+
+default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC'
+
+def string_to_1_0_list(s):
+    r = []
+    for ch in s:
+        x = ord(ch)
+        for i in range(8):
+            t = (x >> i) & 0x1
+            r.append(t)
+
+    return r
+
+def to_1_0_string(L):
+    return ''.join(map(lambda x: chr(x + ord('0')), L))
+
+code = string_to_1_0_list(default_access_code)
+
+access_code = to_1_0_string(code)
+
+def main():
+
+    fg = gr.flow_graph()
+    f_rf = 5e6
+    fs = 400e3
+    sr = 100e3
+    alpha = 0.5
+    M = 4
+    k = int(gru.log2(M))
+    
+    # Source
+    src = usrp.source_c ()
+    adc_rate = src.adc_rate()
+    usrp_decim = int(adc_rate / fs)
+    src.set_decim_rate(usrp_decim)
+        
+    subdev_spec = usrp.pick_rx_subdevice(src)
+    subdev = usrp.selected_subdev(src, subdev_spec)
+    print "Using RX d'board %s" % (subdev.side_and_name(),)
+    src.set_mux(usrp.determine_rx_mux_value(src, subdev_spec))
+    src.tune(0, subdev, f_rf)
+        
+    g = subdev.gain_range()
+    subdev.set_gain(g[1])
+    subdev.set_auto_tr(True)
+        
+    print "USRP Decimation Rate = %d" % usrp_decim
+    print "RF Frequency = %d" % f_rf
+
+    agc = gr.multiply_const_cc(0.0025)
+        
+    # Downconverter
+    costas_alpha=0.005
+    beta = costas_alpha*costas_alpha*0.25
+    sync_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 0)
+
+    # Stage 2
+#    fs2 = 200e3
+#    D = int(fs / fs2)
+#    decimator = gr.keep_one_in_n(gr.sizeof_gr_complex, D)
+#    print "D = %d\nAfter decimator fs = %f" % (D, fs2)
+
+    # Demodulator
+    taps = gr.firdes.root_raised_cosine(1, fs, sr, alpha, 45)
+    rrc  = gr.fir_filter_ccf(1, taps)
+    
+    # Sampler
+    mu = 0.01
+    omega = 4.3
+    gain_mu = 0.05
+    gain_omega = 0.25*gain_mu*gain_mu
+    omega_rel_limit = 0.5
+    clock_sync = gr.clock_recovery_mm_cc(omega, gain_omega, mu,
+                                         gain_mu, omega_rel_limit)
+    clock_sync.set_verbose(False)
+
+    diff_phasor = gr.diff_phasor_cc()
+
+    threshold = 12
+    constellation = (1+0j, 0+1j, -1+0j, 0-1j)
+    slicer = gr.constellation_decoder_cb((constellation), (0,1,2,3))
+    unpack = gr.unpack_k_bits_bb(k)
+    access = gr.correlate_access_code_bb(access_code,threshold)
+
+    test = gr.file_sink(gr.sizeof_gr_complex, 'test.dat')
+    sink = gr.file_sink(gr.sizeof_char, 'output.dat')
+
+    fg.connect(src, agc, sync_loop, rrc, clock_sync)
+    fg.connect(clock_sync, diff_phasor, slicer, unpack, access, sink)
+
+    fg.connect(slicer, gr.file_sink(gr.sizeof_char, 'chunks.dat'))
+    fg.connect(unpack, gr.file_sink(gr.sizeof_char, 'unpack.dat'))
+    fg.connect(clock_sync, gr.file_sink(gr.sizeof_gr_complex, 'phasor.dat'))
+
+    fg.start()
+    fg.wait()
+
+if __name__ == "__main__":
+    main()
diff --git a/gnuradio-examples/python/gmsk2/receive_path.py b/gnuradio-examples/python/gmsk2/receive_path.py
new file mode 100644
index 0000000000..505ff7c4d3
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/receive_path.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+
+# from current dir
+from pick_bitrate import pick_rx_bitrate
+
+# /////////////////////////////////////////////////////////////////////////////
+#                              receive path
+# /////////////////////////////////////////////////////////////////////////////
+
+class receive_path(gr.hier_block):
+    def __init__(self, fg, demod_class, rx_subdev_spec,
+                 bitrate, decim, spb,
+                 rx_callback, options, demod_kwargs):
+
+        self.u = usrp.source_c (fusb_block_size=options.fusb_block_size,
+                                fusb_nblocks=options.fusb_nblocks)
+        adc_rate = self.u.adc_rate()
+
+        (self._bitrate, self._spb, self._decim) = \
+            pick_rx_bitrate(bitrate, demod_class.bits_per_baud(), spb, decim, adc_rate)
+
+        self.u.set_decim_rate(self._decim)
+        sw_decim = 1
+
+        if rx_subdev_spec is None:
+            rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
+        self.subdev = usrp.selected_subdev(self.u, rx_subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, rx_subdev_spec))
+
+        # Create filter to get actual channel we want
+        chan_coeffs = gr.firdes.low_pass (1.0,                  # gain
+                                          sw_decim * self._spb, # sampling rate
+                                          1.0,                  # midpoint of trans. band
+                                          0.1,                  # width of trans. band
+                                          gr.firdes.WIN_HANN)   # filter type 
+
+        print "len(rx_chan_coeffs) =", len(chan_coeffs)
+
+        # Decimating Channel filter
+        # complex in and out, float taps
+        self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs)
+        #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs)
+
+        # receiver
+        self.packet_receiver = \
+            blks.demod_pkts(fg,
+                            demod_class(fg, spb=self._spb, **demod_kwargs),
+                            access_code=None,
+                            callback=rx_callback,
+                            threshold=-1)
+
+        fg.connect(self.u, self.chan_filt, self.packet_receiver)
+        gr.hier_block.__init__(self, fg, None, None)
+
+        g = self.subdev.gain_range()
+        #self.set_gain((g[0] + g[1])/2)        # set gain to midpoint
+        self.set_gain(g[1])                    # set gain to max
+        self.set_auto_tr(True)                 # enable Auto Transmit/Receive switching
+
+        # Carrier Sensing Blocks
+        alpha = 0.001
+        thresh = 30   # in dB, will have to adjust
+        self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)
+        fg.connect(self.chan_filt, self.probe)
+
+    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(0, self.subdev, target_freq)
+        if r:
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        if gain is None:
+            r = self.subdev.gain_range()
+            gain = (r[0] + r[1])/2               # set gain to midpoint
+        self.gain = gain
+        return self.subdev.set_gain(gain)
+
+    def set_auto_tr(self, enable):
+        return self.subdev.set_auto_tr(enable)
+        
+    def bitrate(self):
+        return self._bitrate
+
+    def spb(self):
+        return self._spb
+
+    def decim(self):
+        return self._decim
+
+
+    def carrier_sensed(self):
+        """
+        Return True if we think carrier is present.
+        """
+        #return self.probe.level() > X
+        return self.probe.unmuted()
+
+    def carrier_threshold(self):
+        """
+        Return current setting in dB.
+        """
+        return self.probe.threshold()
+
+    def set_carrier_threshold(self, threshold_in_db):
+        """
+        Set carrier threshold.
+
+        @param threshold_in_db: set detection threshold
+        @type threshold_in_db:  float (dB)
+        """
+        self.probe.set_threshold(threshold_in_db)
+    
diff --git a/gnuradio-examples/python/gmsk2/rx_voice.py b/gnuradio-examples/python/gmsk2/rx_voice.py
new file mode 100755
index 0000000000..3f5cc3b476
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/rx_voice.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+from gnuradio.vocoder import gsm_full_rate
+
+import random
+import struct
+
+# from current dir
+from receive_path import receive_path
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class audio_tx(gr.hier_block):
+    def __init__(self, fg):
+        self.packet_src = gr.message_source(33)
+        voice_decoder = gsm_full_rate.decode_ps()
+        s2f = gr.short_to_float ()
+        sink_scale = gr.multiply_const_ff(1.0/32767.)
+        audio_sink = audio.sink(8000)
+        fg.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink)
+        gr.hier_block.__init__(self, fg, self.packet_src, audio_sink)
+        
+    def msgq(self):
+        return self.packet_src.msgq()
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, rx_subdev_spec, bitrate, decim_rate, spb, rx_callback, log):
+        gr.flow_graph.__init__(self)
+        self.rxpath = receive_path(self, rx_subdev_spec, bitrate, decim_rate,
+                                   spb, rx_callback, log)
+
+        self.audio_tx = audio_tx(self)
+        
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+global n_rcvd, n_right
+
+def main():
+    global n_rcvd, n_right
+
+    n_rcvd = 0
+    n_right = 0
+    
+    def rx_callback(ok, payload):
+        global n_rcvd, n_right
+        n_rcvd += 1
+        if ok:
+            n_right += 1
+
+        fg.audio_tx.msgq().insert_tail(gr.message_from_string(payload))
+        
+        print "ok = %r  n_rcvd = %4d  n_right = %4d" % (
+            ok, n_rcvd, n_right)
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Rx side A or B")
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                       help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=100e3,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]")
+    parser.add_option("-d", "--decim", type="intx", default=None,
+                      help="set fpga decim rate to DECIM [default=%default]")
+    parser.add_option("-g", "--gain", type="eng_float", default=27,
+                      help="set rx gain")
+    parser.add_option("","--log", action="store_true", default=False,
+                      help="enable diagnostic logging")
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    # build the graph
+    fg = my_graph(options.rx_subdev_spec, options.bitrate,
+                  options.decim, options.spb, rx_callback, options.log)
+
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),)
+    print "spb:     %3d" % (fg.rxpath.spb(),)
+    print "decim:   %3d" % (fg.rxpath.decim(),)
+
+    fg.rxpath.set_freq(options.freq)
+    fg.rxpath.set_gain(options.gain)
+    print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain
+
+    fg.start()        # start flow graph
+    fg.wait()         # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/transmit_path.py b/gnuradio-examples/python/gmsk2/transmit_path.py
new file mode 100644
index 0000000000..a1df1579fa
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/transmit_path.py
@@ -0,0 +1,108 @@
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+
+# from current dir
+from pick_bitrate import pick_tx_bitrate
+
+# /////////////////////////////////////////////////////////////////////////////
+#                              transmit path
+# /////////////////////////////////////////////////////////////////////////////
+
+class transmit_path(gr.hier_block): 
+    def __init__(self, fg, mod_class, tx_subdev_spec,
+                 bitrate, interp, spb, gain,
+                 options, mod_kwargs):
+
+        self.normal_gain = gain
+
+        self.u = usrp.sink_c (fusb_block_size=options.fusb_block_size,
+                              fusb_nblocks=options.fusb_nblocks)
+        dac_rate = self.u.dac_rate();
+
+        print mod_class
+        print mod_class.bits_per_baud()
+        (self._bitrate, self._spb, self._interp) = \
+            pick_tx_bitrate(bitrate, mod_class.bits_per_baud(), spb, interp, dac_rate)
+
+        self.u.set_interp_rate(self._interp)
+
+        # determine the daughterboard subdevice we're using
+        if tx_subdev_spec is None:
+            tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
+        self.u.set_mux(usrp.determine_tx_mux_value(self.u, tx_subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, tx_subdev_spec)
+        print "Using TX d'board %s" % (self.subdev.side_and_name(),)
+
+        # transmitter
+        self.packet_transmitter = \
+            blks.mod_pkts(fg,
+                          mod_class(fg, spb=self._spb, **mod_kwargs),
+                          access_code=None,
+                          msgq_limit=4,
+                          pad_for_usrp=True)
+
+        self.amp = gr.multiply_const_cc (self.normal_gain)
+
+        fg.connect(self.packet_transmitter, self.amp, self.u)
+        gr.hier_block.__init__(self, fg, None, None)
+
+        self.set_gain(self.subdev.gain_range()[1])  # set max Tx gain
+        self.set_auto_tr(True)                      # enable Auto Transmit/Receive switching
+
+    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:
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.gain = gain
+        self.subdev.set_gain(gain)
+
+    def set_auto_tr(self, enable):
+        return self.subdev.set_auto_tr(enable)
+        
+    def send_pkt(self, payload='', eof=False):
+        return self.packet_transmitter.send_pkt(payload, eof)
+        
+    def bitrate(self):
+        return self._bitrate
+
+    def spb(self):
+        return self._spb
+
+    def interp(self):
+        return self._interp
diff --git a/gnuradio-examples/python/gmsk2/tunnel.py b/gnuradio-examples/python/gmsk2/tunnel.py
new file mode 100755
index 0000000000..bc10d3e34f
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/tunnel.py
@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#
+#    This code sets up up a virtual ethernet interface (typically gr0),
+#    and relays packets between the interface and the GNU Radio PHY+MAC
+#
+#    What this means in plain language, is that if you've got a couple
+#    of USRPs on different machines, and if you run this code on those
+#    machines, you can talk between them using normal TCP/IP networking.
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random
+import time
+import struct
+import sys
+import os
+
+# from current dir
+from transmit_path import transmit_path
+from receive_path import receive_path
+import fusb_options
+
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#
+#   Use the Universal TUN/TAP device driver to move packets to/from kernel
+#
+#   See /usr/src/linux/Documentation/networking/tuntap.txt
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+# Linux specific...
+# TUNSETIFF ifr flags from <linux/tun_if.h>
+
+IFF_TUN		= 0x0001   # tunnel IP packets
+IFF_TAP		= 0x0002   # tunnel ethernet frames
+IFF_NO_PI	= 0x1000   # don't pass extra packet info
+IFF_ONE_QUEUE	= 0x2000   # beats me ;)
+
+def open_tun_interface(tun_device_filename):
+    from fcntl import ioctl
+    
+    mode = IFF_TAP | IFF_NO_PI
+    TUNSETIFF = 0x400454ca
+
+    tun = os.open(tun_device_filename, os.O_RDWR)
+    ifs = ioctl(tun, TUNSETIFF, struct.pack("16sH", "gr%d", mode))
+    ifname = ifs[:16].strip("\x00")
+    return (tun, ifname)
+    
+
+# /////////////////////////////////////////////////////////////////////////////
+#                             the flow graph
+# /////////////////////////////////////////////////////////////////////////////
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, mod_class, demod_class, tx_subdev_spec, rx_subdev_spec,
+                 bitrate, decim_rate, interp_rate, spb,
+                 bt, rx_callback, options):
+
+        gr.flow_graph.__init__(self)
+        self.txpath = transmit_path(self, mod_class, tx_subdev_spec,
+                                    bitrate, interp_rate, spb,
+                                    bt, options)
+        self.rxpath = receive_path(self, demod_class, rx_subdev_spec,
+                                   bitrate, decim_rate, spb,
+                                   rx_callback, options)
+
+    def send_pkt(self, payload='', eof=False):
+        return self.txpath.send_pkt(payload, eof)
+
+    def carrier_sensed(self):
+        """
+        Return True if the receive path thinks there's carrier
+        """
+        return self.rxpath.carrier_sensed()
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                           Carrier Sense MAC
+# /////////////////////////////////////////////////////////////////////////////
+
+class cs_mac(object):
+    """
+    Prototype carrier sense MAC
+
+    Reads packets from the TUN/TAP interface, and sends them to the PHY.
+    Receives packets from the PHY via phy_rx_callback, and sends them
+    into the TUN/TAP interface.
+
+    Of course, we're not restricted to getting packets via TUN/TAP, this
+    is just an example.
+    """
+    def __init__(self, tun_fd, verbose=False):
+        self.tun_fd = tun_fd       # file descriptor for TUN/TAP interface
+        self.verbose = verbose
+        self.fg = None             # flow graph (access to PHY)
+
+    def set_flow_graph(self, fg):
+        self.fg = fg
+
+    def phy_rx_callback(self, ok, payload):
+        """
+        Invoked by thread associated with PHY to pass received packet up.
+
+        @param ok: bool indicating whether payload CRC was OK
+        @param payload: contents of the packet (string)
+        """
+        if self.verbose:
+            print "Rx: ok = %r  len(payload) = %4d" % (ok, len(payload))
+        if ok:
+            os.write(self.tun_fd, payload)
+
+    def main_loop(self):
+        """
+        Main loop for MAC.
+        Only returns if we get an error reading from TUN.
+
+        FIXME: may want to check for EINTR and EAGAIN and reissue read
+        """
+        min_delay = 0.001               # seconds
+
+        while 1:
+            payload = os.read(self.tun_fd, 10*1024)
+            if not payload:
+                self.fg.send_pkt(eof=True)
+                break
+
+            if self.verbose:
+                print "Tx: len(payload) = %4d" % (len(payload),)
+
+            delay = min_delay
+            while self.fg.carrier_sensed():
+                sys.stderr.write('B')
+                time.sleep(delay)
+                if delay < 0.050:
+                    delay = delay * 2       # exponential back-off
+
+            self.fg.send_pkt(payload)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                       help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=None,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-g", "--rx-gain", type="eng_float", default=27,
+                      help="set rx gain")
+    parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Tx side A or B")
+    parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Rx side A or B")
+    parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]")
+    parser.add_option("-d", "--decim", type="intx", default=None,
+                      help="set fpga decim rate to DECIM [default=%default]")
+    parser.add_option("-i", "--interp", type="intx", default=None,
+                      help="set fpga interpolation rate to INTERP [default=%default]")
+    parser.add_option("-c", "--carrier-threshold", type="eng_float", default=30,
+                      help="set carrier detect threshold (dB) [default=%default]")
+    parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]")
+    parser.add_option("","--tun-device-filename", default="/dev/net/tun",
+                      help="path to tun device file [default=%default]")
+    parser.add_option("-v","--verbose", action="store_true", default=False)
+    fusb_options.add_options(parser)
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    # open the TUN/TAP interface
+    (tun_fd, tun_ifname) = open_tun_interface(options.tun_device_filename)
+
+    # Attempt to enable realtime scheduling
+    r = gr.enable_realtime_scheduling()
+    if r == gr.RT_OK:
+        realtime = True
+    else:
+        realtime = False
+        print "Note: failed to enable realtime scheduling"
+
+
+    # If the user hasn't set the fusb_* parameters on the command line,
+    # pick some values that will reduce latency.
+
+    if options.fusb_block_size == 0 and options.fusb_nblocks == 0:
+        if realtime:                        # be more aggressive
+            options.fusb_block_size = gr.prefs().get_long('fusb', 'rt_block_size', 1024)
+            options.fusb_nblocks    = gr.prefs().get_long('fusb', 'rt_nblocks', 16)
+        else:
+            options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096)
+            options.fusb_nblocks    = gr.prefs().get_long('fusb', 'nblocks', 16)
+    
+    print "fusb_block_size =", options.fusb_block_size
+    print "fusb_nblocks    =", options.fusb_nblocks
+
+    # instantiate the MAC
+    mac = cs_mac(tun_fd, verbose=True)
+
+
+    # build the graph (PHY)
+    fg = my_graph(blks.gmsk2_mod, blks.gmsk2_demod,
+                  options.tx_subdev_spec, options.rx_subdev_spec,
+                  options.bitrate, options.decim, options.interp,
+                  options.spb, options.bt, mac.phy_rx_callback,
+                  options)
+
+    mac.set_flow_graph(fg)    # give the MAC a handle for the PHY
+
+    if fg.txpath.bitrate() != fg.rxpath.bitrate():
+        print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % (
+            eng_notation.num_to_str(fg.txpath.bitrate()),
+            eng_notation.num_to_str(fg.rxpath.bitrate()))
+             
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
+    print "spb:     %3d" % (fg.txpath.spb(),)
+    print "interp:  %3d" % (fg.txpath.interp(),)
+
+    ok = fg.txpath.set_freq(options.freq)
+    if not ok:
+        print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),)
+        raise SystemExit
+
+    ok = fg.rxpath.set_freq(options.freq)
+    if not ok:
+        print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),)
+        raise SystemExit
+
+    fg.rxpath.set_gain(options.rx_gain)
+    print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain
+
+    fg.rxpath.set_carrier_threshold(options.carrier_threshold)
+    print "Carrier sense threshold:", options.carrier_threshold, "dB"
+    
+    print
+    print "Allocated virtual ethernet interface: %s" % (tun_ifname,)
+    print "You must now use ifconfig to set its IP address. E.g.,"
+    print
+    print "  $ sudo ifconfig %s 10.10.10.1" % (tun_ifname,)
+    print
+    print "Be sure to use a different address in the same subnet for each machine."
+    print
+
+
+    fg.start()    # Start executing the flow graph (runs in separate threads)
+
+    mac.main_loop()    # don't expect this to return...
+
+    fg.stop()     # but if it does, tell flow graph to stop.
+    fg.wait()     # wait for it to finish
+                
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/gmsk2/tx_voice.py b/gnuradio-examples/python/gmsk2/tx_voice.py
new file mode 100755
index 0000000000..9e274e5e09
--- /dev/null
+++ b/gnuradio-examples/python/gmsk2/tx_voice.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+from gnuradio.vocoder import gsm_full_rate
+
+import random
+import time
+import struct
+import sys
+
+# from current dir
+from transmit_path import transmit_path
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self, tx_subdev_spec, bitrate, interp_rate, spb, bt):
+        gr.flow_graph.__init__(self)
+        self.txpath = transmit_path(self, tx_subdev_spec, bitrate, interp_rate, spb, bt)
+
+        audio_input = ""
+        sample_rate = 8000
+        src = audio.source(sample_rate, audio_input)
+        src_scale = gr.multiply_const_ff(32767)
+        f2s = gr.float_to_short()
+        voice_coder = gsm_full_rate.encode_sp()
+        self.packets_from_encoder = gr.msg_queue()
+        packet_sink = gr.message_sink(33, self.packets_from_encoder, False)
+        self.connect(src, src_scale, f2s, voice_coder, packet_sink)
+
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    def send_pkt(payload='', eof=False):
+        return fg.txpath.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        print "ok = %r, payload = '%s'" % (ok, payload)
+
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                      help="select USRP Tx side A or B")
+    parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                       help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-r", "--bitrate", type="eng_float", default=100e3,
+                      help="specify bitrate.  spb and interp will be derived.")
+    parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]")
+    parser.add_option("-i", "--interp", type="intx", default=None,
+                      help="set fpga interpolation rate to INTERP [default=%default]")
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]")
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("","--discontinuous", action="store_true", default=False,
+                      help="enable discontinous transmission (bursts of 5 packets)")
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    pkt_size = int(options.size)
+
+    # build the graph
+    fg = my_graph(options.tx_subdev_spec, options.bitrate, options.interp,
+                  options.spb, options.bt)
+
+    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
+    print "spb:     %3d" % (fg.txpath.spb(),)
+    print "interp:  %3d" % (fg.txpath.interp(),)
+
+    fg.txpath.set_freq(options.freq)
+
+    fg.start()                       # start flow graph
+
+    # generate and send packets
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+
+    while n < nbytes:
+        packet = fg.packets_from_encoder.delete_head()
+        s = packet.to_string()
+        send_pkt(s)
+        n += len(s)
+        sys.stderr.write('.')
+        if options.discontinuous and pktno % 5 == 4:
+            time.sleep(1)
+        pktno += 1
+        
+    send_pkt(eof=True)
+    fg.wait()                       # wait for it to finish
+    fg.txpath.set_auto_tr(False)
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/mc4020/Makefile.am b/gnuradio-examples/python/mc4020/Makefile.am
new file mode 100644
index 0000000000..21bed3e469
--- /dev/null
+++ b/gnuradio-examples/python/mc4020/Makefile.am
@@ -0,0 +1,28 @@
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+EXTRA_DIST = 			\
+	fm_demod.py		\
+	mc4020_fft.py		
+
+
+
+
diff --git a/gnuradio-examples/python/mc4020/fm_demod.py b/gnuradio-examples/python/mc4020/fm_demod.py
new file mode 100755
index 0000000000..e58407f738
--- /dev/null
+++ b/gnuradio-examples/python/mc4020/fm_demod.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+from gnuradio import audio
+from gnuradio import mc4020
+import sys
+
+def high_speed_adc (fg, input_rate):
+    # return gr.file_source (gr.sizeof_short, "dummy.dat", False)
+    return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V)
+
+#
+# return a gr.flow_graph
+#
+def build_graph (freq1, freq2):
+    input_rate = 20e6
+    cfir_decimation = 125
+    audio_decimation = 5
+
+    quad_rate = input_rate / cfir_decimation
+    audio_rate = quad_rate / audio_decimation
+
+    fg = gr.flow_graph ()
+    
+    # use high speed ADC as input source
+    src = high_speed_adc (fg, input_rate)
+    
+    # compute FIR filter taps for channel selection
+    channel_coeffs = \
+      gr.firdes.low_pass (1.0,          # gain
+                          input_rate,   # sampling rate
+                          250e3,        # low pass cutoff freq
+                          8*100e3,      # width of trans. band
+                          gr.firdes.WIN_HAMMING)
+
+    # input: short; output: complex
+    chan_filter1 = \
+      gr.freq_xlating_fir_filter_scf (cfir_decimation,
+                                      channel_coeffs,
+                                      freq1,        # 1st station freq
+                                      input_rate)
+    
+    (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation)
+    
+    # sound card as final sink
+    audio_sink = audio.sink (int (audio_rate))
+
+    # now wire it all together
+    fg.connect (src, chan_filter1)
+    fg.connect (chan_filter1, head1)
+    fg.connect (tail1, (audio_sink, 0))
+
+    # two stations at once?
+    if freq2:
+        # Extract the second station and connect
+        # it to a second pipeline...
+
+        # input: short; output: complex
+        chan_filter2 = \
+          gr.freq_xlating_fir_filter_scf (cfir_decimation,
+                                          channel_coeffs,
+                                          freq2,        # 2nd station freq
+                                          input_rate)
+
+        (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation)
+
+        fg.connect (src, chan_filter2)
+        fg.connect (chan_filter2, head2)
+        fg.connect (tail2, (audio_sink, 1))
+    
+    return fg
+
+def build_pipeline (fg, quad_rate, audio_decimation):
+    '''Given a flow_graph, fg, construct a pipeline
+    for demodulating a broadcast FM signal.  The
+    input is the downconverteed complex baseband
+    signal. The output is the demodulated audio.
+
+    build_pipeline returns a two element tuple
+    containing the input and output endpoints.
+    '''
+    fm_demod_gain = 2200.0/32768.0
+    audio_rate = quad_rate / audio_decimation
+    volume = 1.0
+
+    # input: complex; output: float
+    fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain)
+
+    # compute FIR filter taps for audio filter
+    width_of_transition_band = audio_rate / 32
+    audio_coeffs = gr.firdes.low_pass (1.0,            # gain
+                                       quad_rate,      # sampling rate
+                                       audio_rate/2 - width_of_transition_band,
+                                       width_of_transition_band,
+                                       gr.firdes.WIN_HAMMING)
+
+    # input: float; output: float
+    audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
+
+    fg.connect (fm_demod, audio_filter)
+    return ((fm_demod, 0), (audio_filter, 0))
+    
+
+def main (args):
+    nargs = len (args)
+    if nargs == 1:
+        freq1 = float (args[0]) * 1e6
+        freq2 = None
+    elif nargs == 2:
+        freq1 = float (args[0]) * 1e6
+        freq2 = float (args[1]) * 1e6
+    else:
+        sys.stderr.write ('usage: fm_demod freq1 [freq2]\n')
+        sys.exit (1)
+
+    # connect to RF front end
+    rf_front_end = gr.microtune_4937_eval_board ()
+    if not rf_front_end.board_present_p ():
+        raise IOError, 'RF front end not found'
+
+    # set front end gain
+    rf_front_end.set_AGC (300)
+    IF_freq = rf_front_end.get_output_freq ()
+    IF_freq = 5.75e6
+
+    if not freq2:      # one station
+
+        rf_front_end.set_RF_freq (freq1)
+        fg = build_graph (IF_freq, None)
+
+    else:              # two stations
+
+        if abs (freq1 - freq2) > 5.5e6:
+            raise IOError, 'freqs too far apart'
+
+        target_freq = (freq1 + freq2) / 2
+        actual_freq = rf_front_end.set_RF_freq (target_freq)
+        #actual_freq = target_freq
+        
+        fg = build_graph (IF_freq + freq1 - actual_freq,
+                          IF_freq + freq2 - actual_freq)
+    
+    fg.start ()        # fork thread(s) and return
+    raw_input ('Press Enter to quit: ')
+    fg.stop ()
+
+if __name__ == '__main__':
+    main (sys.argv[1:])
+
+
diff --git a/gnuradio-examples/python/mc4020/mc4020_fft.py b/gnuradio-examples/python/mc4020/mc4020_fft.py
new file mode 100755
index 0000000000..3348ad4f6b
--- /dev/null
+++ b/gnuradio-examples/python/mc4020/mc4020_fft.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import mc4020
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink
+from optparse import OptionParser
+import wx
+
+class app_flow_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+
+        
+        parser = OptionParser (option_class=eng_option)
+        (options, args) = parser.parse_args ()
+
+        input_rate = 20e6
+        src = mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V)
+        cvt = gr.short_to_float ()
+        block, fft_win = fftsink.make_fft_sink_f (self, panel, "Rx Data", 512, input_rate)
+
+        self.connect (src, cvt)
+        self.connect (cvt, block)
+        vbox.Add (fft_win, 1, wx.EXPAND)
+
+
+def main ():
+    app = stdgui.stdapp (app_flow_graph, "USRP FFT")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/multi-antenna/multi_fft.py b/gnuradio-examples/python/multi-antenna/multi_fft.py
new file mode 100755
index 0000000000..ca9c614a88
--- /dev/null
+++ b/gnuradio-examples/python/multi-antenna/multi_fft.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from gnuradio import eng_notation
+from gnuradio import optfir
+from optparse import OptionParser
+from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+import wx
+import usrp_dbid
+import time
+import os.path
+import sys
+
+# required FPGA that can do 4 rx channels.
+
+
+class my_graph(stdgui.gui_flow_graph):
+
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self)
+
+        self.frame = frame
+        self.panel = panel
+
+        parser = OptionParser (option_class=eng_option)
+        #parser.add_option("-S", "--subdev", type="subdev", default=(0, None),
+        #                  help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-d", "--decim", type="int", default=128,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=146.585e6,
+                          help="set frequency to FREQ [default=%default])", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=20,
+                          help="set gain in dB [default=%default]")
+        parser.add_option("-F", "--filter", action="store_true", default=True,
+                          help="Enable channel filter")
+        (options, args) = parser.parse_args()
+
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit
+
+        nchan = 4
+
+        if options.filter:
+            sw_decim = 4
+        else:
+            sw_decim = 1
+
+        self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf")
+        if self.u.nddc() < nchan:
+            sys.stderr.write('This code requires an FPGA build with %d DDCs.  This FPGA has only %d.\n' % (
+                nchan, self.u.nddc()))
+            raise SystemExit
+                             
+        if not self.u.set_nchannels(nchan):
+            sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,))
+            raise SystemExit
+        
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+        print "USB data rate   = %s" % (eng_notation.num_to_str(input_rate),)
+        print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),)
+
+        self.subdev = self.u.db[0] + self.u.db[1]
+
+        if (len (self.subdev) != 4 or
+            self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or
+            self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX):
+            sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n')
+            sys.exit(1)
+
+        self.u.set_mux(gru.hexint(0xf3f2f1f0))
+
+        # deinterleave four channels from FPGA
+        di = gr.deinterleave(gr.sizeof_gr_complex)
+
+        self.connect(self.u, di)
+        
+
+
+        # taps for channel filter
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            input_rate,  # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+
+        for i in range(nchan):
+            scope = fftsink.fft_sink_c(self, panel, sample_rate=input_rate/sw_decim,
+                                       title="Input %d" % (i,),
+                                       ref_level=80, y_per_div=20)
+            vbox.Add(scope.win, 10, wx.EXPAND)
+
+            if options.filter:
+                chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs)
+                self.connect((di, i), chan_filt, scope)
+            else:
+                self.connect((di, i), scope)
+
+
+        self.set_gain(options.gain)
+        self.set_freq(options.freq)
+
+    def set_gain(self, gain):
+        for i in range(len(self.subdev)):
+            self.subdev[i].set_gain(gain)
+
+    def set_freq(self, target_freq):
+        ok = True
+        for i in range(len(self.subdev)):
+            r = usrp.tune(self.u, i, self.subdev[i], target_freq)
+            if not r:
+                ok = False
+                print "set_freq: failed to set subdev[%d] freq to %f" % (
+                    i, target_freq)
+
+        return ok
+
+
+def main ():
+    app = stdgui.stdapp(my_graph, "Multi Scope", nstatus=1)
+    app.MainLoop()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/multi-antenna/multi_file.py b/gnuradio-examples/python/multi-antenna/multi_file.py
new file mode 100755
index 0000000000..e2a6e04f68
--- /dev/null
+++ b/gnuradio-examples/python/multi-antenna/multi_file.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from gnuradio import eng_notation
+from gnuradio import optfir
+from optparse import OptionParser
+from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+import wx
+import usrp_dbid
+import time
+import os.path
+import sys
+
+# required FPGA that can do 4 rx channels.
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser = OptionParser (option_class=eng_option)
+        #parser.add_option("-S", "--subdev", type="subdev", default=(0, None),
+        #                  help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-d", "--decim", type="int", default=128,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=146.585e6,
+                          help="set frequency to FREQ [default=%default])", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=20,
+                          help="set gain in dB [default=%default]")
+        parser.add_option("-F", "--filter", action="store_true", default=True,
+                          help="Enable channel filter")
+        parser.add_option("-o", "--output", type="string", default=None,
+                          help="set output basename")
+        (options, args) = parser.parse_args()
+
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit
+
+        if options.output is None:
+            parser.print_help()
+            sys.stderr.write("You must provide an output filename base with -o OUTPUT\n")
+            raise SystemExit
+        else:
+            basename = options.output
+
+        nchan = 4
+        nsecs = 4.0
+
+        if options.filter:
+            sw_decim = 4
+        else:
+            sw_decim = 1
+
+        self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf")
+        if self.u.nddc() < nchan:
+            sys.stderr.write('This code requires an FPGA build with %d DDCs.  This FPGA has only %d.\n' % (
+                nchan, self.u.nddc()))
+            raise SystemExit
+                             
+        if not self.u.set_nchannels(nchan):
+            sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,))
+            raise SystemExit
+        
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+        print "USB data rate   = %s" % (eng_notation.num_to_str(input_rate),)
+        sink_data_rate = input_rate/sw_decim
+        print "Scope data rate = %s" % (eng_notation.num_to_str(sink_data_rate),)
+
+        self.subdev = self.u.db[0] + self.u.db[1]
+
+        if (len(self.subdev) != 4 or
+            self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or
+            self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX):
+            sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n')
+            sys.exit(1)
+
+        self.u.set_mux(gru.hexint(0xf3f2f1f0))
+
+        # collect 1 second worth of data
+        limit = int(nsecs * input_rate * nchan)
+        print "limit = ", limit
+        head = gr.head(gr.sizeof_gr_complex, limit)
+
+        # deinterleave four channels from FPGA
+        di = gr.deinterleave(gr.sizeof_gr_complex)
+
+        self.connect(self.u, head, di)
+        
+        # taps for channel filter
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            input_rate,  # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+
+        for i in range(nchan):
+
+            sink = gr.file_sink(gr.sizeof_gr_complex,
+                                basename + ("-%s-%d.dat" % (eng_notation.num_to_str(sink_data_rate), i)))
+            if options.filter:
+                chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs)
+                self.connect((di, i), chan_filt, sink)
+            else:
+                self.connect((di, i), sink)
+
+
+        self.set_gain(options.gain)
+        self.set_freq(options.freq)
+
+    def set_gain(self, gain):
+        for i in range(len(self.subdev)):
+            self.subdev[i].set_gain(gain)
+
+    def set_freq(self, target_freq):
+        ok = True
+        for i in range(len(self.subdev)):
+            r = usrp.tune(self.u, i, self.subdev[i], target_freq)
+            if not r:
+                ok = False
+                print "set_freq: failed to set subdev[%d] freq to %f" % (
+                    i, target_freq)
+
+        return ok
+
+
+def main ():
+    my_graph().run()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/multi-antenna/multi_scope.py b/gnuradio-examples/python/multi-antenna/multi_scope.py
new file mode 100755
index 0000000000..43aa77b0d6
--- /dev/null
+++ b/gnuradio-examples/python/multi-antenna/multi_scope.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from gnuradio import eng_notation
+from gnuradio import optfir
+from optparse import OptionParser
+from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+import wx
+import usrp_dbid
+import time
+import os.path
+import sys
+
+# required FPGA that can do 4 rx channels.
+
+
+class my_graph(stdgui.gui_flow_graph):
+
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self)
+
+        self.frame = frame
+        self.panel = panel
+
+        parser = OptionParser (option_class=eng_option)
+        #parser.add_option("-S", "--subdev", type="subdev", default=(0, None),
+        #                  help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-d", "--decim", type="int", default=128,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=146.585e6,
+                          help="set frequency to FREQ [default=%default])", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=20,
+                          help="set gain in dB [default=%default]")
+        parser.add_option("-F", "--filter", action="store_true", default=True,
+                          help="Enable channel filter")
+        (options, args) = parser.parse_args()
+
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit
+
+        nchan = 4
+
+        if options.filter:
+            sw_decim = 4
+        else:
+            sw_decim = 1
+
+        self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf")
+        if self.u.nddc() < nchan:
+            sys.stderr.write('This code requires an FPGA build with %d DDCs.  This FPGA has only %d.\n' % (
+                nchan, self.u.nddc()))
+            raise SystemExit
+                             
+        if not self.u.set_nchannels(nchan):
+            sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,))
+            raise SystemExit
+        
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+        print "USB data rate   = %s" % (eng_notation.num_to_str(input_rate),)
+        print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),)
+
+        self.subdev = self.u.db[0] + self.u.db[1]
+
+        if (len(self.subdev) != 4 or
+            self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or
+            self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX):
+            sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n')
+            sys.exit(1)
+
+        self.u.set_mux(gru.hexint(0xf3f2f1f0))
+
+        # deinterleave four channels from FPGA
+        di = gr.deinterleave(gr.sizeof_gr_complex)
+
+        self.connect(self.u, di)
+        
+        # our destination (8 float inputs)
+        self.scope = scopesink.scope_sink_f(self, panel, sample_rate=input_rate/sw_decim)
+
+        # taps for channel filter
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            input_rate,  # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+
+        # bust the deinterleaved complex channels into floats
+        for i in range(nchan):
+
+            if options.filter:
+                chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs)
+                c2f = gr.complex_to_float()
+                self.connect((di, i), chan_filt, c2f)
+            else:
+                c2f = gr.complex_to_float()
+                self.connect((di, i), c2f)
+
+            self.connect((c2f, 0), (self.scope, 2*i + 0))
+            self.connect((c2f, 1), (self.scope, 2*i + 1))
+
+
+        self._build_gui(vbox)
+
+        self.set_gain(options.gain)
+        self.set_freq(options.freq)
+
+    def set_gain(self, gain):
+        for i in range(len(self.subdev)):
+            self.subdev[i].set_gain(gain)
+
+    def set_freq(self, target_freq):
+        ok = True
+        for i in range(len(self.subdev)):
+            r = usrp.tune(self.u, i, self.subdev[i], target_freq)
+            if not r:
+                ok = False
+                print "set_freq: failed to set subdev[%d] freq to %f" % (
+                    i, target_freq)
+
+        return ok
+
+
+    def _build_gui(self, vbox):
+        vbox.Add(self.scope.win, 10, wx.EXPAND)
+        
+
+
+def main ():
+    app = stdgui.stdapp(my_graph, "Multi Scope", nstatus=1)
+    app.MainLoop()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/multi_usrp/Makefile.am b/gnuradio-examples/python/multi_usrp/Makefile.am
new file mode 100644
index 0000000000..c2c6a29435
--- /dev/null
+++ b/gnuradio-examples/python/multi_usrp/Makefile.am
@@ -0,0 +1,28 @@
+#
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+EXTRA_DIST = 			\
+	README		\
+	multi_usrp_oscope.py		\
+	multi_usrp_rx_cfile.py
+
+
+
diff --git a/gnuradio-examples/python/multi_usrp/README b/gnuradio-examples/python/multi_usrp/README
new file mode 100644
index 0000000000..c93d7736a0
--- /dev/null
+++ b/gnuradio-examples/python/multi_usrp/README
@@ -0,0 +1,260 @@
+Quick start multi-usrp:
+
+Unpack, build and install usrp, gnuradio-core and gr-usrp
+Versions need to be more recent then 2.7cvs/svn 11 may 2006
+
+Make sure usrp/fpga/rbf/rev2/multi*.rbf is installed in /usr/local/share/usrp/rev2/
+Make sure usrp/fpga/rbf/rev4/multi*.rbf is installed in /usr/local/share/usrp/rev4/
+(If in doubt, copy manually)
+ 
+build and install gr-wxgui gr-audio-xxx  and so on.
+
+unpack gnuradio-examples.
+
+There is a gnuradio-examples/python/multi_usrp directory which contains examples
+
+
+Put at least a basic RX or dbsrx board in RXA of the master and RXA of the slave board.
+Make sure that the usrps have a serial or unique identifier programmed in their eeprom.
+(All new rev 4.1 boards have this)
+You can do without a serial but then you never know which usrp is the master and which is the slave.
+
+
+CONNECTING THE CABLES
+Now connect the 64MHz clocks between the boards with a short sma coax cable.
+(See the wiki on how to enable clock-out and clock-in 
+http://comsec.com/wiki?USRPClockingNotes )
+
+You need one board with a clock out and one board with a clock in.
+
+You can choose any of the two boards as master or slave, this is not dependant on which board has the clock-out or in.
+In my experiments I had fewer problems when the board that has the clock-in will be the master board.
+
+You can use a standard 16-pole flatcable to connect tvrx, basic-rx or dbsrx boards.
+Of this 16pin flatcable only two pins are used (io15 and ground)
+For all new daughterboards which use up a lot of io pins you have to use a cable with fewer connections.
+The savest is using a 2pin headercable connected to io15,gnd (a cable like the ones used to connect frontpanel leds to the mainboard of a PC)
+
+If using basic rx board:
+  Connect a 16-pole flatcable from J25 on basicrx/dbs_rx in rxa of the master usrp to J25 on basicrx/dbsrx in RXA of the slave usrp
+  Don't twist the cable (Make sure the pin1 marker (red line on the flatcable) is on the same side of the connector (at io-8 on the master and at io8 on the slave.))
+  For basic_rx this means the marker should be on the side of the dboard with the sma connectors. 
+  For dbs_rx this means the marker should be on the side of the dboard with the two little chips.
+  In other words, don't twist the cable, you will burn your board if you do.
+
+You can also connect a flatcable with multiple connectors from master-J25 to slave1-J25 to slave2-J25 to ...
+You will however have to think of something to create a common 64Mhz clock for more then two usrps.
+
+For all other daughterboards, connect a 2wire cable from masterRXA J25 io15,gnd to slaveRXA J25 io15,gnd 
+
+
+So now the hardware is setup, software is setup. Lets do some tests.
+
+Connect power to both usrps.
+unpack the gnuradio_examples somewhere (cvs version later then 11 may 2006) 
+go to the gnuradio-examples/python/multi_usrp folder.
+
+Now run 
+ ./multi_usrp_oscope.py -x 12345678
+
+It should tell you that usrp 12345678 is not found and tell you which serials are available.
+
+Now run  ./multi_usrp_oscope.py -x actualserialnum 
+You should now get an oscope with two channels, one is from the master and one is from the slave
+It will which show the I-signal from channel 0 of the master usrp and I-signal from channel 0 of the slave usrp.
+(For testing connect the same signal source to the inputs of both boards)
+The signals should be aligned.
+If you click the sync button, it will resync the master and slave (should never be needed)
+
+Now run
+./multi_usrp_oscope.py --help
+To see all available options.
+
+
+Now you are ready to do phase-locked aligned signal processing.
+
+You can also capture to file with:
+./multi_usrp_rx_cfile.py 
+
+run ./multi_usrp_rx_cfile.py --help to see all available options.
+
+
+
+Here follows a description of the detail blocks used in usrp_multi.py
+
+Multi usrp
+
+With this code you can connect two or more usrps (with a locked clock) and get synchronised samples.
+You must connect a (flat)cable between a dboard on the master in RXA and a dboard on the slave in RXA.
+You then put one usrp in master mode, put the other in slave mode.
+
+The easiest thing to see how this works is just looking at the code in
+ multi_usrp_oscope.py
+ multi_usrp_rx_cfile.py 
+
+Use the usrp_multi block which is installed by gr-usrp.
+instantiate in the following way:
+
+        self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, nchan=options.nchan )
+
+nchan should be 2 or 4.
+
+You determine which is the master by master_serialno (this is a text string a hexadecimal number).
+If you enter a serial number which is not found it will print the serial numbers which are available.
+If you give no serial number  (master_serialno=None), the code will pick a Master for you.
+
+You can get a reference to the master and the slave usrp in the following way:
+
+        self.um=self.multi.get_master_usrp()
+        self.us=self.multi.get_slave_usrp()
+
+You only need these references for setting freqs/gains or getting info about daughterboards.
+Don't use the output directly but use the aligned output from multi.get_master_source_c() and multi.get_slave_source_c()
+
+You get references to the aligned output samples in the following way:
+aligned_master_source_c=self.multi.get_master_source_c()
+aligned_slave_source_c=self.multi.get_slave_source_c()
+
+These blocks have multiple outputs.
+output 0 is the sample counter (high bits in I, low bits in Q)
+You normally don't need the samplecounters so you can ignore output 0
+
+output 1 is the first aligend output channel (if you enable 2 or 4 channels)
+output 2 is the second output channel (only if you enable 4 channels)
+
+so the usefull 4 channels are:
+self.aligned_master_chan1=(self.multi.get_master_source_c(),1)
+self.aligned_master_chan2=(self.multi.get_master_source_c(),2)
+self.aligned_slave_chan1=(self.multi.get_slave_source_c(),1)
+self.aligned_slave_chan2=(self.multi.get_slave_source_c(),2)
+
+The two samplecounters are:
+self.aligned_master_samplecounter=(self.multi.get_master_source_c(),0)
+self.aligned_slave_samplecounter=(self.multi.get_slave_source_c(),0)
+
+You can set the gain or tune the frequency for all 4 receive daughetrboards at once:
+        self.multi.set_gain_all_rx(options.gain)
+        result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq)
+
+This will only work reliably when you have all the same daughterboards.
+Otherwise set all freqs and gains individually.
+
+You must call self.multi.sync() at least once AFTER the flowgraph has started running.
+(This will synchronise the streams of the two usrps)
+
+This work was funded by Toby Oliver at Sensus Analytics / Path Intelligence.
+Many Thanks for making this possible.
+
+It was written by Martin Dudok van Heel at Olifantasia.
+
+
+
+Here follows a brief of the new blocks and (changes)functionality written for multi-usrp support.
+
+You can also look at the generated documentation in  
+/usr/local/share/doc/gnuradio-core-X.X
+/usr/local/share/doc/usrp-X.X
+(Make sure to build and install the documentation, go to the doc directory of the sourcetree and issue make doc; make install)
+ 
+
+gnuradio-examples:
+new/changed files:
+multi_usrp/multi_usrp_oscope.py
+multi_usrp/multi_usrp_rx_cfile.py
+
+
+gnuradio-core:
+gr.align_on_samplenumbers_ss (int nchan,int align_interval) 
+
+align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values)
+
+Parameters:
+    	nchan 	number of complex_short input channels (including the 32 bit counting channel)
+    	align_interval 	interval at which the samples are aligned, ignored for now.
+
+Pay attention on how you connect this block It expects a minimum of 2 usrp_source_s with nchan number of channels and as mode  usrp_prims.bmFR_MODE_RX_COUNTING_32BIT enabled. This means that the first complex_short channel is an interleaved 32 bit counter. The samples are aligned by dropping samples untill the samplenumbers match.
+
+files:
+gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc
+gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h
+gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i
+
+
+gr-usrp
+   added _write_fpga_reg_masked
+   added usrp_multi.py
+  new usrp_multi block which can instantiate two linked usrps as master and slave and alignes their output.
+  It has a sync() function which should be called AFTER the flowgraph has started running.
+  bool sync();
+     \brief Call this on a master usrp to sync master and slave by outputing a sync pulse on rx_a_io[15].
+        The 32 bit samplecounter of master and slave will be reset to zero and all phase and buffer related things in the usrps are reset.
+        Call this only after the flowgraph has been started, otherwise there will be no effect since everything is kept in reset state as long as the flowgraph is not running.
+     \returns true if successfull.
+
+files:
+configure.ac
+src/Makefile.am
+src/usrp1.i
+src/usrp1_source_base.cc
+src/usrp1_source_base.h
+src/usrp_multi.py
+
+usrp-0.11cvsmulti:
+usrp:
+   new constant bmFR_MODE_RX_COUNTING_32BIT    (could also be added as extra mode like FPGA_MODE_COUNTING_32BIT)
+   Use this for the mode parameter when creating a usrp when you want to use the master/slave setup or if you want to use the 32 bit counter for other things, like testing with gr.check_counting_s(True)
+
+  added register FR_RX_MASTER_SLAVE
+  added bitno and bitmaskes:
+   bmFR_MODE_RX_COUNTING_32BIT
+
+   bitnoFR_RX_SYNC 
+   bitnoFR_RX_SYNC_MASTER
+   bitnoFR_RX_SYNC_SLAVE
+
+   bitnoFR_RX_SYNC_INPUT_IOPIN 15
+   bmFR_RX_SYNC_INPUT_IOPIN  (1<<bitnoFR_RX_SYNC_INPUT_IOPIN)
+   bitnoFR_RX_SYNC_OUTPUT_IOPIN 15
+   bmFR_RX_SYNC_OUTPUT_IOPIN (1<<bitnoFR_RX_SYNC_OUTPUT_IOPIN)
+ 
+   added _write_fpga_reg_masked()
+   added new toplevel folder usrp_multi
+   added usrp_multi.v and master_control_multi.v
+   added new MULTI_ON and COUNTER_32BIT_ON defines
+      If these are turned off usrp_multi.v will behave exactly as usrp_std.v
+
+   added setting_reg_masked.v
+   changed reset behaviour of phase_acc.v and rx_buffer.v
+
+   changed generate_regs.py to handle bm and bitno defines
+
+
+files:
+firmware/include/fpga_regs_standard.v
+firmware/include/fpga_regs_common.h
+firmware/include/generate_regs.py
+firmware/include/fpga_regs_standard.h
+host/lib/usrp_basic.h
+host/lib/usrp_basic.cc
+host/lib/usrp_standard.h
+fpga/rbf/Makefile.am
+fpga/toplevel/usrp_std/usrp_std.v
+fpga/toplevel/usrp_multi/usrp_multi.esf
+fpga/toplevel/usrp_multi/usrp_multi.vh
+fpga/toplevel/usrp_multi/usrp_std.vh
+fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh
+fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh
+fpga/toplevel/usrp_multi/usrp_multi.v
+fpga/toplevel/usrp_multi/usrp_multi.qpf
+fpga/toplevel/usrp_multi/usrp_multi.psf
+fpga/toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh
+fpga/toplevel/usrp_multi/usrp_multi.qsf
+fpga/toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh
+fpga/toplevel/usrp_multi/usrp_multi.csf
+fpga/toplevel/usrp_multi/.cvsignore
+fpga/sdr_lib/rx_buffer.v
+fpga/sdr_lib/master_control_multi.v
+fpga/sdr_lib/phase_acc.v
+fpga/sdr_lib/setting_reg_masked.v
+
+
diff --git a/gnuradio-examples/python/multi_usrp/multi_usrp_oscope.py b/gnuradio-examples/python/multi_usrp/multi_usrp_oscope.py
new file mode 100755
index 0000000000..d64cd1e641
--- /dev/null
+++ b/gnuradio-examples/python/multi_usrp/multi_usrp_oscope.py
@@ -0,0 +1,343 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# print "Loading revised usrp_oscope with additional options for scopesink..."
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+from optparse import OptionParser
+import wx
+import sys
+
+import time
+from gnuradio import usrp_multi
+
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    If there's a daughterboard on A, select A.
+    If there's a daughterboard on B, select B.
+    Otherwise, select A.
+    """
+    if u.db[0][0].dbid() >= 0:       # dbid is < 0 if there's no d'board or a problem
+        return (0, 0)
+    if u.db[1][0].dbid() >= 0:
+        return (1, 0)
+    return (0, 0)
+
+
+class app_flow_graph(stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self)
+
+        self.frame = frame
+        self.panel = panel
+        
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=first one with a daughterboard)")
+        parser.add_option("-d", "--decim", type="int", default=128,
+                          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)")
+        #align interval is default not yet enabled in gr.align_on_samplenumbers_ss
+        #parser.add_option("-a", "--align_interval", type="int", default=-1,
+        #                  help="Align master and slave every so much samples.")
+
+        # width 8 does not work yet with multi_usrp because it interferes with the 32 bit samplecounter
+        #parser.add_option("-8", "--width-8", action="store_true", default=False,
+        #                  help="Enable 8-bit samples across USB")
+        parser.add_option("-m", "--mux", type="intx", default=None,
+                          help="set fpga FR_RX_MUX register to MUX")
+        parser.add_option("-n", "--frame-decim", type="int", default=1,
+                          help="set oscope frame decimation factor to n [default=1]")
+        parser.add_option("-N", "--nchan", type="int", default=2,
+                          help="set nchannels to NCHAN")
+        parser.add_option("-q", "--show-q", action="store_true", default=False,
+                          help="show the q value of the complex samples")
+        parser.add_option("-s", "--show-counters", action="store_true", default=False,
+                          help="show the counters")
+        parser.add_option("-v", "--v-scale", type="eng_float", default=1000,
+                          help="set oscope initial V/div to SCALE [default=%default]")
+        parser.add_option("-t", "--t-scale", type="eng_float", default=49e-6,
+                          help="set oscope initial s/div to SCALE [default=50us]")
+        parser.add_option("-x", "--master-serialno", type="string", default=None, 
+                          help="Serial_no of the usrp which should be the MASTER (default= select any)")
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+
+        self.show_debug_info = True
+        
+        # build the graph
+
+        #self.u = usrp.source_c(which=options.which_usrp,decim_rate=options.decim)
+        if (options.mux is None) | (4==options.nchan):
+           init_mux=None #use default mux which is 0x10321032
+        else:
+           init_mux=options.mux
+
+        init_gain=0.0
+        init_freq=0.0
+        init_align_interval=-1
+
+        self.multi=usrp_multi.multi_source_align( self,   options.master_serialno, options.decim,
+                                                 options.nchan, init_gain, init_freq, init_mux, init_align_interval)
+        self.um=self.multi.get_master_usrp()
+        self.us=self.multi.get_slave_usrp()
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.um)
+        if (options.mux==None) and (options.nchan!=4):
+          mux=usrp.determine_rx_mux_value(self.um, options.rx_subdev_spec)
+          mux= (mux<<8 & 0xffffffff) | (mux & 0xff)
+          self.um.set_mux(mux)
+          self.us.set_mux(mux)
+
+        # width 8 does not work yet with multi_usrp because it interferes with the 32 bit samplecounter
+        #if options.width_8:
+        #    width = 8
+        #    shift = 8
+        #    format = self.um.make_format(width, shift)
+        #    r = self.um.set_format(format)
+        #    r = self.us.set_format(format)
+            
+        # determine the daughterboard subdevice of the first channel we're using
+        self.subdevm = usrp.selected_subdev(self.um, options.rx_subdev_spec)
+        self.subdevs = usrp.selected_subdev(self.us, options.rx_subdev_spec)
+
+        input_rate = self.um.adc_freq() / self.um.decim_rate()
+
+        self.scope = scopesink.scope_sink_f(self, panel, sample_rate=input_rate,
+                                            frame_decim=options.frame_decim,
+                                            v_scale=options.v_scale,
+                                            t_scale=options.t_scale)
+        self.sink_count=0
+        self.add_to_scope((self.multi.get_master_source_c(),1),options.show_q)
+        self.add_to_scope((self.multi.get_slave_source_c(),1),options.show_q)
+        if 4==options.nchan:
+          self.add_to_scope((self.multi.get_master_source_c(),2),options.show_q)
+          self.add_to_scope((self.multi.get_slave_source_c(),2),options.show_q)
+
+        if options.show_counters:
+          self.add_to_scope((self.multi.get_master_source_c(),0),options.show_q)
+          self.add_to_scope((self.multi.get_slave_source_c(),0),options.show_q)
+
+        self._build_gui(vbox)
+
+        # set initial values
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdevm.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.subdevm.freq_range()
+            options.freq = float(r[0]+r[1])/2
+
+        self.set_gain(options.gain)
+
+        if self.show_debug_info:
+            self.myform['decim'].set_value(self.um.decim_rate())
+            self.myform['fs@usb'].set_value(self.um.adc_freq() / self.um.decim_rate())
+            self.myform['dbname'].set_value(self.subdevm.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")
+
+        self.multi.print_db_info()
+        self.unsynced=True
+        frame.Bind(wx.EVT_IDLE, self.onIdle)
+
+    def add_to_scope(self,source_c,show_q):
+        c2f= gr.complex_to_float ()
+        self.connect(source_c, c2f)
+        self.connect((c2f,0), (self.scope,self.sink_count))
+        self.sink_count=self.sink_count+1
+        if show_q:
+          self.connect((c2f,1), (self.scope,self.sink_count))
+          self.sink_count=self.sink_count+1
+        
+        
+    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.subdevm.gain_range()
+        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)
+        buttonSync = form.button_with_callback(parent=self.panel, label='sync',callback=self.sync_usrps)
+        hbox.Add(buttonSync,0,wx.EXPAND)
+
+        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)
+        
+        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.static_float_field(
+            parent=panel, sizer=hbox, label="Decim")
+
+        hbox.Add((5,0), 1)
+        myform['fs@usb'] = form.static_float_field(
+            parent=panel, sizer=hbox, label="Fs@USB")
+
+        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)
+
+
+    def set_freq(self, target_freq, sync=True):
+        """
+        Set the center frequency we're interested in for all channels,
+        on all rx daughterboards on MASTER and SLAVE.
+
+        @param target_freq: frequency in Hz
+        @param sync: sync the usrps after setting the freqs (this will clear any phase differences in the DDCS)
+        @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.
+        """
+        result,r1,r2,r3,r4 = self.multi.tune_all_rx(target_freq)
+        if sync:
+          self.sync_usrps() #sync master and slave and clear any DDC phase differences
+        if r1:
+            self.myform['freq'].set_value(target_freq)     # update displayed value
+            if self.show_debug_info:
+                self.myform['baseband'].set_value(r1.baseband_freq)
+                self.myform['ddc'].set_value(r1.dxc_freq)
+        return result
+
+    def set_freq_chan0(self, target_freq, sync=True):
+        """
+        Set the center frequency we're interested in for rx chan 0 only on MASTER and SLAVE.
+
+        @param target_freq: frequency in Hz
+        @param sync: sync the usrps after setting the freqs (this will clear any phase differences in the DDCS)
+        @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.
+        """
+        rm = usrp.tune(self.um, 0, self.subdevm, target_freq)
+        rs = usrp.tune(self.us, 0, self.subdevs, target_freq)
+        r=rm
+        if sync:
+          self.sync_usrps()  #sync master and slave and clear any DDC phase differences
+        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)
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.multi.set_gain_all_rx(gain)
+
+    def set_gain_chan0(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.subdevm.set_gain(gain)
+        self.subdevs.set_gain(gain)
+
+    def onIdle(self,evt):
+        if self.unsynced:
+          time.sleep(0.5)
+          self.unsynced=True
+          self.multi.sync()
+          self.unsynced=False
+          #print 'synced'
+
+    def sync_usrps(self):
+        self.multi.sync()
+
+def main ():
+    app = stdgui.stdapp(app_flow_graph, "MULTI_USRP O'scope", nstatus=1)
+    app.MainLoop()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py b/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py
new file mode 100755
index 0000000000..6084aba3d7
--- /dev/null
+++ b/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+
+"""
+Read samples 2 from two linked synchronised USRP's and write to file formatted as binary
+single-precision complex values.
+Make sure you read README on how to link the two usrps
+
+"""
+
+from gnuradio import gr, eng_notation
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+
+import time
+from gnuradio import usrp_multi
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        usage="%prog: [options] output_filename"
+        parser = OptionParser(option_class=eng_option, usage=usage)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0),
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-d", "--decim", type="int", default=128,
+                          help="set selfpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=0.0,
+                          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("-n", "--nchan", type="intx", default=2,
+                          help="set nchannels to NCHAN")
+        parser.add_option("-N", "--nsamples", type="eng_float", default=None,
+                          help="number of samples to collect [default=+inf]")
+        parser.add_option ("-o", "--output-file-m", default="usrp_rx_m.dat",
+                       help="write master data to FILE", metavar="FILE")
+        parser.add_option ("--output-file-m2", default="usrp_rx_m2.dat",
+                       help="write master data from second channel to FILE", metavar="FILE")
+        parser.add_option ("-p", "--output-file-s", default="usrp_rx_s.dat",
+                       help="write slave data to FILE", metavar="FILE")
+        parser.add_option ("--output-file-s2", default="usrp_rx_s2.dat",
+                       help="write slave data from second channel to FILE", metavar="FILE")
+        parser.add_option("-x", "--master-serialno", type="string", default=None, 
+                          help="Serial_no of the usrp which should be the MASTER (default= select any)")
+        (options, args) = parser.parse_args ()
+        if len(args) != 0:
+            parser.print_help()
+            raise SystemExit, 1
+
+        if options.freq is None:
+            parser.print_help()
+            sys.stderr.write('You must specify the frequency with -f FREQ\n');
+            raise SystemExit, 1
+
+        # build the graph
+        self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, 
+                                                  nchan=options.nchan )
+        self.um=self.multi.get_master_usrp()
+        self.us=self.multi.get_slave_usrp()
+
+        dst_m=gr.file_sink (gr.sizeof_gr_complex, options.output_file_m)
+        dst_s=gr.file_sink (gr.sizeof_gr_complex, options.output_file_s)
+        if options.nsamples is None:
+            self.connect((self.multi.get_master_source_c(),1),dst_m)
+            self.connect((self.multi.get_slave_source_c(),1),dst_s)
+        else:
+            head_m = gr.head(gr.sizeof_gr_complex, int(options.nsamples))
+            head_s = gr.head(gr.sizeof_gr_complex, int(options.nsamples))
+            self.connect((self.multi.get_master_source_c(),1),head_m,dst_m)
+            self.connect((self.multi.get_slave_source_c(),1),head_s,dst_s)
+
+        if(4==options.nchan):
+            dst_m2=gr.file_sink (gr.sizeof_gr_complex, options.output_file_m2)
+            dst_s2=gr.file_sink (gr.sizeof_gr_complex, options.output_file_s2)
+            if options.nsamples is None:
+                self.connect((self.multi.get_master_source_c(),2),dst_m2)
+                self.connect((self.multi.get_slave_source_c(),2),dst_s2) 
+            else:
+                head_m2 = gr.head(gr.sizeof_gr_complex, int(options.nsamples))
+                head_s2 = gr.head(gr.sizeof_gr_complex, int(options.nsamples))
+                self.connect((self.multi.get_master_source_c(),2),head_m2,dst_m2)
+                self.connect((self.multi.get_slave_source_c(),2),head_s2,dst_s2) 
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = usrp.pick_rx_subdevice(self.um)
+
+        if (options.nchan!=4):
+          mux=usrp.determine_rx_mux_value(self.um, options.rx_subdev_spec)
+          mux= (mux<<8 & 0xffffffff) | (mux & 0xff)
+          self.um.set_mux(mux)
+          self.us.set_mux(mux)
+
+        # determine the daughterboard subdevice we're using
+        self.subdevm = usrp.selected_subdev(self.um, options.rx_subdev_spec)
+        self.subdevs = usrp.selected_subdev(self.us, options.rx_subdev_spec)
+        print "Using MASTER RX d'board %s" % (self.subdevm.side_and_name(),)
+        print "Using SLAVE RX d'board %s" % (self.subdevs.side_and_name(),)
+        input_rate = self.um.adc_freq() / self.um.decim_rate()
+        print "USB sample rate %s" % (eng_notation.num_to_str(input_rate))
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdevm.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+        self.multi.set_gain_all_rx(options.gain)
+        result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq)
+        if not result:
+            sys.stderr.write('Failed to set frequency\n')
+            raise SystemExit, 1
+
+    def sync_usrps(self):
+        self.multi.sync()   
+       
+        
+if __name__ == '__main__':
+    fg=my_graph()
+    fg.start()
+    #time.sleep(0.5)
+    fg.sync_usrps() 
+    raw_input ('Press Enter to quit: ')
+    fg.stop()
+    #try:
+    #    fg.start()
+    #    fg.sync_usrps()
+    #except KeyboardInterrupt:
+    #    pass
diff --git a/gnuradio-examples/python/networking/measurement_slave.py b/gnuradio-examples/python/networking/measurement_slave.py
new file mode 100755
index 0000000000..2bc7c39c78
--- /dev/null
+++ b/gnuradio-examples/python/networking/measurement_slave.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+#
+# Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+import struct
+import socket
+import asyncore
+import sys
+import optparse
+import random
+from gnuradio.eng_option import eng_option
+import gnuradio.gr.gr_threading as _threading
+
+LOOP_TIMEOUT = 0.001
+BROADCAST_ADDR = '255.255.255.255'
+
+BROADCAST_PORT = 27010   # UDP
+CONTROL_PORT   = 27011   # TCP
+
+PKT_HEADER_SIZE = 4      # 32-bit int
+
+logfile = None
+
+def unpack_header(s):
+    (len,) = struct.unpack('!i', s)
+    return (len,)
+
+def pack_header(len):
+    return struct.pack('!i', len)
+
+
+class control_port_listener(asyncore.dispatcher):
+    def __init__(self, port=CONTROL_PORT, udp_socket=None, verbose=False):
+        """
+        @param port: TCP port to listen on.
+        @type port: int
+        """
+        asyncore.dispatcher.__init__(self)
+
+        self._verbose = verbose
+        self._udp_socket = udp_socket
+
+        host = ''                       # symbolic name for localhost
+        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.set_reuse_addr()
+
+        try:
+            self.bind((host, port))
+        except socket.error, err:
+            sys.stderr.write('Failed to bind to %s: %s\n' %
+                             ((host, port), os.strerror (err.args[0]),))
+            sys.exit(1)
+
+        self.listen(3)
+        
+    def handle_accept(self):
+        socket, addr = self.accept()
+        sys.stderr.write("handle_accept: %r\n" % (addr,))
+        if not(socket is None):
+            # instantiate a server
+            s = control_server(socket, addr, self._udp_socket, self._verbose)
+        
+
+class gr_dispatcher(asyncore.dispatcher):
+    def __init__(self, sock=None, map=None):
+        asyncore.dispatcher.__init__(self, sock=sock, map=map)
+
+    def read_packet(self):
+        """
+        Returns None or packet
+        """
+        s = self.recvall(PKT_HEADER_SIZE)
+        if s == '':
+            return None
+        
+        (payload_len,) = unpack_header(s)
+
+        payload_len = int(payload_len)
+        
+        if payload_len == 0:
+            payload = ''
+        else:
+            payload = self.recvall(payload_len)
+            if len(payload) != payload_len:
+                sys.stderr.write ('short recv, expected %d bytes, got %d\n' % (
+                    payload_len, len(payload)))
+                raise RuntimeError, "short recv"
+
+        return payload
+
+    def recvall(self, buffer_size):
+        result = ''
+        while len(result) < buffer_size:
+            data = self.recv(buffer_size - len(result))
+            if not data:
+                return ''
+            result += data
+        return result
+
+
+class pkt_receiver_thread(_threading.Thread):
+    def __init__(self, socket):
+        _threading.Thread.__init__(self)
+        self.setDaemon(1)
+        self.socket = socket
+        self.keep_running = True
+        self.start()
+
+    def run(self):
+        while self.keep_running:
+            pkt, sender = self.socket.recvfrom(10000)
+            if pkt:
+                if len(pkt) > 2:
+                    t = struct.unpack('!H', pkt[0:2])
+                    seqno = t[0]
+                else:
+                    seqno = -1
+                    
+                logfile.write('RCVD seqno %4d len %4d from %s\n' % (seqno, len(pkt), sender))
+                logfile.flush()
+
+
+class control_server(gr_dispatcher):
+    def __init__(self, socket, addr, udp_socket, verbose=False):
+        gr_dispatcher.__init__(self, sock=socket)
+        
+        self._udp_socket = udp_socket
+        self.verbose = verbose
+        self.setblocking(1)
+
+    def writable(self):
+        return False
+
+    def handle_read(self):
+        pkt = self.read_packet()
+        if pkt:
+            annotate = 'ANNOTATE'
+            if pkt.startswith(annotate):
+                logfile.write(pkt[len(annotate)+1:])
+                logfile.write('\n')
+                logfile.flush()
+            elif pkt.startswith('SEND'):
+                tokens = pkt.split()
+                if len(tokens) < 4:
+                    invalid_packet(pkt)
+                else:
+                    npkts = int(tokens[1])
+                    size = int(tokens[2])
+                    power = float(tokens[3])
+                    send_test_packets(self._udp_socket, npkts, size, power)
+            else:
+                invalid_packet(pkt)
+
+    def handle_close(self):
+        self.close()
+
+
+def invalid_packet(pkt):
+    sys.stderr.write('received unrecognized packet: %s\n' % (pkt,))
+
+
+def make_random_payload(size):
+    p = [0] * size
+    if 1:
+        for i in range(size):
+            p[i] = chr(random.randint(0, 255))
+    else:
+        for i in range(size):
+            p[i] = chr(i % 256)
+    return ''.join(p)
+
+
+def send_test_packets(udp_socket, npkts, size, power):
+    # we ignore power for now...
+    size = max(2, size)
+    payload = make_random_payload(size - 2)
+    for n in range(npkts):
+        pkt = struct.pack('!H', n) + payload
+        udp_socket.sendto(pkt, (BROADCAST_ADDR, BROADCAST_PORT))
+        #udp_socket.sendall(pkt)
+
+
+def open_udp_broadcast_socket(gr0_host_ip, port):
+    s  = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+#    s.bind((gr0_host_ip, port))
+    s.bind(('', port))
+    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+#    s.connect((BROADCAST_ADDR, port))
+    return s
+
+
+def main():
+    global logfile
+    
+    usage = 'usage: %prog [options] gr0-ip-addr'
+    parser = optparse.OptionParser (option_class=eng_option, usage=usage)
+    parser.add_option('-l', '--logfile', type='string', default=None,
+                      help="specify log file name [default=<stdout>]")
+    parser.add_option('-v', '--verbose', action="store_true", default=False,
+                      help="enable verbose diagnostics")
+
+    (options, args) = parser.parse_args ()
+    if len(args) != 1:
+        parser.print_help()
+        sys.exit(1)
+
+    gr0_ip_addr = args[0]
+    if options.logfile is None:
+        logfile = sys.stdout
+    else:
+        logfile = file(options.logfile, 'w')
+
+    udp_socket = open_udp_broadcast_socket(gr0_ip_addr, BROADCAST_PORT)
+    R = pkt_receiver_thread(udp_socket)
+    L = control_port_listener(CONTROL_PORT, udp_socket=udp_socket, verbose=options.verbose)
+    asyncore.loop(LOOP_TIMEOUT)
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/usrp/Makefile.am b/gnuradio-examples/python/usrp/Makefile.am
new file mode 100644
index 0000000000..32442d5cbe
--- /dev/null
+++ b/gnuradio-examples/python/usrp/Makefile.am
@@ -0,0 +1,52 @@
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+EXTRA_DIST = 					\
+	am_rcv.py				\
+	ayfabtu.py				\
+	benchmark_usb.py			\
+	fm_tx4.py				\
+	fsk_loopback.py				\
+	fsk_rx.py				\
+	fsk_tx.py				\
+	max_power.py				\
+	test_counting.py			\
+	test_dft_analysis.py			\
+	test_dft_synth.py			\
+	test_digital_loopback_counting.py	\
+	test_digital_loopback_lfsr.py		\
+	tvrx_am_rcv_gui.py			\
+	tvrx_tv_rcv.py				\
+	usrp_fft.py				\
+	usrp_fft_old.py				\
+	usrp_nbfm_ptt.py			\
+	usrp_nbfm_rcv.py			\
+	usrp_oscope.py				\
+	usrp_rx_cfile.py			\
+	usrp_rx_file.py				\
+	usrp_rx_nogui.py			\
+	usrp_siggen.py				\
+	usrp_wfm_rcv.py				\
+	usrp_wfm_rcv_nogui.py			\
+	usrp_wfm_rcv2_nogui.py			\
+	usrp_wfm_rcv_pll.py			\
+	usrp_wxapt_rcv.py			\
+	wfm_rcv_file.py				
diff --git a/gnuradio-examples/python/usrp/am_rcv.py b/gnuradio-examples/python/usrp/am_rcv.py
new file mode 100755
index 0000000000..2908dcbf54
--- /dev/null
+++ b/gnuradio-examples/python/usrp/am_rcv.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, eng_notation
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+import math
+
+from gnuradio.wxgui import stdgui, fftsink
+import wx
+
+class am_rx_graph (stdgui.gui_flow_graph):
+    def __init__(self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+
+        station = parseargs(argv[1:])
+        offset_freq = 30e3
+        IF_freq = offset_freq - station
+
+        adc_rate = 64e6
+        usrp_decim = 250
+        if_rate = adc_rate / usrp_decim               # 256 kHz
+        if_decim = 4
+        demod_rate = if_rate / if_decim        # 64 kHz
+        audio_decimation = 2
+        audio_rate = demod_rate / audio_decimation  # 16 kHz
+        
+        # usrp is data source
+        src = usrp.source_c (0, usrp_decim)
+        src.set_rx_freq (0, IF_freq)
+        actual_IF_freq =src.rx_freq(0)
+        actual_offset = actual_IF_freq + station
+        
+        #print actual_IF_freq
+        #print actual_offset
+ 
+        src.set_pga(0,20)
+        # sound card as final sink
+        audio_sink = audio.sink (int (audio_rate))
+        
+        channel_coeffs = \
+                       gr.firdes.low_pass (1.0,           # gain
+                                           if_rate,   # sampling rate
+                                           9e3,         # low pass cutoff freq
+                                           10e3,         # width of trans. band
+                                           gr.firdes.WIN_HANN)
+
+        ddc =  gr.freq_xlating_fir_filter_ccf (if_decim,channel_coeffs,-actual_offset,if_rate)
+
+        magblock = gr.complex_to_mag()
+        volumecontrol = gr.multiply_const_ff(.003)
+
+        # Deemphasis.  Is this necessary on AM?
+        TAU  = 75e-6  # 75us in US, 50us in EUR
+        fftaps = [ 1 - math.exp(-1/TAU/if_rate), 0]
+        fbtaps= [ 0 , math.exp(-1/TAU/if_rate) ]
+        
+        deemph = gr.iir_filter_ffd(fftaps,fbtaps)
+
+        # compute FIR filter taps for audio filter
+        width_of_transition_band = audio_rate / 8
+        audio_coeffs = gr.firdes.low_pass (1.0,            # gain
+                                           if_rate,      # sampling rate
+                                           9e3,         #audio_rate/2 - width_of_transition_band,
+                                           4e3,         # width_of_transition_band,
+                                           gr.firdes.WIN_HANN)
+        
+        # input: float; output: float
+        audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
+
+
+
+        
+        print len(channel_coeffs)
+        print len(audio_coeffs)
+        
+        # now wire it all together
+        self.connect (src, ddc)
+        self.connect (ddc, magblock)
+        self.connect (magblock, volumecontrol)
+        self.connect (volumecontrol,deemph)
+        self.connect (deemph,audio_filter)
+        self.connect (audio_filter, (audio_sink, 0))
+
+        if 1:
+            pre_demod = fftsink.fft_sink_c (self, panel, title="Pre-Demodulation", fft_size=128, sample_rate=if_rate)
+            self.connect (src, pre_demod)
+            vbox.Add (pre_demod.win, 1, wx.EXPAND)
+
+        if 0:
+            post_demod = fftsink.fft_sink_c (self, panel, title="Post Demodulation", fft_size=256, sample_rate=demod_rate)
+            self.connect (ddc, post_demod)
+            vbox.Add (post_demod.win, 1, wx.EXPAND)
+
+        if 0:
+            post_filt = fftsink.fft_sink_f (self, panel, title="Post Filter", fft_size=512, sample_rate=audio_rate)
+            self.connect (magblock,post_filt)
+            vbox.Add (post_filt.win, 1, wx.EXPAND)
+        
+def parseargs (args):
+    nargs = len (args)
+    if nargs == 1:
+        freq1 = float (args[0]) * 1e3
+    else:
+        sys.stderr.write ('usage: am_rcv freq1\n')
+        sys.exit (1)
+
+    return freq1
+
+if __name__ == '__main__':
+    app = stdgui.stdapp (am_rx_graph, "AM RX")
+    app.MainLoop ()
+
diff --git a/gnuradio-examples/python/usrp/ayfabtu.dat b/gnuradio-examples/python/usrp/ayfabtu.dat
new file mode 100644
index 0000000000..5c65cf4833
Binary files /dev/null and b/gnuradio-examples/python/usrp/ayfabtu.dat differ
diff --git a/gnuradio-examples/python/usrp/ayfabtu.py b/gnuradio-examples/python/usrp/ayfabtu.py
new file mode 100755
index 0000000000..7647e93b8a
--- /dev/null
+++ b/gnuradio-examples/python/usrp/ayfabtu.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+#
+# All Your Frequencies are Belong to Us!
+#
+#   Transmit NBFM message on 25 channels simultaneously!
+#
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio import blks
+from gnuradio import optfir
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import math
+import sys
+import random
+
+from gnuradio.wxgui import stdgui, fftsink
+import wx
+
+
+def make_random_complex_tuple(L):
+    result = []
+    for x in range(L):
+        result.append(complex(random.gauss(0, 1),random.gauss(0, 1)))
+                      
+    return tuple(result)
+
+def random_noise_c():
+    src = gr.vector_source_c(make_random_complex_tuple(32*1024), True)
+    return src
+
+
+def plot_taps(taps, sample_rate=2):
+    return gru.gnuplot_freqz (gru.freqz (taps, 1), sample_rate)
+    
+
+class ayfabtu_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option ("-c", "--duc-freq", type="eng_float", default=29.325e6,
+                           help="set Tx ddc frequency to FREQ", metavar="FREQ")
+        (options, args) = parser.parse_args ()
+
+        nchan = 25
+        IF_GAIN = 80000
+        AUDIO_GAIN = 100
+        
+        self.dac_rate = 128e6
+        self.usrp_interp = 256
+        self.usrp_rate = self.dac_rate / self.usrp_interp    # 500 kS/s
+        self.audio_rate = 32000                              # 32 kS/s
+
+        self.audio_src = gr.file_source(gr.sizeof_float, "ayfabtu.dat", True)
+
+        ahp_taps = gr.firdes.high_pass(1,     # gain
+                                       32e3,  # Fs
+                                       300,   # cutoff
+                                       600,   # trans width
+                                       gr.firdes.WIN_HANN)
+        self.audio_hp = gr.fir_filter_fff(1, ahp_taps)
+
+        self.audio_gain = gr.multiply_const_ff(AUDIO_GAIN)
+
+        null_src = gr.null_source(gr.sizeof_gr_complex)
+        #noise_src = gr.noise_source_c(gr.GR_UNIFORM, 1, 0)
+        noise_src = random_noise_c()
+
+        if 0:
+            artaps = optfir.low_pass(1,       # gain
+                                     2,       # Fs
+                                     .75/32,  # freq1
+                                     1.0/32,  # freq2
+                                     1,       # pb ripple in dB
+                                     50,      # stopband atten in dB
+                                     2)       # + extra taps
+        else:
+            artaps = gr.firdes.low_pass(1,      # gain
+                                        32e3*15,# Fs
+                                        2.7e3,  # cutoff
+                                         .3e3,  # trans width
+                                        gr.firdes.WIN_HANN)
+        print "len(artaps) =", len(artaps)
+        self.audio_resampler = blks.rational_resampler_fff(self, 15, 32, artaps)
+
+        self.fm_mod = blks.nbfm_tx(self, 15000, 15000, max_dev=4.5e3)
+
+
+        fbtaps = gr.firdes.low_pass(1,                # gain
+                                    25*15e3,          # rate
+                                    13e3,             # cutoff
+                                    2e3,              # trans width
+                                    gr.firdes.WIN_HANN)
+        print "len(fbtabs) =", len(fbtaps)
+        #self.plot = plot_taps(fbtaps, 25*15e3)
+        self.filter_bank = blks.synthesis_filterbank(self, nchan, fbtaps)
+        
+        self.if_gain = gr.multiply_const_cc(IF_GAIN)
+
+        if 0:
+            ifrtaps = optfir.low_pass(1,
+                                      2,       # Fs
+                                      .75/3,   # freq1
+                                      1.0/3,   # freq2
+                                      1,       # pb ripple in dB
+                                      50,      # stopband atten in dB
+                                      2)       # + extra taps
+        else:
+            ifrtaps = gr.firdes.low_pass(1,
+                                         2,       # Fs
+                                         .75/3,   # freq1
+                                         .25/3,   # trans width
+                                         gr.firdes.WIN_HANN)
+
+
+        print "len(ifrtaps) =", len(ifrtaps)
+        self.if_resampler = blks.rational_resampler_ccf(self, 4, 3, ifrtaps)
+
+
+        self.u = usrp.sink_c(0, 256)
+        self.u.set_tx_freq(0, options.duc_freq)
+        self.u.set_pga(0, self.u.pga_max())
+
+        # wire it all together
+        
+        self.connect(self.audio_src, self.audio_hp, self.audio_gain,
+                     self.audio_resampler, self.fm_mod)
+
+        null_sink = gr.null_sink(gr.sizeof_gr_complex)
+
+        for i in range(nchan):
+            if True or i == 0:
+                self.connect(self.fm_mod, (self.filter_bank, i))
+            else:
+                self.connect(null_src, (self.filter_bank, i))
+
+        self.connect(self.filter_bank, self.if_gain, self.if_resampler, self.u)
+        
+
+def main ():
+    app = stdgui.stdapp (ayfabtu_graph, "All Your Frequency Are Belong to Us")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/benchmark_usb.py b/gnuradio-examples/python/usrp/benchmark_usb.py
new file mode 100755
index 0000000000..8418f50625
--- /dev/null
+++ b/gnuradio-examples/python/usrp/benchmark_usb.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+"""
+Benchmark the USB/USRP throughput.  Finds the maximum full-duplex speed
+the USRP/USB combination can sustain without errors.
+
+This program does not currently give reliable results.  Sorry about that...
+"""
+
+from gnuradio import gr
+from gnuradio import usrp
+from gnuradio import eng_notation
+
+import sys
+
+def run_test (usb_throughput, verbose):
+    # usb_throughput is in bytes/sec.
+    #
+    # Returns True or False
+    
+    nsec = 1
+    stream_length = int (usb_throughput/2 * nsec)   # length of stream to examine
+
+    adc_freq =  64e6
+    dac_freq = 128e6
+    sizeof_sample = 2 * gr.sizeof_short
+
+    usb_throughput_in_samples = usb_throughput / sizeof_sample
+
+    # allocate usb throughput 50/50 between Tx and Rx
+
+    tx_interp = int (dac_freq) / int (usb_throughput_in_samples / 2)
+    rx_decim  = int (adc_freq) / int (usb_throughput_in_samples / 2)
+
+    # print "tx_interp =", tx_interp, "rx_decim =", rx_decim
+    assert (tx_interp == 2 * rx_decim)
+    
+    fg = gr.flow_graph ()
+
+    # Build the Tx pipeline
+    data_src = gr.lfsr_32k_source_s ()
+    src_head = gr.head (gr.sizeof_short, int (stream_length * 2))
+    usrp_tx = usrp.sink_s (0, tx_interp)
+    fg.connect (data_src, src_head, usrp_tx)
+
+    # and the Rx pipeline
+    usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK)
+    head = gr.head (gr.sizeof_short, stream_length)
+    check = gr.check_lfsr_32k_s ()
+    fg.connect (usrp_rx, head, check)
+
+    fg.run ()
+
+    ntotal = check.ntotal ()
+    nright = check.nright ()
+    runlength = check.runlength ()
+
+    if verbose:
+        print "usb_throughput =", eng_notation.num_to_str (usb_throughput)
+        print "ntotal    =", ntotal
+        print "nright    =", nright
+        print "runlength =", runlength
+        print "delta     =", ntotal - runlength
+
+    return runlength >= stream_length - 80000
+    
+def main ():
+    verbose = True
+    best_rate = 0
+    usb_rate = [ 2e6, 4e6, 8e6, 16e6, 32e6 ]
+    #usb_rate = [ 32e6, 32e6, 32e6, 32e6, 32e6 ]
+    # usb_rate.reverse ()
+    for rate in usb_rate:
+        sys.stdout.write ("Testing %sB/sec... " % (eng_notation.num_to_str (rate)))
+        sys.stdout.flush ()
+        ok = run_test (rate, verbose)
+        if ok:
+            best_rate = max (best_rate, rate)
+            sys.stdout.write ("OK\n")
+        else:
+            sys.stdout.write ("FAILED\n")
+
+    print "Max USB/USRP throughput = %sB/sec" % (eng_notation.num_to_str (best_rate),)
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/dsb_tx.py b/gnuradio-examples/python/usrp/dsb_tx.py
new file mode 100755
index 0000000000..df65761cd4
--- /dev/null
+++ b/gnuradio-examples/python/usrp/dsb_tx.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, eng_notation
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+
+def build_graph (cordic_freq):
+
+    audio_rate = 32000
+    sw_interp = 4
+    usrp_interp = 1000
+    audio_file = "/home/eb/demo/testing-audio.dat"
+    
+    fg = gr.flow_graph ()
+
+    src = gr.file_source (gr.sizeof_float, audio_file, True)
+    gain = gr.multiply_const_ff (10000)
+
+    interp = gr.interp_fir_filter_fff (sw_interp, (1, 1, 1, 1))
+
+    f2c = gr.float_to_complex ()
+    
+    u = usrp.sink_c (0, usrp_interp)
+    u.set_tx_freq (0, cordic_freq)
+
+    fg.connect (src, gain)
+    fg.connect (gain, interp)
+    fg.connect (interp, (f2c, 0))
+    fg.connect (interp, (f2c, 1))
+    fg.connect (f2c, u)
+
+    return fg
+
+def main ():
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option ("-c", "--cordic-freq", type="eng_float", default=10e6,
+                       help="set Tx cordic frequency to FREQ", metavar="FREQ")
+    (options, args) = parser.parse_args ()
+
+    print "cordic_freq = %s" % (eng_notation.num_to_str (options.cordic_freq))
+    fg = build_graph (options.cordic_freq)
+    
+    fg.start ()
+    raw_input ('Press Enter to quit: ')
+    fg.stop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/flexrf_debug.py b/gnuradio-examples/python/usrp/flexrf_debug.py
new file mode 100755
index 0000000000..70c6309602
--- /dev/null
+++ b/gnuradio-examples/python/usrp/flexrf_debug.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink, scopesink, slider
+from optparse import OptionParser
+import wx
+
+class app_flow_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+
+        self.frame = frame
+        self.panel = panel
+        
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option ("-d", "--decim", type="int", default=8,
+                           help="set fgpa decimation rate to DECIM")
+        parser.add_option ("-c", "--ddc-freq", type="eng_float", default=0,
+                           help="set Digital downconverter frequency to FREQ", metavar="FREQ")
+        parser.add_option ("-f", "--freq", type="eng_float", default=950e6,
+                           help="set RF downconverter frequency to FREQ", metavar="FREQ")
+        parser.add_option ("-m", "--mux", type="intx", default=0x32103210,
+                           help="set fpga FR_RX_MUX register to MUX")
+        parser.add_option ("-g", "--gain", type="eng_float", default=0,
+                           help="set Rx PGA gain in dB (default 0 dB)")
+        (options, args) = parser.parse_args ()
+
+        self.u = usrp.source_c (0, options.decim, 1, gru.hexint(options.mux), 0)
+        
+        self.u.set_verbose (0)
+        
+        input_rate = self.u.adc_freq () / self.u.decim_rate ()
+
+        block = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate)
+        self.connect (self.u, block)
+        vbox.Add (block.win, 10, wx.EXPAND)
+
+	if 0:
+            c2f_1 = gr.complex_to_float ()
+            scope = scopesink.scope_sink_f (self, panel, "Rx Data", input_rate)
+            vbox.Add (scope.win, 6, wx.EXPAND)
+
+            self.connect (self.u,c2f_1)
+            self.connect ((c2f_1, 0), (scope, 0))
+            self.connect ((c2f_1, 1), (scope, 1))
+
+        if 0:
+            rms_complex = gr.rms_cf(.0001)
+            rms_i = gr.rms_ff(.0001)
+            rms_q = gr.rms_ff(.0001)
+            
+            self.connect(self.u,rms_complex)
+            self.connect((c2f_1,0),rms_i)
+            self.connect((c2f_1,1),rms_q)
+            
+            ns1 = gr.null_sink(4)
+            ns2 = gr.null_sink(4)
+            ns3 = gr.null_sink(4)
+            
+            self.connect(rms_complex,ns1)
+            self.connect(rms_i,ns2)
+            self.connect(rms_q,ns3)
+
+        # sliders
+
+        #vbox.Add(slider.slider(panel, 0, 104, self.set_gain), 1, wx.ALIGN_CENTER)
+
+        #vbox.Add(slider.slider(panel, 0, 4095, self.set_gain_gc1), 1, wx.ALIGN_CENTER)
+        #vbox.Add(slider.slider(panel, 0, 31, self.set_gain_gc2), 1, wx.ALIGN_CENTER)
+        #vbox.Add(slider.slider(panel, 0, 1, self.set_gain_dl), 1, wx.ALIGN_CENTER)
+        #vbox.Add(slider.slider(panel, 0, 200, self.set_gain_i), 1, wx.ALIGN_CENTER)
+        #vbox.Add(slider.slider(panel, 0, 200, self.set_gain_q), 1, wx.ALIGN_CENTER)
+
+        self.offset = 0
+        #vbox.Add(slider.slider(panel, -200, 200, self.set_offset_i), 1, wx.ALIGN_CENTER)
+        #vbox.Add(slider.slider(panel, -200, 200, self.set_offset_q), 1, wx.ALIGN_CENTER)
+
+        vbox.Add(slider.slider(panel, 380, 480, self.set_rf_freq), 1, wx.EXPAND|wx.ALIGN_CENTER)
+        vbox.Add(slider.slider(panel, -32000, +32000, self.set_if_freq), 1, wx.EXPAND|wx.ALIGN_CENTER)
+        vbox.Add(slider.slider(panel, 0, 4095, self.set_gain), 1, wx.EXPAND|wx.ALIGN_CENTER)
+
+        # build small control area at bottom
+        hbox = wx.BoxSizer (wx.HORIZONTAL)
+        hbox.Add ((1, 1), 1, wx.EXPAND)
+        hbox.Add (wx.StaticText (panel, -1, "Set ddc freq: "), 0, wx.ALIGN_CENTER)
+        self.tc_freq = wx.TextCtrl (panel, -1, "", style=wx.TE_PROCESS_ENTER)
+        hbox.Add (self.tc_freq, 0, wx.ALIGN_CENTER)
+        wx.EVT_TEXT_ENTER (self.tc_freq, self.tc_freq.GetId(), self.handle_text_enter)
+        hbox.Add ((1, 1), 1, wx.EXPAND)
+        # add it to the main vbox
+        vbox.Add (hbox, 0, wx.EXPAND)
+
+        self.update_status_bar ()
+
+    def set_rf_freq (self,freq):
+        (success,actual_freq) = self.set_freq(1e6*freq)
+        if not success:
+            print "Failed on ",freq
+    def set_if_freq (self,freq):
+        self.u.set_rx_freq(0,freq*1e3)
+            
+    def set_gain (self,gain):
+        self.rfrx.set_gain(gain)
+
+    def set_gain_i (self,gain):
+        self.u.set_pga(0,gain/10.0)
+    def set_gain_q (self,gain):
+        self.u.set_pga(1,gain/10.0)
+
+    def set_offset_i(self,offset):
+        self.offset = (self.offset & 0x0000ffff) | ((offset&0xffff)<<16)
+        self.u._write_fpga_reg (3,self.offset)
+
+    def set_offset_q(self,offset):
+        self.offset = (self.offset & 0xffff0000) | (offset&0xffff)
+        self.u._write_fpga_reg (3,self.offset)
+
+    def handle_text_enter (self, event):
+        str = event.GetString ()
+        self.tc_freq.Clear ()
+        self.u.set_rx_freq (0, eng_notation.str_to_num (str))
+        self.update_status_bar ()
+
+    def update_status_bar (self):
+        ddc_freq = self.u.rx_freq (0)
+        decim_rate = self.u.decim_rate ()
+        sample_rate = self.u.adc_freq () / decim_rate
+        msg = "decim: %d  %sS/s  DDC: %s" % (
+            decim_rate,
+            eng_notation.num_to_str (sample_rate),
+            eng_notation.num_to_str (ddc_freq))
+            
+        self.frame.GetStatusBar().SetStatusText (msg, 1)
+
+    def set_gain(self,gain):
+        assert gain>=0 and gain<4096
+        self.u.write_aux_dac(0,0,int(gain))
+        
+def main ():
+    app = stdgui.stdapp (app_flow_graph, "USRP FFT")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
+
+
diff --git a/gnuradio-examples/python/usrp/flexrf_siggen.py b/gnuradio-examples/python/usrp/flexrf_siggen.py
new file mode 100755
index 0000000000..6a59148b88
--- /dev/null
+++ b/gnuradio-examples/python/usrp/flexrf_siggen.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+from gnuradio.wxgui import stdgui, slider
+import wx
+
+class flex_siggen (stdgui.gui_flow_graph):
+    __slots__ = ['interp', 'waveform_type', 'waveform_ampl',
+                 'waveform_freq', 'waveform_offset', 'fg', 'usrp',
+                 'siggen', 'noisegen', 'src', 'file_sink' ]
+
+    def __init__ (self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+        
+        self.frame = frame
+        self.panel = panel
+
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option ("-a", "--amplitude", type="int", default=32000,
+                           help="amplitude")
+        parser.add_option ("-i", "--interp", type="int", default=64,
+                           help="set fpga interpolation rate to INTERP")
+        parser.add_option ("-n", "--nchannels", type="int", default=1,
+                           help="set number of output channels to NCHANNELS")
+        (options, args) = parser.parse_args ()
+
+        self.waveform_type = gr.GR_CONST_WAVE
+        self.waveform_ampl = options.amplitude
+        self.waveform_freq = 100.12345e3
+        self.waveform_offset = 0
+
+        self.interp = options.interp
+        self._instantiate_blocks ()
+        self.usrp.set_nchannels (options.nchannels)
+        
+        self.dboard=self.usrp.db[0][0]
+        
+        self.set_waveform_type (self.waveform_type)
+        vbox.Add(slider.slider(panel, 390, 510, self.set_rf_freq), 1, wx.EXPAND|wx.ALIGN_CENTER)
+        vbox.Add(slider.slider(panel, -45000, +45000, self.set_if_freq), 1, wx.EXPAND|wx.ALIGN_CENTER)
+        #vbox.Add(slider.slider(panel, 0, 4095, self.set_gain), 1, wx.EXPAND|wx.ALIGN_CENTER)
+        
+    def usb_freq (self):
+        return self.usrp.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_if_freq (self, freq):
+        self.if_freq = freq
+        self.usrp.set_tx_freq (0,freq*1e3)
+        
+    def set_rf_freq (self, freq):
+        self.rf_freq = freq
+        (success,actual_freq) = self.dboard.set_freq (freq*1e6)
+        if not success:
+            print "Failed on ", 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.usrp.set_interp_rate (interp)
+
+    def set_duc_freq (self, freq):
+        self.usrp.set_tx_freq (0, freq)
+        
+    def _instantiate_blocks (self):
+        self.src = None
+        self.usrp = 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)
+        print "done"
+        
+    def _configure_graph (self, type):
+        was_running = self.is_running ()
+        if was_running:
+            self.stop ()
+        self.disconnect_all ()
+        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
+            self.connect (self.siggen, self.usrp)
+            self.siggen.set_waveform (type)
+            self.src = self.siggen
+        elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN:
+            self.connect (self.noisegen, self.usrp)
+            self.noisegen.set_type (type)
+            self.src = self.noisegen
+        else:
+            raise ValueError, type
+        if was_running:
+            self.start ()
+
+
+if __name__ == '__main__':
+    parser = OptionParser (option_class=eng_option)
+    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 ("-f", "--freq", type="eng_float", default=100e3,
+                       help="set waveform frequency to FREQ")
+    parser.add_option ("-r", "--rf-freq", type="eng_float", default=910e6,
+                       help="set waveform frequency to FREQ")
+    parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3,
+                       help="set waveform amplitude to AMPLITUDE", metavar="AMPL")
+    parser.add_option ("-o", "--offset", type="eng_float", default=0,
+                       help="set waveform offset to OFFSET")
+    parser.add_option ("-c", "--duc-freq", type="eng_float", default=0,
+                       help="set Tx DUC frequency to FREQ", metavar="FREQ")
+    parser.add_option ("-m", "--mux", type="intx", default=0x98,
+                       help="set output mux register")
+    
+    app = stdgui.stdapp (flex_siggen, "USRP FlexRF Siggen")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/fm_tx4.py b/gnuradio-examples/python/usrp/fm_tx4.py
new file mode 100755
index 0000000000..a9201b3f4d
--- /dev/null
+++ b/gnuradio-examples/python/usrp/fm_tx4.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+"""
+Transmit N simultaneous narrow band FM signals.
+
+They will be centered at the frequency specified on the command line,
+and will spaced at 25kHz steps from there.
+
+The program opens N files with names audio-N.dat where N is in [0,7].
+These files should contain floating point audio samples in the range [-1,1]
+sampled at 32kS/sec.  You can create files like this using
+audio_to_file.py
+"""
+
+from gnuradio import gr, eng_notation
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import usrp_dbid
+import math
+import sys
+
+from gnuradio.wxgui import stdgui, fftsink
+from gnuradio import tx_debug_gui
+import wx
+
+
+########################################################
+# instantiate one transmit chain for each call
+
+class pipeline(gr.hier_block):
+    def __init__(self, fg, filename, lo_freq, audio_rate, if_rate):
+
+        src = gr.file_source (gr.sizeof_float, filename, True)
+        fmtx = blks.nbfm_tx (fg, audio_rate, if_rate,
+                             max_dev=5e3, tau=75e-6)
+        
+        # Local oscillator
+        lo = gr.sig_source_c (if_rate,        # sample rate
+                              gr.GR_SIN_WAVE, # waveform type
+                              lo_freq,        #frequency
+                              1.0,            # amplitude
+                              0)              # DC Offset
+        mixer = gr.multiply_cc ()
+    
+        fg.connect (src, fmtx, (mixer, 0))
+        fg.connect (lo, (mixer, 1))
+
+        gr.hier_block.__init__(self, fg, src, mixer)
+
+
+
+class fm_tx_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        MAX_CHANNELS = 7
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Tx side A or B")
+        parser.add_option("-f", "--freq", type="eng_float", default=None,
+                           help="set Tx frequency to FREQ [required]", metavar="FREQ")
+        parser.add_option("-n", "--nchannels", type="int", default=4,
+                           help="number of Tx channels [1,4]")
+        parser.add_option("","--debug", action="store_true", default=False,
+                          help="Launch Tx debugger")
+        (options, args) = parser.parse_args ()
+
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+
+        if options.nchannels < 1 or options.nchannels > MAX_CHANNELS:
+            sys.stderr.write ("fm_tx4: nchannels out of range.  Must be in [1,%d]\n" % MAX_CHANNELS)
+            sys.exit(1)
+        
+        if options.freq is None:
+            sys.stderr.write("fm_tx4: must specify frequency with -f FREQ\n")
+            parser.print_help()
+            sys.exit(1)
+
+        # ----------------------------------------------------------------
+        # Set up constants and parameters
+
+        self.u = usrp.sink_c ()       # the USRP sink (consumes samples)
+
+        self.dac_rate = self.u.dac_rate()                    # 128 MS/s
+        self.usrp_interp = 400
+        self.u.set_interp_rate(self.usrp_interp)
+        self.usrp_rate = self.dac_rate / self.usrp_interp    # 320 kS/s
+        self.sw_interp = 10
+        self.audio_rate = self.usrp_rate / self.sw_interp    # 32 kS/s
+
+        # determine the daughterboard subdevice we're using
+        if options.tx_subdev_spec is None:
+            options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
+
+        m = usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec)
+        #print "mux = %#04x" % (m,)
+        self.u.set_mux(m)
+        self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec)
+        print "Using TX d'board %s" % (self.subdev.side_and_name(),)
+
+        self.subdev.set_gain(self.subdev.gain_range()[1])    # set max Tx gain
+        self.set_freq(options.freq)
+        self.subdev.set_enable(True)                         # enable transmitter
+
+        sum = gr.add_cc ()
+
+        # Instantiate N NBFM channels
+        step = 25e3
+        offset = (0 * step, 1 * step, -1 * step, 2 * step, -2 * step, 3 * step, -3 * step)
+        for i in range (options.nchannels):
+            t = pipeline (self, "audio-%d.dat" % (i % 4), offset[i],
+                          self.audio_rate, self.usrp_rate)
+            self.connect (t, (sum, i))
+
+        gain = gr.multiply_const_cc (4000.0 / options.nchannels)
+
+        # connect it all
+        self.connect (sum, gain)
+        self.connect (gain, self.u)
+
+        # plot an FFT to verify we are sending what we want
+        if 1:
+            post_mod = fftsink.fft_sink_c(self, panel, title="Post Modulation",
+                                          fft_size=512, sample_rate=self.usrp_rate,
+                                          y_per_div=20, ref_level=40)
+            self.connect (sum, post_mod)
+            vbox.Add (post_mod.win, 1, wx.EXPAND)
+            
+
+        if options.debug:
+            self.debugger = tx_debug_gui.tx_debug_gui(self.subdev)
+            self.debugger.Show(True)
+
+
+    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.  Finally, we feed
+        any residual_freq to the s/w freq translater.
+        """
+
+        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
+            
+            # Could use residual_freq in s/w freq translator
+            return True
+
+        return False
+
+def main ():
+    app = stdgui.stdapp (fm_tx_graph, "Multichannel FM Tx")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py b/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py
new file mode 100755
index 0000000000..1cb161018f
--- /dev/null
+++ b/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+"""
+Transmit 2 signals, one out each daughterboard.
+
+Outputs SSB (USB) signals on side A and side B at frequencies
+specified on command line.
+
+Side A is 600 Hz tone.
+Side B is 350 + 440 Hz tones.
+"""
+
+from gnuradio import gr
+from gnuradio.eng_notation import num_to_str, str_to_num
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import usrp_dbid
+import math
+import sys
+
+
+class example_signal_0(gr.hier_block):
+    """
+    Sinusoid at 600 Hz.
+    """
+    def __init__(self, fg, sample_rate):
+
+        src = gr.sig_source_c (sample_rate,    # sample rate
+                               gr.GR_SIN_WAVE, # waveform type
+                               600,            # frequency
+                               1.0,            # amplitude
+                               0)              # DC Offset
+    
+        gr.hier_block.__init__(self, fg, None, src)
+
+
+class example_signal_1(gr.hier_block):
+    """
+    North American dial tone (350 + 440 Hz).
+    """
+    def __init__(self, fg, sample_rate):
+
+        src0 = gr.sig_source_c (sample_rate,    # sample rate
+                                gr.GR_SIN_WAVE, # waveform type
+                                350,            # frequency
+                                1.0,            # amplitude
+                                0)              # DC Offset
+
+        src1 = gr.sig_source_c (sample_rate,    # sample rate
+                                gr.GR_SIN_WAVE, # waveform type
+                                440,            # frequency
+                                1.0,            # amplitude
+                                0)              # DC Offset
+        sum = gr.add_cc()
+        fg.connect(src0, (sum, 0))
+        fg.connect(src1, (sum, 1))
+        
+        gr.hier_block.__init__(self, fg, None, sum)
+    
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__ (self)
+
+        usage="%prog: [options] side-A-tx-freq side-B-tx-freq"
+        parser = OptionParser (option_class=eng_option, usage=usage)
+        (options, args) = parser.parse_args ()
+
+        if len(args) != 2:
+            parser.print_help()
+            raise SystemExit
+        else:
+            freq0 = str_to_num(args[0])
+            freq1 = str_to_num(args[1])
+
+        # ----------------------------------------------------------------
+        # Set up USRP to transmit on both daughterboards
+
+        self.u = usrp.sink_c(nchan=2)          # say we want two channels
+
+        self.dac_rate = self.u.dac_rate()                    # 128 MS/s
+        self.usrp_interp = 400
+        self.u.set_interp_rate(self.usrp_interp)
+        self.usrp_rate = self.dac_rate / self.usrp_interp    # 320 kS/s
+
+        # we're using both daughterboard slots, thus subdev is a 2-tuple
+        self.subdev = (self.u.db[0][0], self.u.db[1][0])
+        print "Using TX d'board %s" % (self.subdev[0].side_and_name(),)
+        print "Using TX d'board %s" % (self.subdev[1].side_and_name(),)
+        
+        # set up the Tx mux so that
+        #  channel 0 goes to Slot A I&Q and channel 1 to Slot B I&Q
+        self.u.set_mux(0xba98)
+
+        self.subdev[0].set_gain(self.subdev[0].gain_range()[1])    # set max Tx gain
+        self.subdev[1].set_gain(self.subdev[1].gain_range()[1])    # set max Tx gain
+
+        self.set_freq(0, freq0)
+        self.set_freq(1, freq1)
+        self.subdev[0].set_enable(True)             # enable transmitter
+        self.subdev[1].set_enable(True)             # enable transmitter
+
+        # ----------------------------------------------------------------
+        # build two signal sources, interleave them, amplify and connect them to usrp
+
+        sig0 = example_signal_0(self, self.usrp_rate)
+        sig1 = example_signal_1(self, self.usrp_rate)
+
+        intl = gr.interleave(gr.sizeof_gr_complex)
+        self.connect(sig0, (intl, 0))
+        self.connect(sig1, (intl, 1))
+
+        # apply some gain
+        if_gain = 10000
+        ifamp = gr.multiply_const_cc(if_gain)
+        
+        # and wire them up
+        self.connect(intl, ifamp, self.u)
+        
+
+    def set_freq(self, side, target_freq):
+        """
+        Set the center frequency we're interested in.
+
+        @param side: 0 = side A, 1 = side B
+        @param target_freq: frequency in Hz
+        @rtype: 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.
+        """
+
+        print "Tuning side %s to %sHz" % (("A", "B")[side], num_to_str(target_freq))
+        r = self.u.tune(self.subdev[side]._which, self.subdev[side], target_freq)
+        if r:
+            print "  r.baseband_freq =", num_to_str(r.baseband_freq)
+            print "  r.dxc_freq      =", num_to_str(r.dxc_freq)
+            print "  r.residual_freq =", num_to_str(r.residual_freq)
+            print "  r.inverted      =", r.inverted
+            print "  OK"
+            return True
+
+        else:
+            print "  Failed!"
+            
+        return False
+
+
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/usrp/max_power.py b/gnuradio-examples/python/usrp/max_power.py
new file mode 100755
index 0000000000..b4ad86b092
--- /dev/null
+++ b/gnuradio-examples/python/usrp/max_power.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+"""
+Setup USRP for maximum power consumption.
+"""
+
+
+from gnuradio import gr
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+def ramp_source (fg):
+    period = 2**16
+    src = gr.vector_source_s (range (-period/2, period/2, 1), True)
+    return src
+
+def build_graph (tx_enable, rx_enable):
+    max_usb_rate = 8e6                  # 8 MS/sec
+    dac_freq = 128e6
+    adc_freq =  64e6
+    
+    tx_nchan = 2
+    tx_mux = 0x0000ba98
+    tx_interp =  int (dac_freq / (max_usb_rate/2 * tx_nchan)) # 16
+    
+    rx_nchan = 2
+    rx_mux = 0x00003210
+    rx_decim = int ((adc_freq * rx_nchan) / (max_usb_rate/2)) # 32
+    
+    fg = gr.flow_graph ()
+
+    if tx_enable:
+        tx_src0 = gr.sig_source_c (dac_freq/tx_interp, gr.GR_CONST_WAVE, 0, 16e3, 0)
+        usrp_tx = usrp.sink_c (0, tx_interp, tx_nchan, tx_mux)
+        usrp_tx.set_tx_freq (0, 10e6)
+        usrp_tx.set_tx_freq (1,  9e6)
+        fg.connect (tx_src0, usrp_tx)
+
+    if rx_enable:
+        usrp_rx = usrp.source_c (0, rx_decim, rx_nchan, rx_mux)
+        usrp_rx.set_rx_freq (0, 5.5e6)
+        usrp_rx.set_rx_freq (1, 6.5e6)
+        rx_dst0 = gr.null_sink (gr.sizeof_gr_complex)
+        fg.connect (usrp_rx, rx_dst0)
+
+    return fg
+    
+def main ():
+    parser = OptionParser (option_class=eng_option)
+    parser.add_option ("-t", action="store_true", dest="tx_enable",
+                       default=False, help="enable Tx path")
+    parser.add_option ("-r", action="store_true", dest="rx_enable",
+                       default=False, help="enable Rx path")
+    (options, args) = parser.parse_args ()
+    fg = build_graph (options.tx_enable, options.rx_enable)
+
+    fg.start ()
+    raw_input ('Press Enter to quit: ')
+    fg.stop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/siggen_min2.py b/gnuradio-examples/python/usrp/siggen_min2.py
new file mode 100755
index 0000000000..8709e3373f
--- /dev/null
+++ b/gnuradio-examples/python/usrp/siggen_min2.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+
+
+def build_graph ():
+
+    # interp = 32
+    interp = 64
+    nchan = 2
+    
+    if nchan == 1:
+        mux = 0x0098
+        #mux = 0x9800
+    else:
+        mux = 0xba98
+
+    f0 = 100e3
+    a0 = 16e3
+    duc0 = 5e6
+
+    f1 = 50e3
+    a1 = 16e3
+    duc1 = 7e6
+
+    fg = gr.flow_graph ()
+
+    u = usrp.sink_c (0, interp, nchan, mux)
+    sample_rate = u.dac_freq () / interp
+    print "sample_rate = ", eng_notation.num_to_str (sample_rate)
+    print "usb_sample_rate = ", eng_notation.num_to_str (sample_rate * nchan)
+
+    u.set_tx_freq (0, duc0)
+    u.set_tx_freq (1, duc1)
+
+    interleave = gr.interleave (gr.sizeof_gr_complex)
+    fg.connect (interleave, u)
+
+    src0 = gr.sig_source_c (sample_rate, gr.GR_SIN_WAVE, f0, a0, 0)
+    fg.connect (src0, (interleave, 0))
+
+    if nchan == 2:
+        if 1:
+            src1 = gr.sig_source_c (sample_rate, gr.GR_SIN_WAVE, f1, a1, 0)
+        else:
+            src1 = gr.noise_source_c (gr.GR_UNIFORM, a1)
+        fg.connect (src1, (interleave, 1))
+    
+    return fg
+
+
+if __name__ == '__main__':
+    fg = build_graph ()
+    fg.start ()
+    raw_input ('Press Enter to quit: ')
+    fg.stop ()
+
diff --git a/gnuradio-examples/python/usrp/test_counting.py b/gnuradio-examples/python/usrp/test_counting.py
new file mode 100755
index 0000000000..ed9328a33a
--- /dev/null
+++ b/gnuradio-examples/python/usrp/test_counting.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+"""
+Check Rx path or USRP Rev 1.
+
+This configures the USRP to return a periodic sequence of integers
+"""
+
+from gnuradio import gr
+from gnuradio import usrp
+
+def build_graph ():
+    rx_decim  = 32
+    
+    fg = gr.flow_graph ()
+    usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_COUNTING)
+    sink = gr.check_counting_s ()
+    fg.connect (usrp_rx, sink)
+
+    # file_sink = gr.file_sink (gr.sizeof_short, 'counting.dat')
+    # fg.connect (usrp_rx, file_sink)
+
+    return fg
+    
+def main ():
+    fg = build_graph ()
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/test_dft_analysis.py b/gnuradio-examples/python/usrp/test_dft_analysis.py
new file mode 100755
index 0000000000..a1d9eda46c
--- /dev/null
+++ b/gnuradio-examples/python/usrp/test_dft_analysis.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, blks
+from gnuradio.wxgui import stdgui, fftsink, slider
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import wx
+
+class test_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self, frame, panel, vbox, argv)
+
+        parser = OptionParser (option_class=eng_option)
+        (options, args) = parser.parse_args ()
+
+        sample_rate = 16e3
+        mpoints = 4
+        ampl = 1000
+        freq = 0
+
+        lo_freq = 1e6
+        lo_ampl = 1
+        
+        vbox.Add(slider.slider(panel,
+                               -sample_rate/2, sample_rate/2,
+                               self.set_lo_freq), 0, wx.ALIGN_CENTER)
+
+
+        src = gr.sig_source_c(sample_rate, gr.GR_CONST_WAVE,
+                              freq, ampl, 0)
+
+        self.lo = gr.sig_source_c(sample_rate, gr.GR_SIN_WAVE,
+                                  lo_freq, lo_ampl, 0)
+
+        mixer = gr.multiply_cc()
+        self.connect(src, (mixer, 0))
+        self.connect(self.lo, (mixer, 1))
+        
+        # We add these throttle blocks so that this demo doesn't
+        # suck down all the CPU available.  Normally you wouldn't use these.
+        thr = gr.throttle(gr.sizeof_gr_complex, sample_rate)
+
+        taps = gr.firdes.low_pass(1,   # gain
+                                  1,   # rate
+                                  1.0/mpoints * 0.4,  # cutoff
+                                  1.0/mpoints * 0.1,  # trans width
+                                  gr.firdes.WIN_HANN)
+        print len(taps)
+        analysis = blks.analysis_filterbank(self, mpoints, taps)
+        
+        self.connect(mixer, thr)
+        self.connect(thr, analysis)
+
+        for i in range(mpoints):
+            fft = fftsink.fft_sink_c(self, frame, fft_size=128,
+                                     sample_rate=sample_rate/mpoints,
+                                     fft_rate=5,
+                                     title="Ch %d" % (i,))
+            self.connect((analysis, i), fft)
+            vbox.Add(fft.win, 1, wx.EXPAND)
+
+    def set_lo_freq(self, freq):
+        self.lo.set_frequency(freq)
+        
+                                     
+
+def main ():
+    app = stdgui.stdapp (test_graph, "Test DFT filterbank")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/test_dft_synth.py b/gnuradio-examples/python/usrp/test_dft_synth.py
new file mode 100755
index 0000000000..60a49e3b37
--- /dev/null
+++ b/gnuradio-examples/python/usrp/test_dft_synth.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, blks
+from gnuradio.wxgui import stdgui, fftsink
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import wx
+import random
+
+
+def make_random_complex_tuple(L, gain=1):
+    result = []
+    for x in range(L):
+        result.append(gain * complex(random.gauss(0, 1),random.gauss(0, 1)))
+                      
+    return tuple(result)
+
+def random_noise_c(gain=1):
+    src = gr.vector_source_c(make_random_complex_tuple(32*1024, gain), True)
+    return src
+
+
+class test_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self, frame, panel, vbox, argv)
+
+        parser = OptionParser (option_class=eng_option)
+        (options, args) = parser.parse_args ()
+
+        sample_rate = 16e6
+        mpoints = 16
+        ampl = 1000
+        
+        enable = mpoints * [0]
+        enable[0] = 1
+
+        taps = gr.firdes.low_pass(1,   # gain
+                                  1,   # rate
+                                  1.0/mpoints * 0.4,  # cutoff
+                                  1.0/mpoints * 0.1,  # trans width
+                                  gr.firdes.WIN_HANN)
+
+        synth = blks.synthesis_filterbank(self, mpoints, taps)
+        
+        null_source = gr.null_source(gr.sizeof_gr_complex)
+        
+        if 0:
+            for i in range(mpoints):
+                s = gr.sig_source_c(sample_rate/mpoints, gr.GR_SIN_WAVE,
+                                    300e3, ampl * enable[i], 0)
+                self.connect(s, (synth, i))
+
+        else:
+            for i in range(mpoints):
+                if i == 0:
+                    s = gr.sig_source_c(sample_rate/mpoints, gr.GR_SIN_WAVE,
+                                        300e3, ampl * enable[i], 0)
+                    #s = random_noise_c(ampl)
+                    self.connect(s, (synth, i))
+                else:
+                    self.connect(null_source, (synth, i))
+            
+
+        # We add these throttle blocks so that this demo doesn't
+        # suck down all the CPU available.  Normally you wouldn't use these.
+        thr = gr.throttle(gr.sizeof_gr_complex, sample_rate)
+        fft = fftsink.fft_sink_c(self, frame, fft_size=1024,
+                                 sample_rate=sample_rate)
+        vbox.Add(fft.win, 1, wx.EXPAND)
+
+        self.connect(synth, thr, fft)
+
+
+def main ():
+    app = stdgui.stdapp (test_graph, "Test DFT filterbank")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/test_digital_loopback_counting.py b/gnuradio-examples/python/usrp/test_digital_loopback_counting.py
new file mode 100755
index 0000000000..e985e4b4e2
--- /dev/null
+++ b/gnuradio-examples/python/usrp/test_digital_loopback_counting.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+"""
+Digital loopback (Tx to Rx) for the USRP Rev1.
+"""
+
+
+from gnuradio import gr
+from gnuradio import usrp
+
+
+def ramp_source (fg):
+    period = 2**16
+    src = gr.vector_source_s (range (-period/2, period/2, 1), True)
+    return src
+
+def build_graph ():
+    tx_interp =  32       # tx should be twice rx
+    rx_decim  =  16
+    
+    fg = gr.flow_graph ()
+
+    data_src = ramp_source (fg)
+    # usrp_tx = usrp.sink_s (0, tx_interp, 1, 0x98)
+    usrp_tx = usrp.sink_s (0, tx_interp)
+    fg.connect (data_src, usrp_tx)
+
+    usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK)
+    sink = gr.check_counting_s ()
+    fg.connect (usrp_rx, sink)
+
+    # file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat")
+    # fg.connect (usrp_rx, file_sink)
+    
+    return fg
+    
+def main ():
+    fg = build_graph ()
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py b/gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py
new file mode 100755
index 0000000000..ae78c71439
--- /dev/null
+++ b/gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+"""
+Digital loopback (Tx to Rx) for the USRP Rev1.
+"""
+
+from gnuradio import gr
+from gnuradio import usrp
+
+
+def build_graph ():
+    tx_interp =  32       # tx should be twice rx
+    rx_decim  =  16
+    
+    fg = gr.flow_graph ()
+
+    data_src = gr.lfsr_32k_source_s ()
+
+    # usrp_tx = usrp.sink_s (0, tx_interp, 1, 0x98)
+    usrp_tx = usrp.sink_s (0, tx_interp)
+
+    fg.connect (data_src, usrp_tx)
+
+    usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK)
+
+    sink = gr.check_lfsr_32k_s ()
+    fg.connect (usrp_rx, sink)
+
+    # file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat")
+    # fg.connect (usrp_rx, file_sink)
+    
+    return fg
+    
+def main ():
+    fg = build_graph ()
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py b/gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py
new file mode 100755
index 0000000000..e4ad36931e
--- /dev/null
+++ b/gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+#
+# Demodulate an AM signal from the TVRX or a recorded file.
+# The file format must be 256 ksps, complex data.
+#
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio import audio_oss as audio
+from gnuradio import usrp
+from gnuradio import tv_rx
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+import math
+from gnuradio.wxgui import stdgui, fftsink, scopesink
+import wx
+
+#
+# return a gr.flow_graph
+#
+class wfm_rx_graph (stdgui.gui_flow_graph):
+  def __init__(self,frame,panel,vbox,argv):
+    stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+    
+    #set rf freq
+    rf_freq = 120.e6
+    
+    # Decimation rate from USRP ADC to IF.
+    usrp_decim = 100
+    
+    # Calculate the sampling rate of the USRP and capture file.
+    # Decimate the IF sampling rate down by 4 to 64 ksps
+    # This is a flow graph that has an input (capture file) and output (audio channel).
+    #self = gr.flow_graph ()
+  
+    # Signal source is assumed to be 256 kspb / complex data stream.
+    which_side = 0
+    # usrp is data source
+    if which_side == 0:
+        src = usrp.source_c (0, usrp_decim, 1, gru.hexint(0xf0f0f0f0), 0)
+    else:
+        src = usrp.source_c (0, usrp_decim, 1, gru.hexint(0xf0f0f0f2), 0)
+
+    if_rate = 640e3 # src.adc_freq() / usrp_decim
+    if_decim = 5
+    demod_rate = if_rate / if_decim
+    
+    audio_decimation = 4
+    audio_rate = demod_rate / audio_decimation
+
+    # set up frontend
+    dboard = tv_rx.tv_rx (src, which_side)
+    self.dboard = dboard
+    (success, actual_freq) = dboard.set_freq(rf_freq)
+    assert success
+
+    if_freq = rf_freq - actual_freq
+    src.set_rx_freq (0, -if_freq)
+
+    print "actual freq ", actual_freq
+    print "IF freq ", if_freq
+        
+    dboard.set_gain(50)
+    
+    #src = gr.file_source (gr.sizeof_gr_complex, "samples/atis_ffz_am_baseband_256k_complex.dat")
+    #src = gr.file_source (gr.sizeof_gr_complex, "samples/garagedoor1.dat", True)
+    
+    #channel_coeffs = gr.firdes.band_pass (
+    #    1.0,    # gain
+    #    if_rate,
+    #    10,   # center of low transition band
+    #    10000,   # center of hi transition band
+    #    200,    # width of transition band
+    #    gr.firdes.WIN_HAMMING)
+    
+    channel_coeffs = gr.firdes.low_pass (1.0, if_rate, 10e3, 4e3, gr.firdes.WIN_HANN)
+    print "len(channel_coeffs) = ", len(channel_coeffs)
+
+    # Tune to the desired frequency.
+    ddc = gr.freq_xlating_fir_filter_ccf (if_decim, channel_coeffs, -20e3, if_rate)
+
+    # Demodule with classic sqrt (I*I + Q*Q)
+    magblock = gr.complex_to_mag()
+
+    # Scale the audio
+    volumecontrol = gr.multiply_const_ff(.1)
+
+    #band-pass
+    audio_coeffs = gr.firdes.band_pass (
+        1.0,    # gain
+        demod_rate,
+        10,   # center of low transition band
+        6000,   # center of hi transition band
+        200,    # width of transition band
+        gr.firdes.WIN_HAMMING)
+    
+    
+    # Low pass filter the demodulator output
+    #audio_coeffs = gr.firdes.low_pass (1.0, demod_rate, 500, 200, gr.firdes.WIN_HANN)
+    print "len(audio_coeffs) = ", len(audio_coeffs)
+
+    # input: float; output: float
+    audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
+
+    # sound card as final sink
+    audio_sink = audio.sink (int (audio_rate))
+
+    # now wire it all together
+    self.connect (src, ddc)
+    self.connect (ddc, magblock)
+    self.connect (magblock, volumecontrol)
+    self.connect (volumecontrol, audio_filter)
+    self.connect (audio_filter, (audio_sink, 0))
+    
+    d_win = fftsink.fft_sink_c (self, panel, title="RF", fft_size=512, sample_rate=if_rate)
+    self.connect (src,d_win)
+    vbox.Add (d_win.win, 4, wx.EXPAND)
+       
+    p_win = fftsink.fft_sink_c (self, panel, title="IF", fft_size=512, sample_rate=demod_rate)
+    self.connect (ddc,p_win)
+    vbox.Add (p_win.win, 4, wx.EXPAND)
+       
+    r_win = fftsink.fft_sink_f (self, panel, title="Audio", fft_size=512, sample_rate=audio_rate)
+    self.connect (audio_filter,r_win)
+    vbox.Add (r_win.win, 4, wx.EXPAND)
+    
+    #audio_oscope = scopesink.scope_sink_f (self, panel, "Oscope Data", audio_rate)
+    #self.connect (audio_filter, audio_oscope)
+    #vbox.Add (audio_oscope.win, 4, wx.EXPAND) 
+                
+if __name__ == '__main__':
+    
+    app = stdgui.stdapp (wfm_rx_graph, "TVRX AM RX")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/usrp_fft.py b/gnuradio-examples/python/usrp/usrp_fft.py
new file mode 100755
index 0000000000..f760e39aaf
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_fft.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+from optparse import OptionParser
+import wx
+import sys
+
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    If there's a daughterboard on A, select A.
+    If there's a daughterboard on B, select B.
+    Otherwise, select A.
+    """
+    if u.db[0][0].dbid() >= 0:       # dbid is < 0 if there's no d'board or a problem
+        return (0, 0)
+    if u.db[1][0].dbid() >= 0:
+        return (1, 0)
+    return (0, 0)
+
+
+class app_flow_graph(stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self)
+
+        self.frame = frame
+        self.panel = panel
+        
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=first one with a daughterboard)")
+        parser.add_option("-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("-8", "--width-8", action="store_true", default=False,
+                          help="Enable 8-bit samples across USB")
+        parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
+                          help="Enable oscilloscope display")
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+
+        self.show_debug_info = True
+        
+        # build the graph
+
+        self.u = usrp.source_c(decim_rate=options.decim)
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+
+        if options.width_8:
+            width = 8
+            shift = 8
+            format = self.u.make_format(width, shift)
+            print "format =", hex(format)
+            r = self.u.set_format(format)
+            print "set_format =", r
+            
+        # determine the daughterboard subdevice we're using
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+
+        if options.waterfall:
+            self.scope = \
+              waterfallsink.waterfall_sink_c (self, panel, fft_size=1024, sample_rate=input_rate)
+        elif options.oscilloscope:
+            self.scope = scopesink.scope_sink_c(self, panel, sample_rate=input_rate)
+        else:
+            self.scope = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate)
+
+        self.connect(self.u, self.scope)
+
+        self._build_gui(vbox)
+
+        # set initial values
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.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.subdev.freq_range()
+            options.freq = float(r[0]+r[1])/2
+
+        self.set_gain(options.gain)
+
+        if self.show_debug_info:
+            self.myform['decim'].set_value(self.u.decim_rate())
+            self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate())
+            self.myform['dbname'].set_value(self.subdev.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.subdev.gain_range()
+        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@usb'] = form.static_float_field(
+            parent=panel, sizer=hbox, label="Fs@USB")
+
+        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)
+
+        
+    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.
+        """
+        r = self.u.tune(0, self.subdev, 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)
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.subdev.set_gain(gain)
+
+    def set_decim(self, decim):
+        ok = self.u.set_decim_rate(decim)
+        if not ok:
+            print "set_decim failed"
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+        self.scope.set_sample_rate(input_rate)
+        if self.show_debug_info:  # update displayed values
+            self.myform['decim'].set_value(self.u.decim_rate())
+            self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate())
+        return ok
+
+def main ():
+    app = stdgui.stdapp(app_flow_graph, "USRP FFT", nstatus=1)
+    app.MainLoop()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/usrp_fft_old.py b/gnuradio-examples/python/usrp/usrp_fft_old.py
new file mode 100755
index 0000000000..c0776ea5cc
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_fft_old.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink, scopesink
+from optparse import OptionParser
+import wx
+
+class app_flow_graph (stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+
+        self.frame = frame
+        self.panel = panel
+        
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option ("-d", "--decim", type="int", default=16,
+                           help="set fgpa decimation rate to DECIM")
+        parser.add_option ("-c", "--ddc-freq", type="eng_float", default=0,
+                           help="set Rx DDC frequency to FREQ", metavar="FREQ")
+        parser.add_option ("-m", "--mux", type="intx", default=0x32103210,
+                           help="set fpga FR_RX_MUX register to MUX")
+        parser.add_option ("-g", "--gain", type="eng_float", default=0,
+                           help="set Rx PGA gain in dB (default 0 dB)")
+        (options, args) = parser.parse_args ()
+
+        self.u = usrp.source_c (0, options.decim, 1, gru.hexint(options.mux), 0)
+        self.u.set_rx_freq (0, options.ddc_freq)
+
+        self.u.set_pga (0, options.gain)
+        self.u.set_pga (1, options.gain)
+
+        self.u.set_verbose (0)
+        
+        input_rate = self.u.adc_freq () / self.u.decim_rate ()
+
+        fft = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate)
+        #fft = fftsink.fft_sink_c (self, panel, fft_size=1024, fft_rate=50, sample_rate=input_rate)
+        self.connect (self.u, fft)
+        vbox.Add (fft.win, 10, wx.EXPAND)
+
+	if 0:
+            c2f_1 = gr.complex_to_float ()
+            scope = scopesink.scope_sink_f (self, panel, "Rx Data", input_rate)
+            vbox.Add (scope.win, 4, wx.EXPAND)
+
+            self.connect (self.u,c2f_1)
+            self.connect ((c2f_1, 0), (scope, 0))
+            self.connect ((c2f_1, 1), (scope, 1))
+
+        # build small control area at bottom
+        hbox = wx.BoxSizer (wx.HORIZONTAL)
+        hbox.Add ((1, 1), 1, wx.EXPAND)
+        hbox.Add (wx.StaticText (panel, -1, "Set ddc freq: "), 0, wx.ALIGN_CENTER)
+        self.tc_freq = wx.TextCtrl (panel, -1, "", style=wx.TE_PROCESS_ENTER)
+        hbox.Add (self.tc_freq, 0, wx.ALIGN_CENTER)
+        wx.EVT_TEXT_ENTER (self.tc_freq, self.tc_freq.GetId(), self.handle_text_enter)
+        hbox.Add ((1, 1), 1, wx.EXPAND)
+        # add it to the main vbox
+        vbox.Add (hbox, 0, wx.EXPAND)
+
+        self.update_status_bar ()
+
+    def handle_text_enter (self, event):
+        str = event.GetString ()
+        self.tc_freq.Clear ()
+        self.u.set_rx_freq (0, eng_notation.str_to_num (str))
+        self.update_status_bar ()
+
+    def update_status_bar (self):
+        ddc_freq = self.u.rx_freq (0)
+        decim_rate = self.u.decim_rate ()
+        sample_rate = self.u.adc_freq () / decim_rate
+        msg = "decim: %d  %sS/s  DDC: %s" % (
+            decim_rate,
+            eng_notation.num_to_str (sample_rate),
+            eng_notation.num_to_str (ddc_freq))
+            
+        self.frame.GetStatusBar().SetStatusText (msg, 1)
+
+        
+
+def main ():
+    app = stdgui.stdapp (app_flow_graph, "USRP FFT")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py b/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py
new file mode 100755
index 0000000000..3e930bbb51
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py
@@ -0,0 +1,491 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+import math
+import sys
+import wx
+from optparse import OptionParser
+
+from gnuradio import gr, gru, eng_notation
+from gnuradio import usrp
+from gnuradio import audio
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink, scopesink, slider, form
+import usrp_dbid
+
+from Numeric import convolve, array
+
+#import os
+#print "pid =", os.getpid()
+#raw_input('Press Enter to continue: ')
+
+# ////////////////////////////////////////////////////////////////////////
+#                           Control Stuff
+# ////////////////////////////////////////////////////////////////////////
+
+class ptt_graph(stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+
+        self.frame = frame
+        self.space_bar_pressed = False
+        
+        parser = OptionParser (option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B")
+        parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Tx side A or B")
+        parser.add_option ("-f", "--freq", type="eng_float", default=442.1e6,
+                           help="set Tx and Rx frequency to FREQ", metavar="FREQ")
+        parser.add_option ("-g", "--rx-gain", type="eng_float", default=None,
+                           help="set rx gain [default=midpoint in dB]")
+        parser.add_option("-I", "--audio-input", type="string", default="",
+                          help="pcm input device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
+        parser.add_option ("-N", "--no-gui", action="store_true", default=False)
+        (options, args) = parser.parse_args ()
+
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+
+        if options.freq < 1e6:
+            options.freq *= 1e6
+            
+        self.txpath = transmit_path(self, options.tx_subdev_spec, options.audio_input)
+        self.rxpath = receive_path(self, options.rx_subdev_spec, options.rx_gain, options.audio_output)
+        self._build_gui(frame, panel, vbox, argv, options.no_gui)
+
+        self.set_transmit(False)
+        self.set_freq(options.freq)
+        self.set_rx_gain(self.rxpath.gain)               # update gui
+        self.set_volume(self.rxpath.volume)              # update gui
+        self.set_squelch(self.rxpath.threshold())        # update gui
+
+
+    def set_transmit(self, enabled):
+        self.txpath.set_enable(enabled)
+        self.rxpath.set_enable(not(enabled))
+        if enabled:
+            self.frame.SetStatusText ("Transmitter ON", 1)
+        else:
+            self.frame.SetStatusText ("Receiver ON", 1)
+
+
+    def set_rx_gain(self, gain):
+        self.myform['rx_gain'].set_value(gain)            # update displayed value
+        self.rxpath.set_gain(gain)
+        
+    def set_tx_gain(self, gain):
+        self.txpath.set_gain(gain)
+
+    def set_squelch(self, threshold):
+        self.rxpath.set_squelch(threshold)
+        self.myform['squelch'].set_value(self.rxpath.threshold())
+
+    def set_volume (self, vol):
+        self.rxpath.set_volume(vol)
+        self.myform['volume'].set_value(self.rxpath.volume)
+        #self.update_status_bar ()
+
+    def set_freq(self, freq):
+        r1 = self.txpath.set_freq(freq)
+        r2 = self.rxpath.set_freq(freq)
+        #print "txpath.set_freq =", r1
+        #print "rxpath.set_freq =", r2
+        if r1 and r2:
+            self.myform['freq'].set_value(freq)     # update displayed value
+        return r1 and r2
+
+    def _build_gui(self, frame, panel, vbox, argv, no_gui):
+
+        def _form_set_freq(kv):
+            return self.set_freq(kv['freq'])
+            
+        self.panel = panel
+        
+        # FIXME This REALLY needs to be replaced with a hand-crafted button
+        # that sends both button down and button up events
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((10,0), 1)
+        self.status_msg = wx.StaticText(panel, -1, "Press Space Bar to Transmit")
+        of = self.status_msg.GetFont()
+        self.status_msg.SetFont(wx.Font(15, of.GetFamily(), of.GetStyle(), of.GetWeight()))
+        hbox.Add(self.status_msg, 0, wx.ALIGN_CENTER)
+        hbox.Add((10,0), 1)
+        vbox.Add(hbox, 0, wx.EXPAND | wx.ALIGN_CENTER)
+
+        panel.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
+        panel.Bind(wx.EVT_KEY_UP, self._on_key_up)
+        panel.Bind(wx.EVT_KILL_FOCUS, self._on_kill_focus)
+        panel.SetFocus()
+
+        if 1 and not(no_gui):
+            rx_fft = fftsink.fft_sink_c (self, panel, title="Rx Input", fft_size=512,
+                                         sample_rate=self.rxpath.if_rate,
+                                         ref_level=80, y_per_div=20)
+            self.connect (self.rxpath.u, rx_fft)
+            vbox.Add (rx_fft.win, 1, wx.EXPAND)
+
+        if 1 and not(no_gui):
+            rx_fft = fftsink.fft_sink_c (self, panel, title="Post s/w DDC",
+                                         fft_size=512, sample_rate=self.rxpath.quad_rate,
+                                         ref_level=80, y_per_div=20)
+            self.connect (self.rxpath.ddc, rx_fft)
+            vbox.Add (rx_fft.win, 1, wx.EXPAND)
+
+        if 0 and not(no_gui):
+            foo = scopesink.scope_sink_f (self, panel, title="Squelch",
+                                               sample_rate=32000)
+            self.connect (self.rxpath.fmrx.div, (foo,0))
+            self.connect (self.rxpath.fmrx.gate, (foo,1))
+            self.connect (self.rxpath.fmrx.squelch_lpf, (foo,2))
+            vbox.Add (foo.win, 1, wx.EXPAND)
+
+        if 0 and not(no_gui):
+            tx_fft = fftsink.fft_sink_c (self, panel, title="Tx Output",
+                                         fft_size=512, sample_rate=self.txpath.usrp_rate)
+            self.connect (self.txpath.amp, tx_fft)
+            vbox.Add (tx_fft.win, 1, wx.EXPAND)
+
+
+        # add control area at the bottom
+
+        self.myform = myform = form.form()
+
+        # first row
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0, 0)
+        myform['freq'] = form.float_field(
+            parent=panel, sizer=hbox, label="Freq", weight=1,
+            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
+
+        hbox.Add((5,0), 0, 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+
+        # second row
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        myform['volume'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume",
+                                        weight=3, range=self.rxpath.volume_range(),
+                                        callback=self.set_volume)
+        hbox.Add((5,0), 0)
+        myform['squelch'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Squelch",
+                                        weight=3, range=self.rxpath.squelch_range(),
+                                        callback=self.set_squelch)
+        hbox.Add((5,0), 0)
+        myform['rx_gain'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Rx Gain",
+                                        weight=3, range=self.rxpath.subdev.gain_range(),
+                                        callback=self.set_rx_gain)
+        hbox.Add((5,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)
+        
+        #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.static_float_field(
+        #    parent=panel, sizer=hbox, label="Decim")
+
+        #hbox.Add((5,0), 1)
+        #myform['fs@usb'] = form.static_float_field(
+        #    parent=panel, sizer=hbox, label="Fs@USB")
+
+        #hbox.Add((5,0), 1)
+        #myform['dbname'] = form.static_text_field(
+        #    parent=panel, sizer=hbox)
+
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+
+    def _set_status_msg(self, msg, which=0):
+        self.frame.GetStatusBar().SetStatusText(msg, which)
+
+    def _on_key_down(self, evt):
+        # print "key_down:", evt.m_keyCode
+        if evt.m_keyCode == wx.WXK_SPACE and not(self.space_bar_pressed):
+            self.space_bar_pressed = True
+            self.set_transmit(True)
+
+    def _on_key_up(self, evt):
+        # print "key_up", evt.m_keyCode
+        if evt.m_keyCode == wx.WXK_SPACE:
+            self.space_bar_pressed = False
+            self.set_transmit(False)
+
+    def _on_kill_focus(self, evt):
+        # if we lose the keyboard focus, turn off the transmitter
+        self.space_bar_pressed = False
+        self.set_transmit(False)
+        
+
+# ////////////////////////////////////////////////////////////////////////
+#                           Transmit Path
+# ////////////////////////////////////////////////////////////////////////
+
+class transmit_path(gr.hier_block):
+    def __init__(self, fg, subdev_spec, audio_input):
+
+        self.u = usrp.sink_c ()
+
+        dac_rate = self.u.dac_rate();
+        self.if_rate = 320e3                               # 320 kS/s
+        self.usrp_interp = int(dac_rate // self.if_rate)
+        self.u.set_interp_rate(self.usrp_interp)
+        self.sw_interp = 10
+        self.audio_rate = self.if_rate // self.sw_interp   #  32 kS/s
+
+        self.audio_gain = 10
+        self.normal_gain = 32000
+
+        self.audio = audio.source(int(self.audio_rate), audio_input)
+        self.audio_amp = gr.multiply_const_ff(self.audio_gain)
+
+        lpf = gr.firdes.low_pass (1,                # gain
+                                  self.audio_rate,            # sampling rate
+                                  3800,               # low pass cutoff freq
+                                  300,                # width of trans. band
+                                  gr.firdes.WIN_HANN) # filter type 
+
+        hpf = gr.firdes.high_pass (1,                # gain
+                                  self.audio_rate,            # sampling rate
+                                  325,               # low pass cutoff freq
+                                  50,                # width of trans. band
+                                  gr.firdes.WIN_HANN) # filter type 
+
+        audio_taps = convolve(array(lpf),array(hpf))
+        self.audio_filt = gr.fir_filter_fff(1,audio_taps)
+
+        self.pl = blks.ctcss_gen_f(fg, self.audio_rate,123.0)
+        self.add_pl = gr.add_ff()
+        fg.connect(self.pl,(self.add_pl,1))
+
+        self.fmtx = blks.nbfm_tx(fg, self.audio_rate, self.if_rate)
+        self.amp = gr.multiply_const_cc (self.normal_gain)
+
+        # determine the daughterboard subdevice we're using
+        if subdev_spec is None:
+            subdev_spec = usrp.pick_tx_subdevice(self.u)
+        self.u.set_mux(usrp.determine_tx_mux_value(self.u, subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, subdev_spec)
+        print "TX using", self.subdev.name()
+
+        fg.connect(self.audio, self.audio_amp, self.audio_filt,
+                   (self.add_pl,0), self.fmtx, self.amp, self.u)
+        
+        gr.hier_block.__init__(self, fg, None, None)
+
+        self.set_gain(self.subdev.gain_range()[1])  # set max Tx 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.  Finally, we feed
+        any residual_freq to the s/w freq translater.
+        """
+        r = self.u.tune(self.subdev._which, self.subdev, target_freq)
+        if r:
+            # Use residual_freq in s/w freq translator
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.gain = gain
+        self.subdev.set_gain(gain)
+
+    def set_enable(self, enable):
+        self.subdev.set_enable(enable)            # set H/W Tx enable
+        if enable:
+            self.amp.set_k (self.normal_gain)
+        else:
+            self.amp.set_k (0)
+
+
+
+# ////////////////////////////////////////////////////////////////////////
+#                           Receive Path
+# ////////////////////////////////////////////////////////////////////////
+
+class receive_path(gr.hier_block):
+    def __init__(self, fg, subdev_spec, gain, audio_output):
+
+        self.u = usrp.source_c ()
+        adc_rate = self.u.adc_rate()
+
+        self.if_rate = 256e3                         # 256 kS/s
+        usrp_decim = int(adc_rate // self.if_rate)
+        if_decim = 4
+        self.u.set_decim_rate(usrp_decim)
+        self.quad_rate = self.if_rate // if_decim    #  64 kS/s
+        audio_decim = 2
+        audio_rate = self.quad_rate // audio_decim   #  32 kS/s
+
+        if subdev_spec is None:
+            subdev_spec = usrp.pick_rx_subdevice(self.u)
+        self.subdev = usrp.selected_subdev(self.u, subdev_spec)
+        print "RX using", self.subdev.name()
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec))
+
+        # Create filter to get actual channel we want
+        chan_coeffs = gr.firdes.low_pass (1.0,                # gain
+                                          self.if_rate,       # sampling rate
+                                          13e3,               # low pass cutoff freq
+                                          4e3,                # width of trans. band
+                                          gr.firdes.WIN_HANN) # filter type 
+
+        print "len(rx_chan_coeffs) =", len(chan_coeffs)
+
+        # Decimating Channel filter with frequency translation
+        # complex in and out, float taps
+        self.ddc = gr.freq_xlating_fir_filter_ccf(if_decim,       # decimation rate
+                                                  chan_coeffs,    # taps
+                                                  0,              # frequency translation amount
+                                                  self.if_rate)   # input sample rate
+
+        # instantiate the guts of the single channel receiver
+        self.fmrx = blks.nbfm_rx(fg, audio_rate, self.quad_rate)
+
+        # standard squelch block
+        self.squelch = blks.standard_squelch(fg, audio_rate)
+
+        # audio gain / mute block
+        self._audio_gain = gr.multiply_const_ff(1.0)
+
+        # sound card as final sink
+        audio_sink = audio.sink (int(audio_rate), audio_output)
+        
+        # now wire it all together
+        fg.connect (self.u, self.ddc, self.fmrx, self.squelch, self._audio_gain, audio_sink)
+        gr.hier_block.__init__(self, fg, self.u, audio_sink)
+
+        if gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            gain = float(g[0]+g[1])/2
+
+        self.enabled = True
+        self.set_gain(gain)
+        v = self.volume_range()
+        self.set_volume((v[0]+v[1])/2)
+        s = self.squelch_range()
+        self.set_squelch((s[0]+s[1])/2)
+        
+        
+    def volume_range(self):
+        return (-20.0, 0.0, 0.5)
+
+    def set_volume (self, vol):
+        g = self.volume_range()
+        self.volume = max(g[0], min(g[1], vol))
+        self._update_audio_gain()
+
+    def set_enable(self, enable):
+        self.enabled = enable
+        self._update_audio_gain()
+
+    def _update_audio_gain(self):
+        if self.enabled:
+            self._audio_gain.set_k(10**(self.volume/10))
+        else:
+            self._audio_gain.set_k(0)
+
+    def squelch_range(self):
+        return self.squelch.squelch_range()
+    
+    def set_squelch(self, threshold):
+        print "SQL =", threshold
+        self.squelch.set_threshold(threshold)
+
+    def threshold(self):
+        return self.squelch.threshold()
+    
+    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 in the
+        FPGA.  Finally, we feed any residual_freq to the s/w freq
+        translator.
+        """
+        r = self.u.tune(0, self.subdev, target_freq)
+        if r:
+            # Use residual_freq in s/w freq translater
+            # print "residual_freq =", r.residual_freq
+            self.ddc.set_center_freq(-r.residual_freq)
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.gain = gain
+        self.subdev.set_gain(gain)
+
+
+# ////////////////////////////////////////////////////////////////////////
+#                                Main
+# ////////////////////////////////////////////////////////////////////////
+
+def main():
+    app = stdgui.stdapp(ptt_graph, "NBFM Push to Talk")
+    app.MainLoop()
+
+if __name__ == '__main__':
+    main()
diff --git a/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py b/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py
new file mode 100755
index 0000000000..018a5b76e8
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py
@@ -0,0 +1,362 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import slider, powermate
+from gnuradio.wxgui import stdgui, fftsink, form
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+import wx
+
+
+#////////////////////////////////////////////////////////////////////////
+#                           Control Stuff
+#////////////////////////////////////////////////////////////////////////
+
+class my_graph (stdgui.gui_flow_graph):
+    def __init__(self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-f", "--freq", type="eng_float", default=146.585e6,
+                          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("-V", "--volume", type="eng_float", default=None,
+                          help="set volume (default is midpoint)")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")
+        parser.add_option("-N", "--no-gui", action="store_true", default=False)
+
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+        
+        if options.freq < 1e6:
+            options.freq *= 1e6
+            
+        self.frame = frame
+        self.panel = panel
+        
+        self.state = "FREQ"
+        self.freq = 0
+        self.freq_step = 25e3
+
+        self.rxpath = receive_path(self, options.rx_subdev_spec, options.gain, options.audio_output)
+
+        self._build_gui(vbox, options.no_gui)
+
+        # set initial values
+
+        if options.volume is not None:
+            self.set_volume(options.volume)
+
+        if not(self.set_freq(options.freq)):
+            self._set_status_msg("Failed to set initial frequency")
+
+        self.set_gain(self.rxpath.gain)               # update gui
+        self.set_volume(self.rxpath.volume)           # update gui
+        self.set_squelch(self.rxpath.threshold())     # update gui
+
+
+    def _set_status_msg(self, msg, which=0):
+        self.frame.GetStatusBar().SetStatusText(msg, which)
+
+
+    def _build_gui(self, vbox, no_gui):
+
+        def _form_set_freq(kv):
+            return self.set_freq(kv['freq'])
+
+
+        self.src_fft = None
+        if 1 and not(no_gui):
+            self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+                                               fft_size=512, sample_rate=self.rxpath.if_rate,
+                                               ref_level=80, y_per_div=20)
+            self.connect (self.rxpath.u, self.src_fft)
+            vbox.Add (self.src_fft.win, 4, wx.EXPAND)
+
+        if 1 and not(no_gui):
+            rx_fft = fftsink.fft_sink_c (self, self.panel, title="Post s/w DDC",
+                                         fft_size=512, sample_rate=self.rxpath.quad_rate,
+                                         ref_level=80, y_per_div=20)
+            self.connect (self.rxpath.ddc, rx_fft)
+            vbox.Add (rx_fft.win, 4, wx.EXPAND)
+        
+        if 1 and not(no_gui):
+            post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
+                                                  fft_size=512, sample_rate=self.rxpath.audio_rate,
+                                                  y_per_div=10, ref_level=-40)
+            self.connect (self.rxpath.fmrx.deemph, post_deemph_fft)
+            vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", 
+                                                fft_size=512, sample_rate=audio_rate,
+                                                y_per_div=10, ref_level=-40)
+            self.connect (self.guts.audio_filter, post_filt)
+            vbox.Add (fft_win4, 4, wx.EXPAND)
+
+        
+        # control area form at bottom
+        self.myform = myform = form.form()
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+        myform['freq'] = form.float_field(
+            parent=self.panel, sizer=hbox, label="Freq", weight=1,
+            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
+
+        #hbox.Add((5,0), 0)
+        #myform['freq_slider'] = \
+        #    form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
+        #                                range=(87.9e6, 108.1e6, 0.1e6),
+        #                                callback=self.set_freq)
+
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+
+        myform['volume'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume",
+                                        weight=3, range=self.volume_range(),
+                                        callback=self.set_volume)
+        hbox.Add((5,0), 0)
+        myform['squelch'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Squelch",
+                                        weight=3, range=self.rxpath.squelch_range(),
+                                        callback=self.set_squelch)
+        hbox.Add((5,0), 0)
+        myform['gain'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain",
+                                        weight=3, range=self.rxpath.subdev.gain_range(),
+                                        callback=self.set_gain)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        try:
+            self.knob = powermate.powermate(self.frame)
+            self.rot = 0
+            powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
+            powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
+        except:
+            print "FYI: No Powermate or Contour Knob found"
+
+
+    def on_rotate (self, event):
+        self.rot += event.delta
+        if (self.state == "FREQ"):
+            if self.rot >= 3:
+                self.set_freq(self.freq + self.freq_step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_freq(self.freq - self.freq_step)
+                self.rot += 3
+        else:
+            step = self.volume_range()[2]
+            if self.rot >= 3:
+                self.set_volume(self.rxpath.volume + step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_volume(self.rxpath.volume - step)
+                self.rot += 3
+            
+    def on_button (self, event):
+        if event.value == 0:        # button up
+            return
+        self.rot = 0
+        if self.state == "FREQ":
+            self.state = "VOL"
+        else:
+            self.state = "FREQ"
+        self.update_status_bar ()
+        
+
+    def set_squelch(self, threshold_in_db):
+        self.rxpath.set_squelch(threshold_in_db)
+        self.myform['squelch'].set_value(self.rxpath.threshold())
+
+    def set_volume (self, vol):
+        self.rxpath.set_volume(vol)
+        self.myform['volume'].set_value(self.rxpath.volume)
+        self.update_status_bar ()
+                                        
+    def set_freq(self, target_freq):
+        r = self.rxpath.set_freq(target_freq)
+        if r:
+            self.freq = target_freq
+            self.myform['freq'].set_value(target_freq)         # update displayed value
+            #self.myform['freq_slider'].set_value(target_freq)  # update displayed value
+            self.update_status_bar()
+            self._set_status_msg("OK", 0)
+            return True
+
+        self._set_status_msg("Failed", 0)
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.rxpath.set_gain(gain)
+
+    def update_status_bar (self):
+        msg = "Volume:%r  Setting:%s" % (self.rxpath.volume, self.state)
+        self._set_status_msg(msg, 1)
+        if self.src_fft:
+            self.src_fft.set_baseband_freq(self.freq)
+
+    def volume_range(self):
+        return (-20.0, 0.0, 0.5)
+        
+
+#////////////////////////////////////////////////////////////////////////
+#                           Receive Path
+#////////////////////////////////////////////////////////////////////////
+
+USE_SIMPLE_SQUELCH = False
+
+class receive_path(gr.hier_block):
+    def __init__(self, fg, subdev_spec, gain, audio_output):
+
+        self.u = usrp.source_c ()
+        adc_rate = self.u.adc_rate()
+
+        self.if_rate = 256e3                              # 256 kS/s
+        usrp_decim = int(adc_rate // self.if_rate)
+        if_decim = 4
+        self.u.set_decim_rate(usrp_decim)
+        self.quad_rate = self.if_rate // if_decim         #  64 kS/s
+        audio_decim = 2
+        self.audio_rate = self.quad_rate // audio_decim   #  32 kS/s
+
+
+        if subdev_spec is None:
+            subdev_spec = usrp.pick_rx_subdevice(self.u)
+        self.subdev = usrp.selected_subdev(self.u, subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec))
+
+        # Create filter to get actual channel we want
+        chan_coeffs = gr.firdes.low_pass (1.0,                # gain
+                                          self.if_rate,       # sampling rate
+                                          13e3,               # low pass cutoff freq
+                                          4e3,                # width of trans. band
+                                          gr.firdes.WIN_HANN) # filter type 
+
+        print "len(rx_chan_coeffs) =", len(chan_coeffs)
+
+        # Decimating Channel filter with frequency translation
+        # complex in and out, float taps
+        self.ddc = gr.freq_xlating_fir_filter_ccf(if_decim,       # decimation rate
+                                                  chan_coeffs,    # taps
+                                                  0,              # frequency translation amount
+                                                  self.if_rate)   # input sample rate
+
+        if USE_SIMPLE_SQUELCH:
+            self.squelch = gr.simple_squelch_cc(20)
+        else:
+            self.squelch = blks.standard_squelch(fg, self.audio_rate)
+
+        # instantiate the guts of the single channel receiver
+        self.fmrx = blks.nbfm_rx(fg, self.audio_rate, self.quad_rate)
+
+        # audio gain / mute block
+        self._audio_gain = gr.multiply_const_ff(1.0)
+
+        # sound card as final sink
+        audio_sink = audio.sink (int(self.audio_rate), audio_output)
+        
+        # now wire it all together
+        if USE_SIMPLE_SQUELCH:
+            fg.connect (self.u, self.ddc, self.squelch, self.fmrx,
+                        self._audio_gain, audio_sink)
+        else:
+            fg.connect (self.u, self.ddc, self.fmrx, self.squelch,
+                        self._audio_gain, audio_sink)
+
+        gr.hier_block.__init__(self, fg, self.u, audio_sink)
+
+        if gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            gain = float(g[0]+g[1])/2
+
+        self.set_gain(gain)
+
+        v = self.volume_range()
+        self.set_volume((v[0]+v[1])/2)
+        s = self.squelch_range()
+        self.set_squelch((s[0]+s[1])/2)
+
+    def volume_range(self):
+        return (-20.0, 0.0, 0.5)
+
+    def set_volume (self, vol):
+        g = self.volume_range()
+        self.volume = max(g[0], min(g[1], vol))
+        self._update_audio_gain()
+
+    def _update_audio_gain(self):
+        self._audio_gain.set_k(10**(self.volume/10))
+        
+    def squelch_range(self):
+        r = self.squelch.squelch_range()
+        #print "squelch_range: ", r
+        return r
+    
+    def set_squelch(self, threshold):
+        #print "SQL =", threshold
+        self.squelch.set_threshold(threshold)
+
+    def threshold(self):
+        t = self.squelch.threshold()
+        #print "t =", t
+        return t
+
+    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 in the
+        FPGA.  Finally, we feed any residual_freq to the s/w freq
+        translator.
+        """
+
+        r = usrp.tune(self.u, 0, self.subdev, target_freq)
+        if r:
+            # Use residual_freq in s/w freq translater
+            # print "residual_freq =", r.residual_freq
+            self.ddc.set_center_freq(-r.residual_freq)
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.gain = gain
+        self.subdev.set_gain(gain)
+
+
+# ////////////////////////////////////////////////////////////////////////
+#                                Main
+# ////////////////////////////////////////////////////////////////////////
+
+if __name__ == '__main__':
+    app = stdgui.stdapp (my_graph, "USRP NBFM RX")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/usrp_oscope.py b/gnuradio-examples/python/usrp/usrp_oscope.py
new file mode 100755
index 0000000000..f4469f9963
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_oscope.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005,2006 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# print "Loading revised usrp_oscope with additional options for scopesink..."
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+from optparse import OptionParser
+import wx
+import sys
+
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    If there's a daughterboard on A, select A.
+    If there's a daughterboard on B, select B.
+    Otherwise, select A.
+    """
+    if u.db[0][0].dbid() >= 0:       # dbid is < 0 if there's no d'board or a problem
+        return (0, 0)
+    if u.db[1][0].dbid() >= 0:
+        return (1, 0)
+    return (0, 0)
+
+
+class app_flow_graph(stdgui.gui_flow_graph):
+    def __init__(self, frame, panel, vbox, argv):
+        stdgui.gui_flow_graph.__init__(self)
+
+        self.frame = frame
+        self.panel = panel
+        
+        parser = OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=first one with a daughterboard)")
+        parser.add_option("-d", "--decim", type="int", default=16,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=None,
+                          help="set frequency to FREQ", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=None,
+                          help="set gain in dB (default is midpoint)")
+        parser.add_option("-8", "--width-8", action="store_true", default=False,
+                          help="Enable 8-bit samples across USB")
+        parser.add_option("-n", "--frame-decim", type="int", default=1,
+                          help="set oscope frame decimation factor to n [default=1]")
+        parser.add_option("-v", "--v-scale", type="eng_float", default=1000,
+                          help="set oscope initial V/div to SCALE [default=%default]")
+        parser.add_option("-t", "--t-scale", type="eng_float", default=49e-6,
+                          help="set oscope initial s/div to SCALE [default=50us]")
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+
+        self.show_debug_info = True
+        
+        # build the graph
+
+        self.u = usrp.source_c(decim_rate=options.decim)
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+
+        if options.width_8:
+            width = 8
+            shift = 8
+            format = self.u.make_format(width, shift)
+            #print "format =", hex(format)
+            r = self.u.set_format(format)
+            #print "set_format =", r
+            
+        # determine the daughterboard subdevice we're using
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+
+        self.scope = scopesink.scope_sink_c(self, panel, sample_rate=input_rate,
+                                            frame_decim=options.frame_decim,
+                                            v_scale=options.v_scale,
+                                            t_scale=options.t_scale)
+        self.connect(self.u, self.scope)
+
+        self._build_gui(vbox)
+
+        # set initial values
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.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.subdev.freq_range()
+            options.freq = float(r[0]+r[1])/2
+
+        self.set_gain(options.gain)
+
+        if self.show_debug_info:
+            self.myform['decim'].set_value(self.u.decim_rate())
+            self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate())
+            self.myform['dbname'].set_value(self.subdev.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.subdev.gain_range()
+        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@usb'] = form.static_float_field(
+            parent=panel, sizer=hbox, label="Fs@USB")
+
+        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)
+
+        
+    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.
+        """
+        r = usrp.tune(self.u, 0, self.subdev, 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)
+            return True
+
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.subdev.set_gain(gain)
+
+    def set_decim(self, decim):
+        ok = self.u.set_decim_rate(decim)
+        if not ok:
+            print "set_decim failed"
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+        self.scope.set_sample_rate(input_rate)
+        if self.show_debug_info:  # update displayed values
+            self.myform['decim'].set_value(self.u.decim_rate())
+            self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate())
+        return ok
+
+def main ():
+    app = stdgui.stdapp(app_flow_graph, "USRP O'scope", nstatus=1)
+    app.MainLoop()
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/usrp_rx_cfile.py b/gnuradio-examples/python/usrp/usrp_rx_cfile.py
new file mode 100755
index 0000000000..306e101d35
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_rx_cfile.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+
+"""
+Read samples from the USRP and write to file formatted as binary
+outputs single precision complex float values or complex short values (interleaved 16 bit signed short integers).
+
+"""
+
+from gnuradio import gr, eng_notation
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        usage="%prog: [options] output_filename"
+        parser = OptionParser(option_class=eng_option, usage=usage)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0),
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-d", "--decim", type="int", default=16,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=None,
+                          help="set frequency to FREQ", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=None,
+                          help="set gain in dB (default is midpoint)")
+        parser.add_option("-8", "--width-8", action="store_true", default=False,
+                          help="Enable 8-bit samples across USB")
+        parser.add_option( "--no-hb", action="store_true", default=False,
+                          help="don't use halfband filter in usrp")
+        parser.add_option( "-s","--output-shorts", action="store_true", default=False,
+                          help="output interleaved shorts in stead of complex floats")
+        parser.add_option("-N", "--nsamples", type="eng_float", default=None,
+                          help="number of samples to collect [default=+inf]")
+        (options, args) = parser.parse_args ()
+        if len(args) != 1:
+            parser.print_help()
+            raise SystemExit, 1
+        filename = args[0]
+
+        if options.freq is None:
+            parser.print_help()
+            sys.stderr.write('You must specify the frequency with -f FREQ\n');
+            raise SystemExit, 1
+
+        # build the graph
+        if options.no_hb or (options.decim<8):
+          self.fpga_filename="std_4rx_0tx.rbf" #Min decimation of this firmware is 4. contains 4 Rx paths without halfbands and 0 tx paths.
+          if options.output_shorts:
+            self.u = usrp.source_s(decim_rate=options.decim,fpga_filename=self.fpga_filename)
+          else:
+            self.u = usrp.source_c(decim_rate=options.decim,fpga_filename=self.fpga_filename)
+        else:
+          #standard fpga firmware "std_2rxhb_2tx.rbf" contains 2 Rx paths with halfband filters and 2 tx paths (the default) min decimation 8
+          if options.output_shorts:
+            self.u = usrp.source_s(decim_rate=options.decim)
+          else:
+            self.u = usrp.source_c(decim_rate=options.decim)
+        if options.width_8:
+            sample_width = 8
+            sample_shift = 8
+            format = self.u.make_format(sample_width, sample_shift)
+            r = self.u.set_format(format)
+        if options.output_shorts:
+          self.dst = gr.file_sink(gr.sizeof_short, filename)
+        else:
+          self.dst = gr.file_sink(gr.sizeof_gr_complex, filename)
+        if options.nsamples is None:
+            self.connect(self.u, self.dst)
+        else:
+            if options.output_shorts:
+              self.head = gr.head(gr.sizeof_short, int(options.nsamples)*2)
+            else:
+              self.head = gr.head(gr.sizeof_gr_complex, int(options.nsamples))
+            self.connect(self.u, self.head, self.dst)
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+
+        # determine the daughterboard subdevice we're using
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+        input_rate = self.u.adc_freq() / self.u.decim_rate()
+        print "USB sample rate %s" % (eng_notation.num_to_str(input_rate))
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+        self.subdev.set_gain(options.gain)
+
+        r = self.u.tune(0, self.subdev, options.freq)
+        if not r:
+            sys.stderr.write('Failed to set frequency\n')
+            raise SystemExit, 1
+
+        
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/usrp/usrp_rx_nogui.py b/gnuradio-examples/python/usrp/usrp_rx_nogui.py
new file mode 100755
index 0000000000..b33d626e28
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_rx_nogui.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, usrp, optfir, audio, eng_notation, blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+"""
+This example application demonstrates receiving and demodulating 
+different types of signals using the USRP. 
+
+A receive chain is built up of the following signal processing
+blocks:
+
+USRP  - Daughter board source generating complex baseband signal.
+CHAN  - Low pass filter to select channel bandwidth
+RFSQL - RF squelch zeroing output when input power below threshold
+AGC   - Automatic gain control leveling signal at [-1.0, +1.0]
+DEMOD - Demodulation block appropriate to selected signal type.
+        This converts the complex baseband to real audio frequencies,
+	and applies an appropriate low pass decimating filter.
+CTCSS - Optional tone squelch zeroing output when tone is not present.
+RSAMP - Resampler block to convert audio sample rate to user specified
+        sound card output rate.
+AUDIO - Audio sink for playing final output to speakers.
+
+The following are required command line parameters:
+
+-f FREQ		USRP receive frequency
+-m MOD		Modulation type, select from AM, FM, or WFM
+
+The following are optional command line parameters:
+
+-R SUBDEV       Daughter board specification, defaults to first found
+-c FREQ         Calibration offset.  Gets added to receive frequency.
+                Defaults to 0.0 Hz.
+-g GAIN         Daughterboard gain setting. Defaults to mid-range.
+-o RATE         Sound card output rate. Defaults to 32000. Useful if
+                your sound card only accepts particular sample rates.
+-r RFSQL	RF squelch in db. Defaults to -50.0.
+-p FREQ		CTCSS frequency.  Opens squelch when tone is present.
+
+Once the program is running, ctrl-break (Ctrl-C) stops operation.
+
+Please see fm_demod.py and am_demod.py for details of the demodulation
+blocks.
+"""
+
+# (usrp_decim, channel_decim, audio_decim, channel_pass, channel_stop, demod)
+demod_params = {
+		'AM'  : (250, 16, 1,  5000,   8000, blks.demod_10k0a3e_cf),
+		'FM'  : (250,  8, 4,  8000,   9000, blks.demod_20k0f3e_cf),
+		'WFM' : (250,  1, 8, 90000, 100000, blks.demod_200kf3e_cf)
+	       }
+
+class usrp_source_c(gr.hier_block):
+    """
+    Create a USRP source object supplying complex floats.
+    
+    Selects user supplied subdevice or chooses first available one.
+
+    Calibration value is the offset from the tuned frequency to 
+    the actual frequency.       
+    """
+    def __init__(self, fg, subdev_spec, decim, gain=None, calibration=0.0):
+	self._decim = decim
+        self._src = usrp.source_c()
+        if subdev_spec is None:
+            subdev_spec = usrp.pick_rx_subdevice(self._src)
+        self._subdev = usrp.selected_subdev(self._src, subdev_spec)
+        self._src.set_mux(usrp.determine_rx_mux_value(self._src, subdev_spec))
+        self._src.set_decim_rate(self._decim)
+
+	# If no gain specified, set to midrange
+	if gain is None:
+	    g = self._subdev.gain_range()
+	    gain = (g[0]+g[1])/2.0
+
+        self._subdev.set_gain(gain)
+        self._cal = calibration
+	gr.hier_block.__init__(self, fg, self._src, self._src)
+
+    def tune(self, freq):
+    	result = usrp.tune(self._src, 0, self._subdev, freq+self._cal)
+    	# TODO: deal with residual
+
+    def rate(self):
+	return self._src.adc_rate()/self._decim
+
+class app_flow_graph(gr.flow_graph):
+    def __init__(self, options, args):
+	gr.flow_graph.__init__(self)
+	self.options = options
+	self.args = args
+
+	(usrp_decim, channel_decim, audio_decim, 
+	 channel_pass, channel_stop, demod) = demod_params[options.modulation]
+
+        USRP = usrp_source_c(self, 		    # Flow graph
+			    options.rx_subdev_spec, # Daugherboard spec
+	                    usrp_decim,     	    # IF decimation ratio
+			    options.gain, 	    # Receiver gain
+			    options.calibration)    # Frequency offset
+	USRP.tune(options.frequency)
+
+	if_rate = USRP.rate()
+        channel_rate = if_rate // channel_decim
+	audio_rate = channel_rate // audio_decim
+
+	CHAN_taps = optfir.low_pass(1.0,         # Filter gain
+				   if_rate, 	 # Sample rate
+				   channel_pass, # One sided modulation bandwidth
+	                           channel_stop, # One sided channel bandwidth
+				   0.1, 	 # Passband ripple
+				   60) 		 # Stopband attenuation
+
+	CHAN = gr.freq_xlating_fir_filter_ccf(channel_decim, # Decimation rate
+	                                      CHAN_taps,     # Filter taps
+					      0.0, 	     # Offset frequency
+					      if_rate)	     # Sample rate
+
+	RFSQL = gr.pwr_squelch_cc(options.rf_squelch,    # Power threshold
+	                          125.0/channel_rate, 	 # Time constant
+				  channel_rate/20,       # 50ms rise/fall
+				  False)		 # Zero, not gate output
+
+	AGC = gr.agc_cc(1.0/channel_rate,  # Time constant
+			1.0,     	   # Reference power 
+			1.0,               # Initial gain
+			1.0)		   # Maximum gain
+
+	DEMOD = demod(self, channel_rate, audio_decim)
+
+	# From RF to audio
+        self.connect(USRP, CHAN, RFSQL, AGC, DEMOD)
+
+	# Optionally add CTCSS and RSAMP if needed
+	tail = DEMOD
+	if options.ctcss != None and options.ctcss > 60.0:
+	    CTCSS = gr.ctcss_squelch_ff(audio_rate,    # Sample rate
+				        options.ctcss) # Squelch tone
+	    self.connect(DEMOD, CTCSS)
+	    tail = CTCSS
+
+	if options.output_rate != audio_rate:
+	    out_lcm = gru.lcm(audio_rate, options.output_rate)
+	    out_interp = int(out_lcm // audio_rate)
+	    out_decim = int(out_lcm // options.output_rate)
+	    RSAMP = blks.rational_resampler_fff(self, out_interp, out_decim)
+	    self.connect(tail, RSAMP)
+	    tail = RSAMP 
+
+	# Send to default audio output
+        AUDIO = audio.sink(options.output_rate, "")
+	self.connect(tail, AUDIO)
+	
+def main():
+    parser = OptionParser(option_class=eng_option)
+    parser.add_option("-f", "--frequency", type="eng_float",
+                      help="set receive frequency to Hz", metavar="Hz")
+    parser.add_option("-R", "--rx-subdev-spec", type="subdev",
+                      help="select USRP Rx side A or B", metavar="SUBDEV")
+    parser.add_option("-c",   "--calibration", type="eng_float", default=0.0,
+                      help="set frequency offset to Hz", metavar="Hz")
+    parser.add_option("-g", "--gain", type="int", default=None,
+                      help="set RF gain", metavar="dB")
+    parser.add_option("-m", "--modulation", type="choice", choices=('AM','FM','WFM'),
+                      help="set modulation type (AM,FM)", metavar="TYPE")
+    parser.add_option("-o", "--output-rate", type="int", default=32000,
+                      help="set audio output rate to RATE", metavar="RATE")
+    parser.add_option("-r", "--rf-squelch", type="eng_float", default=-50.0,
+                      help="set RF squelch to dB", metavar="dB")
+    parser.add_option("-p", "--ctcss", type="float",
+		      help="set CTCSS squelch to FREQ", metavar="FREQ")
+    (options, args) = parser.parse_args()
+
+    if options.frequency < 1e6:
+	options.frequency *= 1e6
+	
+    fg = app_flow_graph(options, args)
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
+
+if __name__ == "__main__":
+    main()
diff --git a/gnuradio-examples/python/usrp/usrp_siggen.py b/gnuradio-examples/python/usrp/usrp_siggen.py
new file mode 100755
index 0000000000..59e01e0a9b
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_siggen.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from gnuradio import eng_notation
+from optparse import OptionParser
+import sys
+
+
+class my_graph(gr.flow_graph):
+    def __init__ (self):
+        gr.flow_graph.__init__(self)
+        
+        # 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._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.file_sink = gr.file_sink (gr.sizeof_gr_complex, "siggen.dat")
+
+    def _configure_graph (self, type):
+        was_running = self.is_running ()
+        if was_running:
+            self.stop ()
+        self.disconnect_all ()
+        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
+            self.connect (self.siggen, self.u)
+            # 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, self.u)
+            self.noisegen.set_type (type)
+            self.src = self.noisegen
+        else:
+            raise ValueError, type
+        if was_running:
+            self.start ()
+
+    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")
+
+    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=100e3,
+                       help="set waveform frequency to FREQ")
+    parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3,
+                       help="set waveform amplitude to AMPLITUDE", metavar="AMPL")
+    parser.add_option ("-o", "--offset", type="eng_float", default=0,
+                       help="set waveform offset to OFFSET")
+    (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
+
+    fg = my_graph()
+    fg.set_interpolator (options.interp)
+    fg.set_waveform_type (options.type)
+    fg.set_waveform_freq (options.waveform_freq)
+    fg.set_waveform_ampl (options.amplitude)
+    fg.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(fg.u)
+
+    m = usrp.determine_tx_mux_value(fg.u, options.tx_subdev_spec)
+    #print "mux = %#04x" % (m,)
+    fg.u.set_mux(m)
+    fg.subdev = usrp.selected_subdev(fg.u, options.tx_subdev_spec)
+    print "Using TX d'board %s" % (fg.subdev.side_and_name(),)
+    
+    fg.subdev.set_gain(fg.subdev.gain_range()[1])    # set max Tx gain
+
+    if not fg.set_freq(options.rf_freq):
+        sys.stderr.write('Failed to set RF frequency\n')
+        raise SystemExit
+    
+    fg.subdev.set_enable(True)                       # enable transmitter
+
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
+
+if __name__ == '__main__':
+    main ()
diff --git a/gnuradio-examples/python/usrp/usrp_tv_rcv.py b/gnuradio-examples/python/usrp/usrp_tv_rcv.py
new file mode 100755
index 0000000000..ed78273a7d
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_tv_rcv.py
@@ -0,0 +1,394 @@
+#!/usr/bin/env python
+"""
+Realtime capture and display of analog Tv stations.
+Can also use a file as source or sink
+When you use an output file you can show the results frame-by-frame using ImageMagick
+When you want to use the realtime sdl display window you must first install gr-video-sdl (is in gnuradio cvs).
+When you use a file source, in stead of the usrp, make sure you capture interleaved shorts.
+(Use usrp_rx_file.py, or use usrp_rx_cfile.py --output-shorts if you have a recent enough usrp_rx_cfile.py)
+There is no synchronisation yet. The sync blocks are in development but not yet in cvs.
+
+"""
+from gnuradio import gr, gru, eng_notation, optfir
+try:
+  from gnuradio import video_sdl
+except:
+  print "FYI: gr-video-sdl is not installed"
+  print "realtime SDL video output window will not be available"
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import slider, powermate
+from gnuradio.wxgui import stdgui, fftsink, form
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+import wx
+
+# To debug, insert this in your test code...
+#import os
+#print 'Blocked waiting for GDB attach (pid = %d)' % (os.getpid(),)
+#raw_input ('Press Enter to continue: ')
+# remainder of your test code follows...
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
+
+    @return a subdev_spec
+    """
+    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
+                                usrp_dbid.TV_RX_REV_2,
+                                usrp_dbid.BASIC_RX))
+
+
+class tv_rx_graph (stdgui.gui_flow_graph):
+    def __init__(self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+
+        usage="%prog: [options] [input_filename]. \n If you don't specify an input filename the usrp will be used as source\n " \
+              "Make sure your input capture file containes interleaved shorts not complex floats"
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-d", "--decim", type="int", default=64,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-f", "--freq", type="eng_float", default=519.25e6,
+                          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("-c", "--contrast", type="eng_float", default=1.0,
+                          help="set contrast (default is 1.0)")
+        parser.add_option("-b", "--brightness", type="eng_float", default=0.0,
+                          help="set brightness (default is 0)")
+        parser.add_option("-8", "--width-8", action="store_true", default=False,
+                          help="Enable 8-bit samples across USB")
+        parser.add_option("-p", "--pal", action="store_true", default=False,
+                          help="PAL video format (this is the default)")
+        parser.add_option("-n", "--ntsc", action="store_true", default=False,
+                          help="NTSC video format")
+        parser.add_option("-o", "--out-filename", type="string", default="sdl",
+                          help="For example out_raw_uchar.gray. If you don't specify an output filename you will get a video_sink_sdl realtime output window. You then need to have gr-video-sdl installed)")
+        parser.add_option("-r", "--repeat", action="store_false", default=True,
+                          help="repeat file in a loop")
+        parser.add_option("-N", "--no-hb", action="store_true", default=False,
+                          help="don't use halfband filter in usrp")
+
+        (options, args) = parser.parse_args()
+        if not ((len(args) == 1) or (len(args) == 0)):
+            parser.print_help()
+            sys.exit(1)
+        
+        if len(args) == 1:
+          filename = args[0]
+        else:
+          filename = None
+
+        self.frame = frame
+        self.panel = panel
+        
+        self.contrast = options.contrast
+        self.brightness = options.brightness
+        self.state = "FREQ"
+        self.freq = 0
+
+        # build graph
+
+        self.u=None
+
+        usrp_decim = options.decim # 32
+
+        if not (options.out_filename=="sdl"):
+          options.repeat=False
+
+        if not ((filename is None) or (filename=="usrp")):
+          self.filesource = gr.file_source(gr.sizeof_short,filename,options.repeat) # file is data source
+          self.istoc = gr.interleaved_short_to_complex()
+          self.connect(self.filesource,self.istoc)
+          adc_rate=64e6
+          self.src=self.istoc
+          options.gain=0.0
+          self.gain=0.0
+        else:
+          if options.no_hb or (options.decim<8):
+            self.fpga_filename="std_4rx_0tx.rbf" #contains 4 Rx paths without halfbands and 0 tx paths
+          else:
+            self.fpga_filename="std_2rxhb_2tx.rbf" # contains 2 Rx paths with halfband filters and 2 tx paths (the default)
+          self.u = usrp.source_c(0,fpga_filename=self.fpga_filename)                    # usrp is data source
+          if options.width_8:
+              sample_width = 8
+              sample_shift = 8
+              format = self.u.make_format(sample_width, sample_shift)
+              r = self.u.set_format(format)
+          adc_rate = self.u.adc_rate()                # 64 MS/s
+          self.u.set_decim_rate(usrp_decim)
+          if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+          self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+          self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+          print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+          if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+          self.src=self.u
+
+        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
+
+        f2uc=gr.float_to_uchar()
+        # sdl window as final sink
+        if not (options.pal or options.ntsc):
+          options.pal=True #set default to PAL
+        if options.pal:
+          lines_per_frame=625.0
+          frames_per_sec=25.0
+          show_width=768
+        elif options.ntsc:
+          lines_per_frame=525.0
+          frames_per_sec=29.97002997
+          show_width=640
+        width=int(usrp_rate/(lines_per_frame*frames_per_sec))
+        height=int(lines_per_frame)
+
+        if (options.out_filename=="sdl"):
+          #Here comes the tv screen, you have to build and install gr-video-sdl for this (subproject of gnuradio, only in cvs for now)
+          try:
+            video_sink = video_sdl.sink_uc ( frames_per_sec, width, height,0,show_width,height)
+          except:
+            print "gr-video-sdl is not installed"
+            print "realtime \"sdl\" video output window is not available"
+            raise SystemExit, 1
+          self.dst=video_sink
+        else:
+          print "You can use the imagemagick display tool to show the resulting imagesequence"
+          print "use the following line to show the demodulated TV-signal:"
+          print "display -depth 8 -size " +str(width)+ "x" + str(height) + " gray:" + options.out_filename
+          print "(Use the spacebar to advance to next frames)" 
+          options.repeat=False
+          file_sink=gr.file_sink(gr.sizeof_char, options.out_filename)
+          self.dst =file_sink 
+
+        self.agc=gr.agc_cc(1e-7,1.0,1.0) #1e-7
+        self.am_demod = gr.complex_to_mag ()
+        self.set_blacklevel=gr.add_const_ff(0.0)
+        self.invert_and_scale = gr.multiply_const_ff (0.0) #-self.contrast *128.0*255.0/(200.0)
+
+        # now wire it all together
+        #sample_rate=options.width*options.height*options.framerate
+
+        process_type='do_no_sync'
+        if process_type=='do_no_sync':
+          self.connect (self.src, self.agc,self.am_demod,self.invert_and_scale, self.set_blacklevel,f2uc,self.dst)
+        elif process_type=='do_tv_sync_adv':
+          #defaults: gr.tv_sync_adv (double sampling_freq, unsigned int tv_format,bool output_active_video_only=false, bool do_invert=false, double wanted_black_level=0.0, double wanted_white_level=255.0, double avg_alpha=0.1, double initial_gain=1.0, double initial_offset=0.0,bool debug=false)
+          self.tv_sync_adv=gr.tv_sync_adv(usrp_rate,0,False,False,0.0,255.0,0.01,1.0,0.0,False) #note, this block is not yet in cvs
+          self.connect (self.src, self.am_demod,self.invert_and_scale,self.tv_sync_adv,s2f,f2uc,self.dst) 
+        elif process_type=='do_nullsink':
+          #self.connect (self.src, self.am_demod,self.invert_and_scale,f2uc,video_sink)
+          c2r=gr.complex_to_real()
+          nullsink=gr.null_sink(gr.sizeof_float)
+          self.connect (self.src, c2r,nullsink) #video_sink)
+        elif process_type=='do_tv_sync_corr':
+          frame_size=width*height #int(usrp_rate/25.0)
+          nframes=10# 32
+          search_window=20*nframes 
+          debug=False
+          video_alpha=0.3 #0.1
+          corr_alpha=0.3
+          tv_corr=gr.tv_correlator_ff(frame_size,nframes, search_window, video_alpha, corr_alpha,debug) #Note: this block is not yet in cvs
+          shift=gr.add_const_ff(-0.7)
+          self.connect (self.src, self.agc,self.am_demod,tv_corr,self.invert_and_scale, self.set_blacklevel,f2uc,self.dst) #self.agc,
+        else: # process_type=='do_test_image':
+          src_vertical_bars = gr.sig_source_f (usrp_rate, gr.GR_SIN_WAVE, 10.0 *usrp_rate/320, 255,128)
+          self.connect(src_vertical_bars,f2uc,self.dst)
+
+        self._build_gui(vbox, usrp_rate, usrp_rate, usrp_rate)
+
+   
+        if abs(options.freq) < 1e6:
+            options.freq *= 1e6
+
+        # set initial values
+        self.set_gain(options.gain)
+        self.set_contrast(self.contrast)
+        self.set_brightness(options.brightness)
+        if not(self.set_freq(options.freq)):
+            self._set_status_msg("Failed to set initial frequency")
+
+
+    def _set_status_msg(self, msg, which=0):
+        self.frame.GetStatusBar().SetStatusText(msg, which)
+
+
+    def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate):
+
+        def _form_set_freq(kv):
+            return self.set_freq(kv['freq'])
+
+
+        if 0:
+            self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+                                               fft_size=512, sample_rate=usrp_rate)
+            self.connect (self.src, self.src_fft)
+            vbox.Add (self.src_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            post_demod_fft = fftsink.fft_sink_f (self, self.panel, title="Post Demod",
+                                                  fft_size=512, sample_rate=demod_rate,
+                                                  y_per_div=10, ref_level=-40)
+            self.connect (self.am_demod, post_demod_fft)
+            vbox.Add (post_demod_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", 
+                                                fft_size=512, sample_rate=audio_rate,
+                                                y_per_div=10, ref_level=-40)
+            self.connect (self.set_blacklevel, post_filt)
+            vbox.Add (fft_win4, 4, wx.EXPAND)
+
+        
+        # control area form at bottom
+        self.myform = myform = form.form()
+
+        if not (self.u is None):
+          hbox = wx.BoxSizer(wx.HORIZONTAL)
+          hbox.Add((5,0), 0)
+          myform['freq'] = form.float_field(
+            parent=self.panel, sizer=hbox, label="Freq", weight=1,
+            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
+
+          hbox.Add((5,0), 0)
+          myform['freq_slider'] = \
+              form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
+                                        range=(50.25e6, 900.25e6, 0.25e6),
+                                        callback=self.set_freq)
+          hbox.Add((5,0), 0)
+          vbox.Add(hbox, 0, wx.EXPAND)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+
+        myform['contrast'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Contrast",
+                                        weight=3, range=(-2.0, 2.0, 0.1),
+                                        callback=self.set_contrast)
+        hbox.Add((5,0), 1)
+
+        myform['brightness'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Brightness",
+                                        weight=3, range=(-255.0, 255.0, 1.0),
+                                        callback=self.set_brightness)
+        hbox.Add((5,0), 0)
+
+        if not (self.u is None):
+          myform['gain'] = \
+              form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain",
+                                        weight=3, range=self.subdev.gain_range(),
+                                        callback=self.set_gain)
+          hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        try:
+            self.knob = powermate.powermate(self.frame)
+            self.rot = 0
+            powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
+            powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
+        except:
+            print "FYI: No Powermate or Contour Knob found"
+
+
+    def on_rotate (self, event):
+        self.rot += event.delta
+        if (self.state == "FREQ"):
+            if self.rot >= 3:
+                self.set_freq(self.freq + .1e6)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_freq(self.freq - .1e6)
+                self.rot += 3
+        elif (self.state == "CONTRAST"):
+            step = 0.1
+            if self.rot >= 3:
+                self.set_contrast(self.contrast + step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_contrast(self.contrast - step)
+                self.rot += 3
+        else:
+            step = 1
+            if self.rot >= 3:
+                self.set_brightness(self.brightness + step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_brightness(self.brightness - step)
+                self.rot += 3
+            
+    def on_button (self, event):
+        if event.value == 0:        # button up
+            return
+        self.rot = 0
+        if self.state == "FREQ":
+            self.state = "CONTRAST"
+        elif self.state == "CONTRAST":
+            self.state = "BRIGHTNESS"
+        else:
+            self.state = "FREQ"
+        self.update_status_bar ()
+        
+
+    def set_contrast (self, contrast):
+        self.contrast = contrast
+        self.invert_and_scale.set_k(-self.contrast *128.0*255.0/(200.0))
+        self.myform['contrast'].set_value(self.contrast)
+        self.update_status_bar ()
+
+    def set_brightness (self, brightness):
+        self.brightness = brightness
+        self.set_blacklevel.set_k(self.brightness +255.0)
+        self.myform['brightness'].set_value(self.brightness)
+        self.update_status_bar ()
+                                        
+    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.
+        """
+        if not (self.u is None):
+          r = usrp.tune(self.u, 0, self.subdev, target_freq)
+          if r:
+              self.freq = target_freq
+              self.myform['freq'].set_value(target_freq)         # update displayed value
+              self.myform['freq_slider'].set_value(target_freq)  # update displayed value
+              self.update_status_bar()
+              self._set_status_msg("OK", 0)
+              return True
+
+        self._set_status_msg("Failed", 0)
+        return False
+
+    def set_gain(self, gain):
+        if not (self.u is None):
+          self.gain=gain
+          self.myform['gain'].set_value(gain)     # update displayed value
+          self.subdev.set_gain(gain)
+          self.update_status_bar()
+
+    def update_status_bar (self):
+        msg = "Setting:%s Contrast:%r Brightness:%r Gain: %r" % (self.state, self.contrast,self.brightness,self.gain)
+        self._set_status_msg(msg, 1)
+        #self.src_fft.set_baseband_freq(self.freq)
+
+        
+
+if __name__ == '__main__':
+    app = stdgui.stdapp (tv_rx_graph, "USRP TV RX black-and-white")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py b/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py
new file mode 100755
index 0000000000..e563188b9c
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+
+"""
+Reads from a file and generates PAL TV pictures in black and white
+which can be displayed using ImageMagick or realtime using gr-video-sdl
+(To capture the input file Use usrp_rx_file.py, or use usrp_rx_cfile.py --output-shorts if you have a recent enough usrp_rx_cfile.py)
+Can also use usrp directly as capture source, but then you need a higher decimation factor (64)
+and thus get a lower horizontal resulution.
+There is no synchronisation yet. The sync blocks are in development but not yet in cvs.
+
+"""
+
+from gnuradio import gr, eng_notation
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+
+try:
+  from gnuradio import video_sdl
+except:
+  print "FYI: gr-video-sdl is not installed"
+  print "realtime \"sdl\" video output window will not be available"
+
+
+class my_graph(gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        usage="%prog: [options] output_filename. \n Special output_filename \"sdl\" will use video_sink_sdl as realtime output window. " \
+              "You then need to have gr-video-sdl installed. \n" \
+              "Make sure your input capture file containes interleaved shorts not complex floats"
+        parser = OptionParser(option_class=eng_option, usage=usage)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0),
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-c", "--contrast", type="eng_float", default=1.0,
+                          help="set contrast (default is 1.0)")
+        parser.add_option("-b", "--brightness", type="eng_float", default=0.0,
+                          help="set brightness (default is 0)")
+        parser.add_option("-d", "--decim", type="int", default=8,
+                          help="set fgpa decimation rate to DECIM [default=%default]")
+        parser.add_option("-i", "--in-filename", type="string", default=None,
+                          help="Use input file as source. samples must be interleaved shorts \n " +
+                               "Use usrp_rx_file.py or usrp_rx_cfile.py --output-shorts. \n"
+                               "Special name \"usrp\"  results in realtime capturing and processing using usrp. \n" +
+                               "You then probably need a decimation factor of 64 or higher.")
+        parser.add_option("-f", "--freq", type="eng_float", default=None,
+                          help="set frequency to FREQ.\nNote that the frequency of the video carrier is not at the middle of the TV channel", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=None,
+                          help="set gain in dB (default is midpoint)")
+        parser.add_option("-p", "--pal", action="store_true", default=False,
+                          help="PAL video format (this is the default)")
+        parser.add_option("-n", "--ntsc", action="store_true", default=False,
+                          help="NTSC video format")
+        parser.add_option("-r", "--repeat", action="store_false", default=True,
+                          help="repeat in_file in a loop")
+        parser.add_option("-8", "--width-8", action="store_true", default=False,
+                          help="Enable 8-bit samples across USB")
+        parser.add_option("-N", "--nframes", type="eng_float", default=None,
+                          help="number of frames to collect [default=+inf]")
+        parser.add_option( "--no-hb", action="store_true", default=False,
+                          help="don't use halfband filter in usrp")
+        (options, args) = parser.parse_args ()
+        if not (len(args) == 1):
+            parser.print_help()
+            sys.stderr.write('You must specify the output. FILENAME or sdl \n');
+            sys.exit(1)
+        
+        filename = args[0]
+
+        if options.in_filename is None:
+            parser.print_help()
+            sys.stderr.write('You must specify the input -i FILENAME or -i usrp\n');
+            raise SystemExit, 1
+
+        if not (filename=="sdl"):
+          options.repeat=False
+
+        if not (options.in_filename=="usrp"):
+          self.filesource = gr.file_source(gr.sizeof_short,options.in_filename,options.repeat) # file is data source, capture with usr_rx_csfile.py
+          self.istoc = gr.interleaved_short_to_complex()
+          self.connect(self.filesource,self.istoc)
+          self.adc_rate=64e6
+          self.src=self.istoc
+        else:
+          if options.freq is None:
+            parser.print_help()
+            sys.stderr.write('You must specify the frequency with -f FREQ\n');
+            raise SystemExit, 1
+          if abs(options.freq) < 1e6:
+              options.freq *= 1e6
+          if options.no_hb or (options.decim<8):
+            self.fpga_filename="std_4rx_0tx.rbf" #contains 4 Rx paths without halfbands and 0 tx paths
+          else:
+            self.fpga_filename="std_2rxhb_2tx.rbf" # contains 2 Rx paths with halfband filters and 2 tx paths (the default)
+
+          # build the graph
+          self.u = usrp.source_c(decim_rate=options.decim,fpga_filename=self.fpga_filename)
+          self.src=self.u
+          if options.width_8:
+              sample_width = 8
+              sample_shift = 8
+              format = self.u.make_format(sample_width, sample_shift)
+              r = self.u.set_format(format)
+          self.adc_rate=self.u.adc_freq()
+          if options.rx_subdev_spec is None:
+              options.rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
+          self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+          # determine the daughterboard subdevice we're using
+          self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+          print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+          if options.gain is None:
+              # if no gain was specified, use the mid-point in dB
+              g = self.subdev.gain_range()
+              options.gain = float(g[0]+g[1])/2
+          self.subdev.set_gain(options.gain)
+
+          r = self.u.tune(0, self.subdev, options.freq)
+          if not r:
+              sys.stderr.write('Failed to set frequency\n')
+              raise SystemExit, 1
+
+        input_rate = self.adc_rate / options.decim
+        print "video sample rate %s" % (eng_notation.num_to_str(input_rate))
+
+        self.agc=gr.agc_cc(1e-7,1.0,1.0) #1e-7
+        self.am_demod = gr.complex_to_mag ()
+        self.set_blacklevel=gr.add_const_ff(options.brightness +255.0)
+        self.invert_and_scale = gr.multiply_const_ff (-options.contrast *128.0*255.0/(200.0))
+        self.f2uc=gr.float_to_uchar()
+
+          # sdl window as final sink
+        if not (options.pal or options.ntsc):
+          options.pal=True #set default to PAL
+        if options.pal:
+          lines_per_frame=625.0
+          frames_per_sec=25.0
+          show_width=768
+        elif options.ntsc:
+          lines_per_frame=525.0
+          frames_per_sec=29.97002997
+          show_width=640
+        width=int(input_rate/(lines_per_frame*frames_per_sec))
+        height=int(lines_per_frame)
+
+        if filename=="sdl":
+          #Here comes the tv screen, you have to build and install gr-video-sdl for this (subproject of gnuradio, only in cvs for now)
+          try:
+            video_sink = video_sdl.sink_uc ( frames_per_sec, width, height,0,show_width,height)
+          except:
+            print "gr-video-sdl is not installed"
+            print "realtime \"sdl\" video output window is not available"
+            raise SystemExit, 1
+          self.dst=video_sink
+        else:
+          print "You can use the imagemagick display tool to show the resulting imagesequence"
+          print "use the following line to show the demodulated TV-signal:"
+          print "display -depth 8 -size " +str(width)+ "x" + str(height) + " gray:" +filename
+          print "(Use the spacebar to advance to next frames)" 
+          file_sink=gr.file_sink(gr.sizeof_char, filename)
+          self.dst =file_sink 
+
+        if options.nframes is None:
+            self.connect(self.src, self.agc)
+        else:
+            self.head = gr.head(gr.sizeof_gr_complex, int(options.nframes*width*height))
+            self.connect(self.src, self.head, self.agc)
+
+        self.connect (self.agc,self.am_demod,self.invert_and_scale, self.set_blacklevel,self.f2uc,self.dst)
+
+        
+if __name__ == '__main__':
+    try:
+        my_graph().run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv.py
new file mode 100755
index 0000000000..2029107677
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import slider, powermate
+from gnuradio.wxgui import stdgui, fftsink, form
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+import wx
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
+
+    @return a subdev_spec
+    """
+    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
+                                usrp_dbid.TV_RX_REV_2,
+                                usrp_dbid.BASIC_RX))
+
+
+class wfm_rx_graph (stdgui.gui_flow_graph):
+    def __init__(self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-f", "--freq", type="eng_float", default=100.1e6,
+                          help="set frequency to FREQ", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=40,
+                          help="set gain in dB (default is midpoint)")
+        parser.add_option("-V", "--volume", type="eng_float", default=None,
+                          help="set volume (default is midpoint)")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")
+
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+        
+        self.frame = frame
+        self.panel = panel
+        
+        self.vol = 0
+        self.state = "FREQ"
+        self.freq = 0
+
+        # build graph
+        
+        self.u = usrp.source_c()                    # usrp is data source
+
+        adc_rate = self.u.adc_rate()                # 64 MS/s
+        usrp_decim = 200
+        self.u.set_decim_rate(usrp_decim)
+        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
+        chanfilt_decim = 1
+        demod_rate = usrp_rate / chanfilt_decim
+        audio_decimation = 10
+        audio_rate = demod_rate / audio_decimation  # 32 kHz
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            usrp_rate,   # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+        chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
+
+        self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+
+        self.volume_control = gr.multiply_const_ff(self.vol)
+
+        # sound card as final sink
+        audio_sink = audio.sink (int (audio_rate),
+                                 options.audio_output,
+                                 False)  # ok_to_block
+        
+        # now wire it all together
+        self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink)
+
+        self._build_gui(vbox, usrp_rate, demod_rate, audio_rate)
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+        if options.volume is None:
+            g = self.volume_range()
+            options.volume = float(g[0]+g[1])/2
+            
+        if abs(options.freq) < 1e6:
+            options.freq *= 1e6
+
+        # set initial values
+
+        self.set_gain(options.gain)
+        self.set_vol(options.volume)
+        if not(self.set_freq(options.freq)):
+            self._set_status_msg("Failed to set initial frequency")
+
+
+    def _set_status_msg(self, msg, which=0):
+        self.frame.GetStatusBar().SetStatusText(msg, which)
+
+
+    def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate):
+
+        def _form_set_freq(kv):
+            return self.set_freq(kv['freq'])
+
+
+        if 1:
+            self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+                                               fft_size=512, sample_rate=usrp_rate)
+            self.connect (self.u, self.src_fft)
+            vbox.Add (self.src_fft.win, 4, wx.EXPAND)
+
+        if 1:
+            post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Demod", 
+                                                fft_size=1024, sample_rate=usrp_rate,
+                                                y_per_div=10, ref_level=0)
+            self.connect (self.guts.fm_demod, post_filt_fft)
+            vbox.Add (post_filt_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
+                                                  fft_size=512, sample_rate=audio_rate,
+                                                  y_per_div=10, ref_level=-20)
+            self.connect (self.guts.deemph, post_deemph_fft)
+            vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)
+
+        
+        # control area form at bottom
+        self.myform = myform = form.form()
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+        myform['freq'] = form.float_field(
+            parent=self.panel, sizer=hbox, label="Freq", weight=1,
+            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
+
+        hbox.Add((5,0), 0)
+        myform['freq_slider'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
+                                        range=(87.9e6, 108.1e6, 0.1e6),
+                                        callback=self.set_freq)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+
+        myform['volume'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume",
+                                        weight=3, range=self.volume_range(),
+                                        callback=self.set_vol)
+        hbox.Add((5,0), 1)
+
+        myform['gain'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain",
+                                        weight=3, range=self.subdev.gain_range(),
+                                        callback=self.set_gain)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        try:
+            self.knob = powermate.powermate(self.frame)
+            self.rot = 0
+            powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
+            powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
+        except:
+            print "FYI: No Powermate or Contour Knob found"
+
+
+    def on_rotate (self, event):
+        self.rot += event.delta
+        if (self.state == "FREQ"):
+            if self.rot >= 3:
+                self.set_freq(self.freq + .1e6)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_freq(self.freq - .1e6)
+                self.rot += 3
+        else:
+            step = self.volume_range()[2]
+            if self.rot >= 3:
+                self.set_vol(self.vol + step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_vol(self.vol - step)
+                self.rot += 3
+            
+    def on_button (self, event):
+        if event.value == 0:        # button up
+            return
+        self.rot = 0
+        if self.state == "FREQ":
+            self.state = "VOL"
+        else:
+            self.state = "FREQ"
+        self.update_status_bar ()
+        
+
+    def set_vol (self, vol):
+        g = self.volume_range()
+        self.vol = max(g[0], min(g[1], vol))
+        self.volume_control.set_k(10**(self.vol/10))
+        self.myform['volume'].set_value(self.vol)
+        self.update_status_bar ()
+                                        
+    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.
+        """
+        r = usrp.tune(self.u, 0, self.subdev, target_freq)
+        
+        if r:
+            self.freq = target_freq
+            self.myform['freq'].set_value(target_freq)         # update displayed value
+            self.myform['freq_slider'].set_value(target_freq)  # update displayed value
+            self.update_status_bar()
+            self._set_status_msg("OK", 0)
+            return True
+
+        self._set_status_msg("Failed", 0)
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.subdev.set_gain(gain)
+
+    def update_status_bar (self):
+        msg = "Volume:%r  Setting:%s" % (self.vol, self.state)
+        self._set_status_msg(msg, 1)
+        self.src_fft.set_baseband_freq(self.freq)
+
+    def volume_range(self):
+        return (-20.0, 0.0, 0.5)
+        
+
+if __name__ == '__main__':
+    app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py
new file mode 100755
index 0000000000..40e7dd754c
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
+
+    @return a subdev_spec
+    """
+    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
+                                usrp_dbid.TV_RX_REV_2,
+                                usrp_dbid.BASIC_RX))
+
+
+class wfm_rx_graph (gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("", "--f1", type="eng_float", default=100.7e6,
+                          help="set 1st station frequency to FREQ", metavar="FREQ")
+        parser.add_option("", "--f2", type="eng_float", default=102.5e6,
+                          help="set 2nd station freq to FREQ", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=40,
+                          help="set gain in dB (default is midpoint)")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")
+
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+        
+        if abs(options.f1) < 1e6:
+            options.f1 *= 1e6
+
+        if abs(options.f2) < 1e6:
+            options.f2 *= 1e6
+
+        if abs(options.f1 - options.f2) > 5.5e6:
+            print "Sorry, two stations must be within 5.5MHz of each other"
+            raise SystemExit
+
+        f = (options.f1, options.f2)
+        
+        self.vol = .1
+        self.state = "FREQ"
+
+        # build graph
+        
+        self.u = usrp.source_c(0, nchan=2)          # usrp is data source
+
+        adc_rate = self.u.adc_rate()                # 64 MS/s
+        usrp_decim = 200
+        self.u.set_decim_rate(usrp_decim)
+        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
+        chanfilt_decim = 1
+        demod_rate = usrp_rate / chanfilt_decim
+        audio_decimation = 10
+        audio_rate = demod_rate / audio_decimation  # 32 kHz
+
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+
+        mv = usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)
+        mv |= (mv << 8) & 0xff00   # both DDC inputs setup same way
+        self.u.set_mux(mv)
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+
+        # deinterleave two channels from FPGA
+        di = gr.deinterleave(gr.sizeof_gr_complex)
+        
+        # wire up the head of the chain
+        self.connect(self.u, di)
+        
+        # sound card as final sink
+        audio_sink = audio.sink(int(audio_rate), options.audio_output)
+
+        # taps for channel filter
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            usrp_rate,   # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+
+        mid_freq = (f[0] + f[1]) / 2
+        # set front end PLL to middle frequency
+        ok, baseband_freq = self.subdev.set_freq(mid_freq)
+
+        for n in range(2):
+            chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
+            guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+            volume_control = gr.multiply_const_ff(self.vol)
+            self.connect((di, n), chan_filt)
+            self.connect(chan_filt, guts, volume_control)
+            self.connect(volume_control, (audio_sink, n))
+            dxc_freq, inverted = usrp.calc_dxc_freq(f[n], baseband_freq,
+                                                    self.u.converter_rate())
+            self.u.set_rx_freq(n, dxc_freq)
+        
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+
+        # set initial values
+        self.set_gain(options.gain)
+
+
+    def set_vol (self, vol):
+        self.vol = vol
+        self.volume_control.set_k(self.vol)
+
+
+    def set_gain(self, gain):
+        self.subdev.set_gain(gain)
+
+    
+if __name__ == '__main__':
+    fg = wfm_rx_graph()
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py
new file mode 100755
index 0000000000..69f810bba9
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
+
+    @return a subdev_spec
+    """
+    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
+                                usrp_dbid.TV_RX_REV_2,
+                                usrp_dbid.BASIC_RX))
+
+
+class wfm_rx_graph (gr.flow_graph):
+
+    def __init__(self):
+        gr.flow_graph.__init__(self)
+
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-f", "--freq", type="eng_float", default=100.1e6,
+                          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("-O", "--audio-output", type="string", default="",
+                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")
+
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+        
+        self.vol = .1
+        self.state = "FREQ"
+        self.freq = 0
+
+        # build graph
+        
+        self.u = usrp.source_c()                    # usrp is data source
+
+        adc_rate = self.u.adc_rate()                # 64 MS/s
+        usrp_decim = 200
+        self.u.set_decim_rate(usrp_decim)
+        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
+        chanfilt_decim = 1
+        demod_rate = usrp_rate / chanfilt_decim
+        audio_decimation = 10
+        audio_rate = demod_rate / audio_decimation  # 32 kHz
+
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            usrp_rate,   # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+        chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
+
+        self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+
+        self.volume_control = gr.multiply_const_ff(self.vol)
+
+        # sound card as final sink
+        audio_sink = audio.sink(int(audio_rate),
+                                options.audio_output,
+                                False)  # ok_to_block
+        
+        # now wire it all together
+        self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink)
+
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+        if abs(options.freq) < 1e6:
+            options.freq *= 1e6
+
+        # set initial values
+
+        self.set_gain(options.gain)
+
+        if not(self.set_freq(options.freq)):
+            self._set_status_msg("Failed to set initial frequency")
+
+    def set_vol (self, vol):
+        self.vol = vol
+        self.volume_control.set_k(self.vol)
+        self.update_status_bar ()
+
+    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.
+        """
+        r = self.u.tune(0, self.subdev, target_freq)
+        
+        if r:
+            self.freq = target_freq
+            self.update_status_bar()
+            self._set_status_msg("OK", 0)
+            return True
+
+        self._set_status_msg("Failed", 0)
+        return False
+
+    def set_gain(self, gain):
+        self.subdev.set_gain(gain)
+
+    def update_status_bar (self):
+        msg = "Freq: %s  Volume:%f  Setting:%s" % (
+            eng_notation.num_to_str(self.freq), self.vol, self.state)
+        self._set_status_msg(msg, 1)
+        
+    def _set_status_msg(self, msg, which=0):
+        print msg
+
+    
+if __name__ == '__main__':
+    fg = wfm_rx_graph()
+    try:
+        fg.run()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py
new file mode 100755
index 0000000000..773076ae5c
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py
@@ -0,0 +1,311 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import slider, powermate
+from gnuradio.wxgui import stdgui, fftsink, form, scopesink
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+import wx
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
+
+    @return a subdev_spec
+    """
+    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
+                                usrp_dbid.TV_RX_REV_2,
+                                usrp_dbid.BASIC_RX))
+
+class wfm_rx_graph (stdgui.gui_flow_graph):
+    def __init__(self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-f", "--freq", type="eng_float", default=100.1e6,
+                          help="set frequency to FREQ", metavar="FREQ")
+        parser.add_option("-g", "--gain", type="eng_float", default=65,
+                          help="set gain in dB (default is midpoint)")
+        parser.add_option("-s", "--squelch", type="eng_float", default=0,
+                          help="set squelch level (default is 0)")
+        parser.add_option("-V", "--volume", type="eng_float", default=None,
+                          help="set volume (default is midpoint)")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")
+
+
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+        
+        self.frame = frame
+        self.panel = panel
+        
+        self.vol = 0
+        self.state = "FREQ"
+        self.freq = 0
+
+        # build graph
+        
+        self.u = usrp.source_c()                    # usrp is data source
+
+        adc_rate = self.u.adc_rate()                # 64 MS/s
+        usrp_decim = 200
+        self.u.set_decim_rate(usrp_decim)
+        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
+        chanfilt_decim = 1
+        demod_rate = usrp_rate / chanfilt_decim
+        audio_decimation = 10
+        audio_rate = demod_rate / audio_decimation  # 32 kHz
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+
+
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            usrp_rate,   # sampling rate
+                                            80e3,        # passband cutoff
+                                            115e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+        chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
+
+
+        #self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+        self.guts = blks.wfm_rcv_pll (self, demod_rate, audio_decimation)
+
+        # FIXME rework {add,multiply}_const_* to handle multiple streams
+        self.volume_control_l = gr.multiply_const_ff(self.vol)
+        self.volume_control_r = gr.multiply_const_ff(self.vol)
+
+        # sound card as final sink
+        audio_sink = audio.sink (int (audio_rate),
+                                 options.audio_output,
+                                 False)   # ok_to_block
+        
+        # now wire it all together
+        self.connect (self.u, chan_filt, self.guts)
+        self.connect ((self.guts, 0), self.volume_control_l, (audio_sink, 0))
+        self.connect ((self.guts, 1), self.volume_control_r, (audio_sink, 1))
+        self.guts.stereo_carrier_pll_recovery.squelch_enable(True);
+
+        self._build_gui(vbox, usrp_rate, demod_rate, audio_rate)
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+        if options.volume is None:
+            g = self.volume_range()
+            options.volume = float(g[0]+g[1])/2
+
+        if abs(options.freq) < 1e6:
+            options.freq *= 1e6
+
+        # set initial values
+
+        self.set_gain(options.gain)
+        self.set_vol(options.volume)
+        self.guts.stereo_carrier_pll_recovery.set_lock_threshold(options.squelch);
+        if not(self.set_freq(options.freq)):
+            self._set_status_msg("Failed to set initial frequency")
+
+
+    def _set_status_msg(self, msg, which=0):
+        self.frame.GetStatusBar().SetStatusText(msg, which)
+
+
+    def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate):
+
+        def _form_set_freq(kv):
+            return self.set_freq(kv['freq'])
+
+
+        if 1:
+            self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+                                               fft_size=512, sample_rate=usrp_rate)
+            self.connect (self.u, self.src_fft)
+            vbox.Add (self.src_fft.win, 4, wx.EXPAND)
+
+        if 1:
+            post_fm_demod_fft = fftsink.fft_sink_f (self, self.panel, title="Post FM Demod",
+                                                  fft_size=512, sample_rate=demod_rate,
+                                                  y_per_div=10, ref_level=0)
+            self.connect (self.guts.fm_demod, post_fm_demod_fft)
+            vbox.Add (post_fm_demod_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            post_stereo_carrier_generator_fft = fftsink.fft_sink_c (self, self.panel, title="Post Stereo_carrier_generator",
+                                                  fft_size=512, sample_rate=audio_rate,
+                                                  y_per_div=10, ref_level=0)
+            self.connect (self.guts.stereo_carrier_generator, post_stereo_carrier_generator_fft)
+            vbox.Add (post_stereo_carrier_generator_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            post_deemphasis_left = fftsink.fft_sink_f (self, self.panel, title="Post_Deemphasis_Left",
+                                                  fft_size=512, sample_rate=audio_rate,
+                                                  y_per_div=10, ref_level=0)
+            self.connect (self.guts.deemph_Left, post_deemphasis_left)
+            vbox.Add (post_deemphasis_left.win, 4, wx.EXPAND)
+
+        if 0:
+            post_deemphasis_right = fftsink.fft_sink_f (self, self.panel, title="Post_Deemphasis_Right",
+                                                  fft_size=512, sample_rate=audio_rate,
+                                                  y_per_div=10, ref_level=-20)
+            self.connect (self.guts.deemph_Left, post_deemphasis_right)
+            vbox.Add (post_deemphasis_right.win, 4, wx.EXPAND)
+
+
+        if 0:
+            LmR_fft = fftsink.fft_sink_f (self, self.panel, title="LmR", 
+                                                fft_size=512, sample_rate=audio_rate,
+                                                y_per_div=10, ref_level=-20)
+            self.connect (self.guts.LmR_real,LmR_fft)
+            vbox.Add (LmR_fft.win, 4, wx.EXPAND)
+
+        if 0:
+            self.scope = scopesink.scope_sink_f(self, self.panel, sample_rate=demod_rate)
+            self.connect (self.guts.fm_demod_a,self.scope)
+            vbox.Add (self.scope.win,4,wx.EXPAND)
+        
+        # control area form at bottom
+        self.myform = myform = form.form()
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+        myform['freq'] = form.float_field(
+            parent=self.panel, sizer=hbox, label="Freq", weight=1,
+            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
+
+        hbox.Add((5,0), 0)
+        myform['freq_slider'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
+                                        range=(87.9e6, 108.1e6, 0.1e6),
+                                        callback=self.set_freq)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+
+        myform['volume'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume",
+                                        weight=3, range=self.volume_range(),
+                                        callback=self.set_vol)
+        hbox.Add((5,0), 1)
+
+        myform['gain'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain",
+                                        weight=3, range=self.subdev.gain_range(),
+                                        callback=self.set_gain)
+        hbox.Add((5,0), 0)
+
+        myform['sqlch_thrsh'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Stereo Squelch Threshold",
+                                        weight=3, range=(0.0,1.0,0.01),
+                                        callback=self.guts.stereo_carrier_pll_recovery.set_lock_threshold)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        try:
+            self.knob = powermate.powermate(self.frame)
+            self.rot = 0
+            powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
+            powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
+        except:
+            print "FYI: No Powermate or Contour Knob found"
+
+
+    def on_rotate (self, event):
+        self.rot += event.delta
+        if (self.state == "FREQ"):
+            if self.rot >= 3:
+                self.set_freq(self.freq + .1e6)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_freq(self.freq - .1e6)
+                self.rot += 3
+        else:
+            step = self.volume_range()[2]
+            if self.rot >= 3:
+                self.set_vol(self.vol + step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_vol(self.vol - step)
+                self.rot += 3
+            
+    def on_button (self, event):
+        if event.value == 0:        # button up
+            return
+        self.rot = 0
+        if self.state == "FREQ":
+            self.state = "VOL"
+        else:
+            self.state = "FREQ"
+        self.update_status_bar ()
+        
+
+    def set_vol (self, vol):
+        g = self.volume_range()
+        self.vol = max(g[0], min(g[1], vol))
+        self.volume_control_l.set_k(10**(self.vol/10))
+        self.volume_control_r.set_k(10**(self.vol/10))
+        self.myform['volume'].set_value(self.vol)
+        self.update_status_bar ()
+                                        
+    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.
+        """
+        r = usrp.tune(self.u, 0, self.subdev, target_freq)
+        
+        if r:
+            self.freq = target_freq
+            self.myform['freq'].set_value(target_freq)         # update displayed value
+            self.myform['freq_slider'].set_value(target_freq)  # update displayed value
+            self.update_status_bar()
+            self._set_status_msg("OK", 0)
+            return True
+
+        self._set_status_msg("Failed", 0)
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.subdev.set_gain(gain)
+
+    def update_status_bar (self):
+        msg = "Volume:%r  Setting:%s" % (self.vol, self.state)
+        self._set_status_msg(msg, 1)
+        self.src_fft.set_baseband_freq(self.freq)
+
+    def volume_range(self):
+        return (-20.0, 0.0, 0.5)
+        
+
+if __name__ == '__main__':
+    app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py b/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py
new file mode 100755
index 0000000000..7c04c988ae
--- /dev/null
+++ b/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import usrp
+from gnuradio import blks
+from gnuradio.eng_option import eng_option
+from gnuradio.wxgui import slider, powermate
+from gnuradio.wxgui import stdgui, fftsink, form
+from optparse import OptionParser
+import usrp_dbid
+import sys
+import math
+import wx
+
+def pick_subdevice(u):
+    """
+    The user didn't specify a subdevice on the command line.
+    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
+
+    @return a subdev_spec
+    """
+    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
+                                usrp_dbid.TV_RX_REV_2,
+                                usrp_dbid.BASIC_RX))
+
+
+class wxapt_rx_graph (stdgui.gui_flow_graph):
+    def __init__(self,frame,panel,vbox,argv):
+        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+
+        parser=OptionParser(option_class=eng_option)
+        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+                          help="select USRP Rx side A or B (default=A)")
+        parser.add_option("-f", "--freq", type="eng_float", default=137.5e6,
+                          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("-V", "--volume", type="eng_float", default=None,
+                          help="set volume (default is midpoint)")
+        parser.add_option("-O", "--audio-output", type="string", default="",
+                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")
+
+        (options, args) = parser.parse_args()
+        if len(args) != 0:
+            parser.print_help()
+            sys.exit(1)
+        
+        self.frame = frame
+        self.panel = panel
+        
+        self.vol = 0
+        self.state = "FREQ"
+        self.freq = 0
+
+        # build graph
+        
+        self.u = usrp.source_c()                    # usrp is data source
+
+        adc_rate = self.u.adc_rate()                # 64 MS/s
+        usrp_decim = 200
+        self.u.set_decim_rate(usrp_decim)
+        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
+        chanfilt_decim = 4
+        demod_rate = usrp_rate / chanfilt_decim
+        audio_decimation = 10
+        audio_rate = demod_rate / audio_decimation  # 32 kHz
+
+        if options.rx_subdev_spec is None:
+            options.rx_subdev_spec = pick_subdevice(self.u)
+
+        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
+        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
+
+
+        chan_filt_coeffs = optfir.low_pass (1,           # gain
+                                            usrp_rate,   # sampling rate
+                                            40e3,        # passband cutoff
+                                            60e3,       # stopband cutoff
+                                            0.1,         # passband ripple
+                                            60)          # stopband attenuation
+        #print len(chan_filt_coeffs)
+        chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
+
+        self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+
+        self.volume_control = gr.multiply_const_ff(self.vol)
+
+        # sound card as final sink
+        audio_sink = audio.sink (int (audio_rate), options.audio_output)
+        
+        # now wire it all together
+        self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink)
+
+        self._build_gui(vbox, usrp_rate, demod_rate, audio_rate)
+
+        if options.gain is None:
+            # if no gain was specified, use the mid-point in dB
+            g = self.subdev.gain_range()
+            options.gain = float(g[0]+g[1])/2
+
+        if options.volume is None:
+            g = self.volume_range()
+            options.volume = float(g[0]+g[1])/2
+            
+        if abs(options.freq) < 1e6:
+            options.freq *= 1e6
+
+        # set initial values
+
+        self.set_gain(options.gain)
+        self.set_vol(options.volume)
+        if not(self.set_freq(options.freq)):
+            self._set_status_msg("Failed to set initial frequency")
+
+
+    def _set_status_msg(self, msg, which=0):
+        self.frame.GetStatusBar().SetStatusText(msg, which)
+
+
+    def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate):
+
+        def _form_set_freq(kv):
+            return self.set_freq(kv['freq'])
+
+
+        if 1:
+            self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+                                               fft_size=512, sample_rate=usrp_rate)
+            self.connect (self.u, self.src_fft)
+            vbox.Add (self.src_fft.win, 4, wx.EXPAND)
+
+        if 1:
+            post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
+                                                  fft_size=512, sample_rate=demod_rate,
+                                                  y_per_div=10, ref_level=-20)
+            self.connect (self.guts.deemph, post_deemph_fft)
+            vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)
+
+        if 1:
+            post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", 
+                                                fft_size=512, sample_rate=audio_rate,
+                                                y_per_div=10, ref_level=0)
+            self.connect (self.guts.audio_filter, post_filt_fft)
+            vbox.Add (post_filt_fft.win, 4, wx.EXPAND)
+
+        
+        # control area form at bottom
+        self.myform = myform = form.form()
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+        myform['freq'] = form.float_field(
+            parent=self.panel, sizer=hbox, label="Freq", weight=1,
+            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
+
+        hbox.Add((5,0), 0)
+        myform['freq_slider'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
+                                        range=(137.0e6, 138.0e6, 0.0005e6),
+                                        callback=self.set_freq)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.Add((5,0), 0)
+
+        myform['volume'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume",
+                                        weight=3, range=self.volume_range(),
+                                        callback=self.set_vol)
+        hbox.Add((5,0), 1)
+
+        myform['gain'] = \
+            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain",
+                                        weight=3, range=self.subdev.gain_range(),
+                                        callback=self.set_gain)
+        hbox.Add((5,0), 0)
+        vbox.Add(hbox, 0, wx.EXPAND)
+
+        try:
+            self.knob = powermate.powermate(self.frame)
+            self.rot = 0
+            powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
+            powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
+        except:
+            print "FYI: No Powermate or Contour Knob found"
+
+
+    def on_rotate (self, event):
+        self.rot += event.delta
+        if (self.state == "FREQ"):
+            if self.rot >= 3:
+                self.set_freq(self.freq + .1e6)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_freq(self.freq - .1e6)
+                self.rot += 3
+        else:
+            step = self.volume_range()[2]
+            if self.rot >= 3:
+                self.set_vol(self.vol + step)
+                self.rot -= 3
+            elif self.rot <=-3:
+                self.set_vol(self.vol - step)
+                self.rot += 3
+            
+    def on_button (self, event):
+        if event.value == 0:        # button up
+            return
+        self.rot = 0
+        if self.state == "FREQ":
+            self.state = "VOL"
+        else:
+            self.state = "FREQ"
+        self.update_status_bar ()
+        
+
+    def set_vol (self, vol):
+        g = self.volume_range()
+        self.vol = max(g[0], min(g[1], vol))
+        self.volume_control.set_k(10**(self.vol/10))
+        self.myform['volume'].set_value(self.vol)
+        self.update_status_bar ()
+                                        
+    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.
+        """
+        r = usrp.tune(self.u, 0, self.subdev, target_freq)
+        
+        if r:
+            self.freq = target_freq
+            self.myform['freq'].set_value(target_freq)         # update displayed value
+            self.myform['freq_slider'].set_value(target_freq)  # update displayed value
+            self.update_status_bar()
+            self._set_status_msg("OK", 0)
+            return True
+
+        self._set_status_msg("Failed", 0)
+        return False
+
+    def set_gain(self, gain):
+        self.myform['gain'].set_value(gain)     # update displayed value
+        self.subdev.set_gain(gain)
+
+    def update_status_bar (self):
+        msg = "Volume:%r  Setting:%s" % (self.vol, self.state)
+        self._set_status_msg(msg, 1)
+        self.src_fft.set_baseband_freq(self.freq)
+
+    def volume_range(self):
+        return (-20.0, 0.0, 0.5)
+        
+
+if __name__ == '__main__':
+    app = stdgui.stdapp (wxapt_rx_graph, "USRP WXAPT RX")
+    app.MainLoop ()
diff --git a/gnuradio-examples/python/usrp/wfm_rcv_file.py b/gnuradio-examples/python/usrp/wfm_rcv_file.py
new file mode 100755
index 0000000000..2c8d4f7603
--- /dev/null
+++ b/gnuradio-examples/python/usrp/wfm_rcv_file.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, eng_notation
+from gnuradio import audio
+# from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+import math
+
+
+#
+# return a gr.flow_graph
+#
+def build_graph (input_filename, repeat):
+    adc_rate = 64e6                             # USRP A/D sampling rate
+    decim = 250                                 # FPGA decimated by this amount
+
+    quad_rate = adc_rate / decim                # 256 kHz (the sample rate of the file)
+    audio_decimation = 8
+    audio_rate = quad_rate / audio_decimation   # 32 kHz
+
+    fg = gr.flow_graph ()
+    
+    # usrp is data source
+    # src = usrp.source_c (0, decim)
+    # src.set_rx_freq (0, -IF_freq)
+
+    src = gr.file_source (gr.sizeof_gr_complex, input_filename, repeat)
+    
+    (head, tail) = build_pipeline (fg, quad_rate, audio_decimation)
+
+    # sound card as final sink
+    audio_sink = audio.sink (int (audio_rate))
+
+    # now wire it all together
+    fg.connect (src, head)
+    fg.connect (tail, (audio_sink, 0))
+    
+    return fg
+
+def build_pipeline (fg, quad_rate, audio_decimation):
+    '''Given a flow_graph, fg, construct a pipeline
+    for demodulating a broadcast FM signal.  The
+    input is the downconverteed complex baseband
+    signal. The output is the demodulated audio.
+
+    build_pipeline returns a two element tuple
+    containing the input and output endpoints.
+    '''
+    fm_demod_gain = 2200.0/32768.0
+    audio_rate = quad_rate / audio_decimation
+    volume = 1.0
+
+    # input: complex; output: float
+    fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain)
+
+    # compute FIR filter taps for audio filter
+    width_of_transition_band = audio_rate / 32
+    audio_coeffs = gr.firdes.low_pass (1.0,            # gain
+                                       quad_rate,      # sampling rate
+                                       audio_rate/2 - width_of_transition_band,
+                                       width_of_transition_band,
+                                       gr.firdes.WIN_HAMMING)
+
+    TAU  = 75e-6  # 75us in US, 50us in EUR
+    fftaps = [ 1 - math.exp(-1/TAU/quad_rate), 0]
+    fbtaps= [ 0 , math.exp(-1/TAU/quad_rate) ]
+    deemph = gr.iir_filter_ffd(fftaps,fbtaps)
+
+    # input: float; output: float
+    audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
+
+    fg.connect (fm_demod, deemph)
+    fg.connect (deemph, audio_filter)
+    return ((fm_demod, 0), (audio_filter, 0))
+    
+
+def main ():
+    usage = "usage: %prog [options] filename"
+    parser = OptionParser (option_class=eng_option, usage=usage)
+    parser.add_option ("-r", "--repeat", action="store_true", default=False)
+    # parser.add_option (... your stuff here...)
+    (options, args) = parser.parse_args ()
+
+    if len (args) != 1:
+        parser.print_help ()
+        sys.exit (1)
+
+    fg = build_graph (args[0], options.repeat)
+
+    fg.start ()        # fork thread(s) and return
+    raw_input ('Press Enter to quit: ')
+    fg.stop ()
+
+if __name__ == '__main__':
+    main ()
+
+
-- 
cgit v1.2.3