diff options
author | Tom Rondeau | 2011-10-06 18:23:58 -0400 |
---|---|---|
committer | Tom Rondeau | 2011-10-06 18:23:58 -0400 |
commit | 646f625d0b16159e03efb64409fe55ac1d07249a (patch) | |
tree | fc3938960bd5603b656f7f305658861bf7682d79 | |
parent | 3e8c3125da6234c4d1f8c0eaf869bc86923cb292 (diff) | |
parent | f9b6786c6b4ea6dd1c7435bd0dfa30ef38b727c1 (diff) | |
download | gnuradio-646f625d0b16159e03efb64409fe55ac1d07249a.tar.gz gnuradio-646f625d0b16159e03efb64409fe55ac1d07249a.tar.bz2 gnuradio-646f625d0b16159e03efb64409fe55ac1d07249a.zip |
Merge branch 'next' into digital
-rw-r--r-- | config/grc_gnuradio_examples.m4 | 6 | ||||
-rw-r--r-- | config/grc_gr_shd.m4 | 59 | ||||
-rw-r--r-- | config/grc_gr_uhd.m4 | 4 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/Makefile.am | 3 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/filter.i | 2 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc | 209 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h | 176 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i | 42 | ||||
-rw-r--r-- | gnuradio-core/src/lib/swig/gnuradio.i | 18 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py | 53 | ||||
-rwxr-xr-x | gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py | 136 | ||||
-rw-r--r-- | gnuradio-examples/python/Makefile.am | 6 | ||||
-rw-r--r-- | gnuradio-examples/python/apps/hf_explorer/README | 48 | ||||
-rw-r--r-- | gnuradio-examples/python/apps/hf_radio/input.py | 46 | ||||
-rw-r--r-- | gnuradio-examples/python/apps/hf_radio/output.py | 17 | ||||
-rw-r--r-- | gnuradio-examples/python/apps/hf_radio/ssbagc.py | 48 | ||||
-rwxr-xr-x | gnuradio-examples/python/multi-antenna/multi_fft.py | 128 | ||||
-rw-r--r-- | gnuradio-examples/python/usrp/Makefile.am | 20 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/max_power.py | 83 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/test_dft_analysis.py | 72 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/test_dft_synth.py | 78 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/usrp_benchmark_usb.py | 106 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/usrp_test_loop_lfsr.py | 62 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py | 183 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py | 177 | ||||
-rw-r--r-- | gnuradio-examples/python/usrp2/qt_wfm_interface.py | 99 | ||||
-rw-r--r-- | gnuradio-examples/python/usrp2/qt_wfm_interface.ui | 253 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp2/usrp2_wfm_qt.py | 355 | ||||
-rwxr-xr-x | gnuradio-examples/python/usrp2/usrp2_wfm_rcv.py | 289 | ||||
-rw-r--r-- | gr-audio/lib/alsa/audio_alsa_sink.cc | 16 | ||||
-rw-r--r-- | gr-audio/swig/audio_swig.i | 18 | ||||
-rw-r--r-- | gr-shd/.gitignore | 3 | ||||
-rw-r--r-- | gr-shd/Makefile.am (renamed from gnuradio-examples/python/apps/README) | 19 | ||||
-rw-r--r-- | gr-shd/apps/.gitignore | 3 | ||||
-rw-r--r-- | gr-shd/apps/Makefile.am (renamed from gnuradio-examples/python/usrp2/Makefile.am) | 16 | ||||
-rwxr-xr-x | gr-shd/apps/shd_fft.py | 280 | ||||
-rwxr-xr-x | gr-shd/apps/shd_rx_cfile.py | 152 | ||||
-rwxr-xr-x | gr-shd/apps/shd_siggen.py | 120 | ||||
-rw-r--r-- | gr-shd/gnuradio-shd.pc.in | 11 | ||||
-rw-r--r-- | gr-shd/grc/.gitignore | 3 | ||||
-rw-r--r-- | gr-shd/grc/Makefile.am | 43 | ||||
-rw-r--r-- | gr-shd/grc/gen_shd_smini_blocks.py | 297 | ||||
-rw-r--r-- | gr-shd/grc/shd_block_tree.xml | 14 | ||||
-rw-r--r-- | gr-shd/include/.gitignore (renamed from gnuradio-examples/python/apps/.gitignore) | 0 | ||||
-rw-r--r-- | gr-shd/include/Makefile.am (renamed from gnuradio-examples/python/apps/Makefile.am) | 11 | ||||
-rw-r--r-- | gr-shd/include/gr_shd_api.h | 33 | ||||
-rw-r--r-- | gr-shd/include/gr_shd_smini_sink.h | 282 | ||||
-rw-r--r-- | gr-shd/include/gr_shd_smini_source.h | 286 | ||||
-rw-r--r-- | gr-shd/lib/.gitignore (renamed from gnuradio-examples/python/usrp2/.gitignore) | 0 | ||||
-rw-r--r-- | gr-shd/lib/Makefile.am | 42 | ||||
-rw-r--r-- | gr-shd/lib/gr_shd_smini_sink.cc | 276 | ||||
-rw-r--r-- | gr-shd/lib/gr_shd_smini_source.cc | 299 | ||||
-rw-r--r-- | gr-shd/swig/.gitignore | 8 | ||||
-rw-r--r-- | gr-shd/swig/Makefile.am | 82 | ||||
-rw-r--r-- | gr-shd/swig/Makefile.swig.gen | 145 | ||||
-rw-r--r-- | gr-shd/swig/__init__.py | 88 | ||||
-rw-r--r-- | gr-shd/swig/gnuradio/.gitignore | 2 | ||||
-rw-r--r-- | gr-shd/swig/gnuradio/shd.scm | 27 | ||||
-rwxr-xr-x | gr-shd/swig/qa_shd.py | 40 | ||||
-rw-r--r-- | gr-shd/swig/run_guile_tests.in | 14 | ||||
-rw-r--r-- | gr-shd/swig/run_tests.in | 10 | ||||
-rw-r--r-- | gr-shd/swig/shd.test | 37 | ||||
-rw-r--r-- | gr-shd/swig/shd_swig.i | 135 | ||||
-rw-r--r-- | gr-uhd/Makefile.am | 2 | ||||
-rw-r--r-- | gr-uhd/apps/Makefile.am | 2 | ||||
-rw-r--r-- | gr-uhd/apps/hf_explorer/.gitignore (renamed from gnuradio-examples/python/apps/hf_explorer/.gitignore) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_explorer/Makefile.am (renamed from gnuradio-examples/python/apps/hf_explorer/Makefile.am) | 2 | ||||
-rw-r--r-- | gr-uhd/apps/hf_explorer/README | 42 | ||||
-rwxr-xr-x | gr-uhd/apps/hf_explorer/hfx.py (renamed from gnuradio-examples/python/apps/hf_explorer/hfx2.py) | 226 | ||||
-rw-r--r-- | gr-uhd/apps/hf_explorer/hfx_help (renamed from gnuradio-examples/python/apps/hf_explorer/hfx_help) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/.gitignore (renamed from gnuradio-examples/python/apps/hf_radio/.gitignore) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/Makefile.am (renamed from gnuradio-examples/python/apps/hf_radio/Makefile.am) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/README.TXT (renamed from gnuradio-examples/python/apps/hf_radio/README.TXT) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/hfir.sci (renamed from gnuradio-examples/python/apps/hf_radio/hfir.sci) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/input.py | 78 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/output.py | 42 | ||||
-rwxr-xr-x | gr-uhd/apps/hf_radio/radio.py (renamed from gnuradio-examples/python/apps/hf_radio/radio.py) | 167 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/radio.xml (renamed from gnuradio-examples/python/apps/hf_radio/radio.xml) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/ssb_taps (renamed from gnuradio-examples/python/apps/hf_radio/ssb_taps) | 0 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/ssbagc.py | 70 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/ssbdemod.py (renamed from gnuradio-examples/python/apps/hf_radio/ssbdemod.py) | 61 | ||||
-rw-r--r-- | gr-uhd/apps/hf_radio/startup.py (renamed from gnuradio-examples/python/apps/hf_radio/startup.py) | 0 | ||||
-rwxr-xr-x | gr-uhd/apps/hf_radio/ui.py (renamed from gnuradio-examples/python/apps/hf_radio/ui.py) | 21 | ||||
-rw-r--r-- | gr-uhd/examples/.gitignore | 5 | ||||
-rw-r--r-- | gr-uhd/examples/Makefile.am | 44 | ||||
-rwxr-xr-x | gr-uhd/examples/fm_tx4.py (renamed from gnuradio-examples/python/usrp/fm_tx4.py) | 106 | ||||
-rwxr-xr-x | gr-uhd/examples/fm_tx_2_daughterboards.py (renamed from gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py) | 114 | ||||
-rwxr-xr-x | gr-uhd/examples/max_power.py | 142 | ||||
-rw-r--r-- | gr-uhd/examples/multi-antenna/.gitignore (renamed from gnuradio-examples/python/multi-antenna/.gitignore) | 0 | ||||
-rw-r--r-- | gr-uhd/examples/multi-antenna/Makefile.am (renamed from gnuradio-examples/python/multi-antenna/Makefile.am) | 0 | ||||
-rwxr-xr-x | gr-uhd/examples/multi-antenna/multi_fft.py | 152 | ||||
-rwxr-xr-x | gr-uhd/examples/multi-antenna/multi_file.py (renamed from gnuradio-examples/python/multi-antenna/multi_file.py) | 0 | ||||
-rwxr-xr-x | gr-uhd/examples/multi-antenna/multi_scope.py (renamed from gnuradio-examples/python/multi-antenna/multi_scope.py) | 0 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_am_mw_rcv.py (renamed from gnuradio-examples/python/usrp/usrp_am_mw_rcv.py) | 152 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_nbfm_ptt.py (renamed from gnuradio-examples/python/usrp/usrp_nbfm_ptt.py) | 161 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_nbfm_rcv.py (renamed from gnuradio-examples/python/usrp/usrp_nbfm_rcv.py) | 143 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_spectrum_sense.py (renamed from gnuradio-examples/python/usrp/usrp_spectrum_sense.py) | 110 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_tv_rcv.py (renamed from gnuradio-examples/python/usrp/usrp_tv_rcv.py) | 202 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_tv_rcv_nogui.py (renamed from gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py) | 125 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wfm_rcv.py (renamed from gnuradio-examples/python/usrp/usrp_wfm_rcv.py) | 141 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wfm_rcv2_nogui.py | 151 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wfm_rcv_fmdet.py (renamed from gnuradio-examples/python/usrp/usrp_wfm_rcv_fmdet.py) | 135 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wfm_rcv_nogui.py | 168 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wfm_rcv_pll.py (renamed from gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py) | 140 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wfm_rcv_sca.py (renamed from gnuradio-examples/python/usrp/usrp_wfm_rcv_sca.py) | 158 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_wxapt_rcv.py (renamed from gnuradio-examples/python/usrp/usrp_wxapt_rcv.py) | 120 | ||||
-rw-r--r-- | gr-uhd/swig/uhd_swig.i | 21 | ||||
-rw-r--r-- | gruel/src/swig/pmt_swig.i | 18 |
109 files changed, 5472 insertions, 3340 deletions
diff --git a/config/grc_gnuradio_examples.m4 b/config/grc_gnuradio_examples.m4 index f5d94318e..2fccc83d1 100644 --- a/config/grc_gnuradio_examples.m4 +++ b/config/grc_gnuradio_examples.m4 @@ -28,20 +28,14 @@ AC_DEFUN([GRC_GNURADIO_EXAMPLES],[ gnuradio-examples/Makefile \ gnuradio-examples/python/Makefile \ gnuradio-examples/grc/Makefile \ - gnuradio-examples/python/apps/hf_explorer/Makefile \ - gnuradio-examples/python/apps/hf_radio/Makefile \ - gnuradio-examples/python/apps/Makefile \ gnuradio-examples/python/digital/Makefile \ gnuradio-examples/python/digital-bert/Makefile \ gnuradio-examples/python/mp-sched/Makefile \ - gnuradio-examples/python/multi-antenna/Makefile \ gnuradio-examples/python/multi_usrp/Makefile \ gnuradio-examples/python/network/Makefile \ gnuradio-examples/python/ofdm/Makefile \ gnuradio-examples/python/pfb/Makefile \ gnuradio-examples/python/tags/Makefile \ - gnuradio-examples/python/usrp/Makefile \ - gnuradio-examples/python/usrp2/Makefile \ gnuradio-examples/waveforms/Makefile \ ]) diff --git a/config/grc_gr_shd.m4 b/config/grc_gr_shd.m4 new file mode 100644 index 000000000..d09505fbf --- /dev/null +++ b/config/grc_gr_shd.m4 @@ -0,0 +1,59 @@ +dnl Copyright 2011 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 3, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, USA. + +AC_DEFUN([GRC_GR_SHD],[ + GRC_ENABLE(gr-shd) + + dnl Dont do gr-shd if gnuradio-core skipped + GRC_CHECK_DEPENDENCY(gr-shd, gnuradio-core) + + if test $passed = yes; then + dnl Don't do gr-shd if the 'shd' package is not installed + PKG_CHECK_MODULES( + [SHD], [shd >= 3.1.0 shd < 3.2.0], [], + [passed=no; AC_MSG_RESULT([gr-shd requires libshd 3.1.x])] + ) + SHD_CPPFLAGS="${SHD_CPPFLAGS} -I\${abs_top_srcdir}/gr-shd/include" + AC_SUBST(SHD_CPPFLAGS) + AC_SUBST(SHD_LIBS) + + # Use this to tell the Makefile whether to define + # GR_HAVE_SHD for swig. + fi + + AM_CONDITIONAL([GR_DEFINE_HAVE_SHD],[test $passed = yes]) + + AC_CONFIG_FILES([ \ + gr-shd/gnuradio-shd.pc \ + gr-shd/Makefile \ + gr-shd/grc/Makefile \ + gr-shd/include/Makefile \ + gr-shd/lib/Makefile \ + gr-shd/swig/Makefile \ + gr-shd/swig/run_tests \ + gr-shd/swig/run_guile_tests \ + gr-shd/apps/Makefile \ + ]) + + GRC_BUILD_CONDITIONAL(gr-shd,[ + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_shd], + [chmod +x gr-shd/swig/run_tests gr-shd/swig/run_guile_tests]) + ]) +]) diff --git a/config/grc_gr_uhd.m4 b/config/grc_gr_uhd.m4 index 111b0ae43..f2170166b 100644 --- a/config/grc_gr_uhd.m4 +++ b/config/grc_gr_uhd.m4 @@ -49,6 +49,10 @@ AC_DEFUN([GRC_GR_UHD],[ gr-uhd/swig/run_tests \ gr-uhd/swig/run_guile_tests \ gr-uhd/apps/Makefile \ + gr-uhd/apps/hf_explorer/Makefile \ + gr-uhd/apps/hf_radio/Makefile \ + gr-uhd/examples/Makefile \ + gr-uhd/examples/multi-antenna/Makefile \ ]) GRC_BUILD_CONDITIONAL(gr-uhd,[ diff --git a/configure.ac b/configure.ac index 28fac41d4..6e6d7018b 100644 --- a/configure.ac +++ b/configure.ac @@ -374,6 +374,7 @@ GRC_GR_UTILS dnl this must come after GRC_GR_WXGUI GRC_GNURADIO_EXAMPLES dnl must come after all GRC_GR_* GRC_GRC GRC_GR_UHD +GRC_GR_SHD GRC_DOCS dnl must be last # Each component is now either to be built, was skipped, will be diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 48ec55a62..c314431bf 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -215,6 +215,7 @@ libfilter_la_common_SOURCES = \ gr_pfb_decimator_ccf.cc \ gr_pfb_interpolator_ccf.cc \ gr_pfb_arb_resampler_ccf.cc \ + gr_pfb_arb_resampler_fff.cc \ gr_pfb_clock_sync_ccf.cc \ gr_pfb_clock_sync_fff.cc \ gr_dc_blocker_cc.cc \ @@ -307,6 +308,7 @@ grinclude_HEADERS = \ gr_pfb_decimator_ccf.h \ gr_pfb_interpolator_ccf.h \ gr_pfb_arb_resampler_ccf.h \ + gr_pfb_arb_resampler_fff.h \ gr_pfb_clock_sync_ccf.h \ gr_pfb_clock_sync_fff.h \ gr_dc_blocker_cc.h \ @@ -374,6 +376,7 @@ swiginclude_HEADERS = \ gr_pfb_decimator_ccf.i \ gr_pfb_interpolator_ccf.i \ gr_pfb_arb_resampler_ccf.i \ + gr_pfb_arb_resampler_fff.i \ gr_pfb_clock_sync_ccf.i \ gr_pfb_clock_sync_fff.i \ gr_dc_blocker_cc.i \ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i index 2af7fcc5c..8c3bb9eb6 100644 --- a/gnuradio-core/src/lib/filter/filter.i +++ b/gnuradio-core/src/lib/filter/filter.i @@ -36,6 +36,7 @@ #include <gr_pfb_decimator_ccf.h> #include <gr_pfb_interpolator_ccf.h> #include <gr_pfb_arb_resampler_ccf.h> +#include <gr_pfb_arb_resampler_fff.h> #include <gr_pfb_clock_sync_ccf.h> #include <gr_pfb_clock_sync_fff.h> #include <gr_dc_blocker_cc.h> @@ -57,6 +58,7 @@ %include "gr_pfb_decimator_ccf.i" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" +%include "gr_pfb_arb_resampler_fff.i" %include "gr_pfb_decimator_ccf.i" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc new file mode 100644 index 000000000..9035e67f4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc @@ -0,0 +1,209 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pfb_arb_resampler_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <cstdio> + +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size) +{ + return gnuradio::get_initial_sptr(new gr_pfb_arb_resampler_fff (rate, taps, + filter_size)); +} + + +gr_pfb_arb_resampler_fff::gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size) + : gr_block ("pfb_arb_resampler_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(float))), + d_updated (false) +{ + d_acc = 0; // start accumulator at 0 + + /* The number of filters is specified by the user as the filter size; + this is also the interpolation rate of the filter. We use it and the + rate provided to determine the decimation rate. This acts as a + rational resampler. The flt_rate is calculated as the residual + between the integer decimation rate and the real decimation rate and + will be used to determine to interpolation point of the resampling + process. + */ + d_int_rate = filter_size; + set_rate(rate); + + // Store the last filter between calls to work + d_last_filter = 0; + + d_start_index = 0; + + d_filters = std::vector<gr_fir_fff*>(d_int_rate); + d_diff_filters = std::vector<gr_fir_fff*>(d_int_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_int_rate); + for(unsigned int i = 0; i < d_int_rate; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + create_taps(taps, d_taps, d_filters); + create_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_arb_resampler_fff::~gr_pfb_arb_resampler_fff () +{ + for(unsigned int i = 0; i < d_int_rate; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_arb_resampler_fff::create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter) +{ + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_int_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(unsigned int i = 0; i < d_int_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(unsigned int j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + 1); + + d_updated = true; +} + +void +gr_pfb_arb_resampler_fff::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + // Calculate the differential taps (derivative filter) by taking the difference + // between two taps. Duplicate the last one to make both filters the same length. + float tap; + difftaps.clear(); + for(unsigned int i = 0; i < newtaps.size()-1; i++) { + tap = newtaps[i+1] - newtaps[i]; + difftaps.push_back(tap); + } + difftaps.push_back(tap); +} + +void +gr_pfb_arb_resampler_fff::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_int_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n"); + } +} + +int +gr_pfb_arb_resampler_fff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + float *out = (float *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = d_start_index; + unsigned int j; + float o0, o1; + + // Restore the last filter position + j = d_last_filter; + + // produce output as long as we can and there are enough input samples + int max_input = ninput_items[0]-(int)d_taps_per_filter; + while((i < noutput_items) && (count < max_input)) { + // start j by wrapping around mod the number of channels + while((j < d_int_rate) && (i < noutput_items)) { + // Take the current filter and derivative filter output + o0 = d_filters[j]->filter(&in[count]); + o1 = d_diff_filters[j]->filter(&in[count]); + + out[i] = o0 + o1*d_acc; // linearly interpolate between samples + i++; + + // Adjust accumulator and index into filterbank + d_acc += d_flt_rate; + j += d_dec_rate + (int)floor(d_acc); + d_acc = fmodf(d_acc, 1.0); + } + if(i < noutput_items) { // keep state for next entry + float ss = (int)(j / d_int_rate); // number of items to skip ahead by + count += ss; // we have fully consumed another input + j = j % d_int_rate; // roll filter around + } + } + + // Store the current filter position and start of next sample + d_last_filter = j; + d_start_index = std::max(0, count - ninput_items[0]); + + // consume all we've processed but no more than we can + consume_each(std::min(count, ninput_items[0])); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h new file mode 100644 index 000000000..541df8aa4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h @@ -0,0 +1,176 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_GR_PFB_ARB_RESAMPLER_FFF_H +#define INCLUDED_GR_PFB_ARB_RESAMPLER_FFF_H + +#include <gr_block.h> + +class gr_pfb_arb_resampler_fff; +typedef boost::shared_ptr<gr_pfb_arb_resampler_fff> gr_pfb_arb_resampler_fff_sptr; +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_fir_fff; + +/*! + * \class gr_pfb_arb_resampler_fff + * + * \brief Polyphase filterbank arbitrary resampler with + * float input, float output and float taps + * + * \ingroup filter_blk + * + * This block takes in a signal stream and performs arbitrary + * resampling. The resampling rate can be any real + * number <EM>r</EM>. The resampling is done by constructing + * <EM>N</EM> filters where <EM>N</EM> is the interpolation rate. We + * then calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. + * + * Using <EM>N</EM> and <EM>D</EM>, we can perform rational resampling + * where <EM>N/D</EM> is a rational number close to the input rate + * <EM>r</EM> where we have <EM>N</EM> filters and we cycle through + * them as a polyphase filterbank with a stride of <EM>D</EM> so that + * <EM>i+1 = (i + D) % N</EM>. + * + * To get the arbitrary rate, we want to interpolate between two + * points. For each value out, we take an output from the current + * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then + * linearly interpolate between the two based on the real resampling + * rate we want. + * + * The linear interpolation only provides us with an approximation to + * the real sampling rate specified. The error is a quantization error + * between the two filters we used as our interpolation points. To + * this end, the number of filters, <EM>N</EM>, used determines the + * quantization error; the larger <EM>N</EM>, the smaller the + * noise. You can design for a specified noise floor by setting the + * filter size (parameters <EM>filter_size</EM>). The size defaults to + * 32 filters, which is about as good as most implementations need. + * + * The trick with designing this filter is in how to specify the taps + * of the prototype filter. Like the PFB interpolator, the taps are + * specified using the interpolated filter rate. In this case, that + * rate is the input sample rate multiplied by the number of filters + * in the filterbank, which is also the interpolation rate. All other + * values should be relative to this rate. + * + * For example, for a 32-filter arbitrary resampler and using the + * GNU Radio's firdes utility to build the filter, we build a low-pass + * filter with a sampling rate of <EM>fs</EM>, a 3-dB bandwidth of + * <EM>BW</EM> and a transition bandwidth of <EM>TB</EM>. We can also + * specify the out-of-band attenuation to use, <EM>ATT</EM>, and the + * filter window function (a Blackman-harris window in this case). The + * first input is the gain of the filter, which we specify here as the + * interpolation rate (<EM>32</EM>). + * + * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The theory behind this block can be found in Chapter 7.5 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + +class gr_pfb_arb_resampler_fff : public gr_block +{ + private: + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + friend gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + std::vector<gr_fir_fff*> d_filters; + std::vector<gr_fir_fff*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + unsigned int d_int_rate; // the number of filters (interpolation rate) + unsigned int d_dec_rate; // the stride through the filters (decimation rate) + float d_flt_rate; // residual rate for the linear interpolation + float d_acc; + unsigned int d_last_filter; + int d_start_index; + unsigned int d_taps_per_filter; + bool d_updated; + + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param newtaps (vector of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. + * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. + */ + void create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + +public: + ~gr_pfb_arb_resampler_fff (); + + // FIXME: See about a set_taps function during runtime. + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + void set_rate (float rate) { + d_dec_rate = (unsigned int)floor(d_int_rate/rate); + d_flt_rate = (d_int_rate/rate) - d_dec_rate; + set_relative_rate(rate); + } + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i new file mode 100644 index 000000000..8c1db22c3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pfb_arb_resampler_fff); + +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_pfb_arb_resampler_fff : public gr_block +{ + private: + gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + public: + ~gr_pfb_arb_resampler_fff (); + + //void set_taps (const std::vector<float> &taps); + void print_taps(); + void set_rate (float rate); +}; diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i index 1856d5007..e365aeac7 100644 --- a/gnuradio-core/src/lib/swig/gnuradio.i +++ b/gnuradio-core/src/lib/swig/gnuradio.i @@ -26,6 +26,24 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// +// Language independent exception handler +//////////////////////////////////////////////////////////////////////// +%include exception.i + +%exception { + try { + $action + } + catch(std::exception &e) { + SWIG_exception(SWIG_RuntimeError, e.what()); + } + catch(...) { + SWIG_exception(SWIG_RuntimeError, "Unknown exception"); + } + +} + +//////////////////////////////////////////////////////////////////////// // Headers %{ diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py index 62f40582e..3aadf700b 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py @@ -73,3 +73,56 @@ class pfb_arb_resampler_ccf(gr.hier_block2): def set_rate(self, rate): self.pfb.set_rate(rate) + + +class pfb_arb_resampler_fff(gr.hier_block2): + ''' + Convenience wrapper for the polyphase filterbank arbitrary resampler. + + The block takes a single float stream in and outputs a single float + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, rate, taps=None, flt_size=32, atten=100): + gr.hier_block2.__init__(self, "pfb_arb_resampler_fff", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + self._rate = rate + self._size = flt_size + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + #self._taps = gr.firdes.low_pass_2(self._size, self._size, bw, tb, atten) + made = False + while not made: + try: + self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = gr.pfb_arb_resampler_fff(self._rate, self._taps, self._size) + #print "PFB has %d taps\n" % (len(self._taps),) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + # Note -- set_taps not implemented in base class yet + def set_taps(self, taps): + self.pfb.set_taps(taps) + + def set_rate(self, rate): + self.pfb.set_rate(rate) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py index 858b9cde6..3a93a11d6 100755 --- a/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py @@ -28,8 +28,9 @@ class wfm_rcv_fmdet(gr.hier_block2): """ Hierarchical block for demodulating a broadcast FM signal. - The input is the downconverted complex baseband signal (gr_complex). - The output is two streams of the demodulated audio (float) 0=Left, 1=Right. + The input is the downconverted complex baseband signal + (gr_complex). The output is two streams of the demodulated + audio (float) 0=Left, 1=Right. @param demod_rate: input sample rate of complex baseband input. @type demod_rate: float @@ -39,16 +40,15 @@ class wfm_rcv_fmdet(gr.hier_block2): gr.hier_block2.__init__(self, "wfm_rcv_fmdet", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(2, 2, gr.sizeof_float)) # Output signature - lowfreq = -125e3 - highfreq = 125e3 + lowfreq = -125e3/demod_rate + highfreq = 125e3/demod_rate audio_rate = demod_rate / audio_decimation - - # We assign to self so that outsiders can grab the demodulator + # We assign to self so that outsiders can grab the demodulator # if they need to. E.g., to plot its output. # # input: complex; output: float - + self.fm_demod = gr.fmdet_cf (demod_rate, lowfreq, highfreq, 0.05) # input: float; output: float @@ -62,25 +62,31 @@ class wfm_rcv_fmdet(gr.hier_block2): 15000 , width_of_transition_band, gr.firdes.WIN_HAMMING) + # input: float; output: float self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) if 1: - # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain - # We pick off the negative frequency half because we want to base band by it! - ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS + # Pick off the stereo carrier/2 with this filter. It + # attenuated 10 dB so apply 10 dB gain We pick off the + # negative frequency half because we want to base band by + # it! + ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO + ## DEEMPHASIS stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0, - demod_rate, - -19020, - -18980, - width_of_transition_band, - gr.firdes.WIN_HAMMING) + demod_rate, + -19020, + -18980, + width_of_transition_band, + gr.firdes.WIN_HAMMING) #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs) #print "stereo carrier filter ", stereo_carrier_filter_coeffs #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate - # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain + # Pick off the double side band suppressed carrier + # Left-Right audio. It is attenuated 10 dB so apply 10 dB + # gain stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0, demod_rate, @@ -90,101 +96,121 @@ class wfm_rcv_fmdet(gr.hier_block2): gr.firdes.WIN_HAMMING) #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs - # construct overlap add filter system from coefficients for stereo carrier - self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs) - - # carrier is twice the picked off carrier so arrange to do a commplex multiply + # construct overlap add filter system from coefficients + # for stereo carrier + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, + stereo_carrier_filter_coeffs) + # carrier is twice the picked off carrier so arrange to do + # a commplex multiply self.stereo_carrier_generator = gr.multiply_cc(); # Pick off the rds signal - stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0, - demod_rate, - 57000 - 1500, - 57000 + 1500, - width_of_transition_band, - gr.firdes.WIN_HAMMING) + demod_rate, + 57000 - 1500, + 57000 + 1500, + width_of_transition_band, + gr.firdes.WIN_HAMMING) #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs # construct overlap add filter system from coefficients for stereo carrier - self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs) - - - - - - + self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, + stereo_rds_filter_coeffs) self.rds_carrier_generator = gr.multiply_cc(); self.rds_signal_generator = gr.multiply_cc(); self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex); - - alpha = 5 * 0.25 * math.pi / (audio_rate) beta = alpha * alpha / 4.0 max_freq = -2.0*math.pi*18990/audio_rate; - min_freq = -2.0*math.pi*19010/audio_rate; + min_freq = -2.0*math.pi*19010/audio_rate; + self.stereo_carrier_pll_recovery = gr.pll_refout_cc(alpha,beta, + max_freq, + min_freq); + + #self.stereo_carrier_pll_recovery.squelch_enable(False) + ##pll_refout does not have squelch yet, so disabled for + #now - self.stereo_carrier_pll_recovery = gr.pll_refout_cc(alpha,beta,max_freq,min_freq); - #self.stereo_carrier_pll_recovery.squelch_enable(False) #pll_refout does not have squelch yet, so disabled for now - - - # set up mixer (multiplier) to get the L-R signal at baseband + # set up mixer (multiplier) to get the L-R signal at + # baseband self.stereo_basebander = gr.multiply_cc(); - # pick off the real component of the basebanded L-R signal. The imaginary SHOULD be zero + # pick off the real component of the basebanded L-R + # signal. The imaginary SHOULD be zero self.LmR_real = gr.complex_to_real(); self.Make_Left = gr.add_ff(); self.Make_Right = gr.sub_ff(); - self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs) + self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, + stereo_dsbsc_filter_coeffs) if 1: - # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier - self.connect (self, self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0)) + # send the real signal to complex filter to pick off the + # carrier and then to one side of a multiplier + self.connect (self, self.fm_demod, self.stereo_carrier_filter, + self.stereo_carrier_pll_recovery, + (self.stereo_carrier_generator,0)) + # send the already filtered carrier to the otherside of the carrier + # the resulting signal from this multiplier is the carrier + # with correct phase but at -38000 Hz. self.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1)) - # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz. # send the new carrier to one side of the mixer (multiplier) self.connect (self.stereo_carrier_generator, (self.stereo_basebander,0)) + # send the demphasized audio to the DSBSC pick off filter, the complex # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier - self.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1)) # the result is BASEBANDED DSBSC with phase zero! + self.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1)) - # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer + # Pick off the real part since the imaginary is + # theoretically zero and then to one side of a summer self.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0)) - #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter + + #take the same real part of the DSBSC baseband signal and + #send it to negative side of a subtracter self.connect (self.LmR_real,(self.Make_Right,1)) - # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone + # Make rds carrier by taking the squared pilot tone and + # multiplying by pilot tone self.connect (self.stereo_basebander,(self.rds_carrier_generator,0)) self.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) - # take signal, filter off rds, send into mixer 0 channel + + # take signal, filter off rds, send into mixer 0 channel self.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) - # take rds_carrier_generator output and send into mixer 1 channel + + # take rds_carrier_generator output and send into mixer 1 + # channel self.connect (self.rds_carrier_generator,(self.rds_signal_generator,1)) - # send basebanded rds signal and send into "processor" which for now is a null sink + + # send basebanded rds signal and send into "processor" + # which for now is a null sink self.connect (self.rds_signal_generator,self_rds_signal_processor) if 1: - # pick off the audio, L+R that is what we used to have and send it to the summer + # pick off the audio, L+R that is what we used to have and + # send it to the summer self.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1)) - # take the picked off L+R audio and send it to the PLUS side of the subtractor + + # take the picked off L+R audio and send it to the PLUS + # side of the subtractor self.connect(self.audio_filter,(self.Make_Right, 0)) + # The result of Make_Left gets (L+R) + (L-R) and results in 2*L # The result of Make_Right gets (L+R) - (L-R) and results in 2*R self.connect(self.Make_Left , self.deemph_Left, (self, 0)) self.connect(self.Make_Right, self.deemph_Right, (self, 1)) + # NOTE: mono support will require variable number of outputs in hier_block2s # See ticket:174 in Trac database #else: diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am index 3f1977e74..d3d20e15a 100644 --- a/gnuradio-examples/python/Makefile.am +++ b/gnuradio-examples/python/Makefile.am @@ -22,15 +22,11 @@ include $(top_srcdir)/Makefile.common SUBDIRS = \ - apps \ digital \ digital-bert \ mp-sched \ - multi-antenna \ multi_usrp \ network \ ofdm \ pfb \ - tags \ - usrp \ - usrp2 + tags diff --git a/gnuradio-examples/python/apps/hf_explorer/README b/gnuradio-examples/python/apps/hf_explorer/README deleted file mode 100644 index 5f780b3d9..000000000 --- a/gnuradio-examples/python/apps/hf_explorer/README +++ /dev/null @@ -1,48 +0,0 @@ -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_radio/input.py b/gnuradio-examples/python/apps/hf_radio/input.py deleted file mode 100644 index 5984d8254..000000000 --- a/gnuradio-examples/python/apps/hf_radio/input.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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 -from usrpm 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, - usrp_dbid.TV_RX_REV_2, - usrp_dbid.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO)) - - 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 deleted file mode 100644 index dc9caf528..000000000 --- a/gnuradio-examples/python/apps/hf_radio/output.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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/ssbagc.py b/gnuradio-examples/python/apps/hf_radio/ssbagc.py deleted file mode 100644 index fdf40bc6b..000000000 --- a/gnuradio-examples/python/apps/hf_radio/ssbagc.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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/multi-antenna/multi_fft.py b/gnuradio-examples/python/multi-antenna/multi_fft.py deleted file mode 100755 index 544445860..000000000 --- a/gnuradio-examples/python/multi-antenna/multi_fft.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/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 stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider -import wx -from usrpm import usrp_dbid -import time -import os.path -import sys - -# required FPGA that can do 4 rx channels. - - -class my_graph(stdgui2.std_top_block): - - def __init__(self, frame, panel, vbox, argv): - stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) - - 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.nddcs() < nchan: - sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( - nchan, self.u.nddcs())) - 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(0, 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 = fftsink2.fft_sink_c(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 = stdgui2.stdapp(my_graph, "Multi Scope", nstatus=1) - app.MainLoop() - -if __name__ == '__main__': - main () diff --git a/gnuradio-examples/python/usrp/Makefile.am b/gnuradio-examples/python/usrp/Makefile.am index 0ede005a0..addee0d40 100644 --- a/gnuradio-examples/python/usrp/Makefile.am +++ b/gnuradio-examples/python/usrp/Makefile.am @@ -25,22 +25,4 @@ ourdatadir = $(exampledir)/usrp dist_ourdata_SCRIPTS = \ fm_tx_2_daughterboards.py \ - fm_tx4.py \ - max_power.py \ - test_dft_analysis.py \ - test_dft_synth.py \ - usrp_benchmark_usb.py \ - usrp_nbfm_ptt.py \ - usrp_nbfm_rcv.py \ - usrp_spectrum_sense.py \ - usrp_test_loop_lfsr.py \ - usrp_tv_rcv_nogui.py \ - usrp_tv_rcv.py \ - usrp_wfm_rcv.py \ - usrp_wfm_rcv_nogui.py \ - usrp_wfm_rcv_fmdet.py \ - usrp_wfm_rcv_pll.py \ - usrp_wfm_rcv_sca.py \ - usrp_wfm_rcv2_nogui.py \ - usrp_wxapt_rcv.py \ - usrp_am_mw_rcv.py + usrp_spectrum_sense.py diff --git a/gnuradio-examples/python/usrp/max_power.py b/gnuradio-examples/python/usrp/max_power.py deleted file mode 100755 index 91005e530..000000000 --- a/gnuradio-examples/python/usrp/max_power.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -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 (): - period = 2**16 - src = gr.vector_source_s (range (-period/2, period/2, 1), True) - return src - -def build_block (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 - - tb = gr.top_block () - - 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) - tb.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) - tb.connect (usrp_rx, rx_dst0) - - return tb - -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 () - tb = build_block (options.tx_enable, options.rx_enable) - - tb.start () - raw_input ('Press Enter to quit: ') - tb.stop () - -if __name__ == '__main__': - main () diff --git a/gnuradio-examples/python/usrp/test_dft_analysis.py b/gnuradio-examples/python/usrp/test_dft_analysis.py deleted file mode 100755 index 49db6bf2a..000000000 --- a/gnuradio-examples/python/usrp/test_dft_analysis.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gru, blks2 -from gnuradio.wxgui import stdgui2, fftsink2, slider -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import wx - -class test_graph (stdgui2.std_top_block): - def __init__(self, frame, panel, vbox, argv): - stdgui2.std_top_block.__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 = blks2.analysis_filterbank(mpoints, taps) - - self.connect(mixer, thr) - self.connect(thr, analysis) - - for i in range(mpoints): - fft = fftsink2.fft_sink_c(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 = stdgui2.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 deleted file mode 100755 index 99b1c4923..000000000 --- a/gnuradio-examples/python/usrp/test_dft_synth.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gru, blks2 -from gnuradio.wxgui import stdgui2, fftsink2 -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 (stdgui2.std_top_block): - def __init__(self, frame, panel, vbox, argv): - stdgui2.std_top_block.__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/2 * [1, 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 = blks2.synthesis_filterbank(mpoints, taps) - - null_source = gr.null_source(gr.sizeof_gr_complex) - - if 1: - 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 == 1: - #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 = fftsink2.fft_sink_c(frame, fft_size=1024,sample_rate=sample_rate) - vbox.Add(fft.win, 1, wx.EXPAND) - - self.connect(synth, thr, fft) - - -def main (): - app = stdgui2.stdapp (test_graph, "Test DFT filterbank") - app.MainLoop () - -if __name__ == '__main__': - main () diff --git a/gnuradio-examples/python/usrp/usrp_benchmark_usb.py b/gnuradio-examples/python/usrp/usrp_benchmark_usb.py deleted file mode 100755 index 4ea84f764..000000000 --- a/gnuradio-examples/python/usrp/usrp_benchmark_usb.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/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 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -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) - - tb = gr.top_block () - - # 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) - tb.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 () - tb.connect (usrp_rx, head, check) - - tb.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/usrp_test_loop_lfsr.py b/gnuradio-examples/python/usrp/usrp_test_loop_lfsr.py deleted file mode 100755 index 696c1a24c..000000000 --- a/gnuradio-examples/python/usrp/usrp_test_loop_lfsr.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -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 - - tb = gr.top_block () - - 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) - - tb.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 () - tb.connect (usrp_rx, sink) - - # file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat") - # tb.connect (usrp_rx, file_sink) - - return tb - -def main (): - tb = build_graph () - try: - tb.run() - except KeyboardInterrupt: - pass - -if __name__ == '__main__': - main () diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py deleted file mode 100755 index edfbc3657..000000000 --- a/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2006,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 -from gnuradio.eng_option import eng_option -from optparse import OptionParser -from usrpm import usrp_dbid -import sys -import math - -def calc_dxc_freq(target_freq, baseband_freq, fs): - dxc_temp = (target_freq - baseband_freq) % fs - - if dxc_temp < fs/2.0: - dxc_freq = - dxc_temp - inverted = False - else: - dxc_freq = fs - dxc_temp - inverted = True - - return (dxc_freq, inverted) - -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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - - -class wfm_rx_block (gr.top_block): - - def __init__(self): - gr.top_block.__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 - tune_result = self.subdev.set_freq(mid_freq) - - for n in range(2): - chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) - guts = blks2.wfm_rcv (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 = calc_dxc_freq(f[n], tune_result.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) - - def __del__(self): - # Avoid weak-reference error - del self.subdev - -if __name__ == '__main__': - tb = wfm_rx_block() - try: - tb.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 deleted file mode 100755 index 217f207c5..000000000 --- a/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2006,2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 -from gnuradio.eng_option import eng_option -from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - - -class wfm_rx_block (gr.top_block): - - def __init__(self): - gr.top_block.__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 = blks2.wfm_rcv (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__': - tb = wfm_rx_block() - try: - tb.run() - except KeyboardInterrupt: - pass diff --git a/gnuradio-examples/python/usrp2/qt_wfm_interface.py b/gnuradio-examples/python/usrp2/qt_wfm_interface.py deleted file mode 100644 index 4c4367ed0..000000000 --- a/gnuradio-examples/python/usrp2/qt_wfm_interface.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'qt_wfm_interface.ui' -# -# Created: Thu Jun 18 23:41:03 2009 -# by: PyQt4 UI code generator 4.4.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -class Ui_InterfaceWindow(object): - def setupUi(self, InterfaceWindow): - InterfaceWindow.setObjectName("InterfaceWindow") - InterfaceWindow.resize(909, 711) - self.centralwidget = QtGui.QWidget(InterfaceWindow) - self.centralwidget.setObjectName("centralwidget") - self.closeButton = QtGui.QPushButton(self.centralwidget) - self.closeButton.setGeometry(QtCore.QRect(790, 580, 101, 31)) - self.closeButton.setObjectName("closeButton") - self.sinkFrame = QtGui.QFrame(self.centralwidget) - self.sinkFrame.setGeometry(QtCore.QRect(10, 10, 891, 501)) - self.sinkFrame.setFrameShape(QtGui.QFrame.StyledPanel) - self.sinkFrame.setFrameShadow(QtGui.QFrame.Raised) - self.sinkFrame.setObjectName("sinkFrame") - self.horizontalLayoutWidget = QtGui.QWidget(self.sinkFrame) - self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 871, 481)) - self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") - self.sinkLayout = QtGui.QHBoxLayout(self.horizontalLayoutWidget) - self.sinkLayout.setObjectName("sinkLayout") - self.channelModeBox = QtGui.QGroupBox(self.centralwidget) - self.channelModeBox.setGeometry(QtCore.QRect(10, 520, 261, 131)) - self.channelModeBox.setObjectName("channelModeBox") - self.bandwidthabel = QtGui.QLabel(self.channelModeBox) - self.bandwidthabel.setGeometry(QtCore.QRect(10, 90, 101, 17)) - self.bandwidthabel.setObjectName("bandwidthabel") - self.bandwidthEdit = QtGui.QLineEdit(self.channelModeBox) - self.bandwidthEdit.setGeometry(QtCore.QRect(130, 90, 113, 23)) - self.bandwidthEdit.setObjectName("bandwidthEdit") - self.gainEdit = QtGui.QLineEdit(self.channelModeBox) - self.gainEdit.setGeometry(QtCore.QRect(130, 60, 113, 23)) - self.gainEdit.setObjectName("gainEdit") - self.gainLabel = QtGui.QLabel(self.channelModeBox) - self.gainLabel.setGeometry(QtCore.QRect(10, 60, 111, 20)) - self.gainLabel.setObjectName("gainLabel") - self.freqEdit = QtGui.QLineEdit(self.channelModeBox) - self.freqEdit.setGeometry(QtCore.QRect(130, 30, 113, 23)) - self.freqEdit.setObjectName("freqEdit") - self.freqLabel = QtGui.QLabel(self.channelModeBox) - self.freqLabel.setGeometry(QtCore.QRect(10, 30, 111, 17)) - self.freqLabel.setObjectName("freqLabel") - self.pauseButton = QtGui.QPushButton(self.centralwidget) - self.pauseButton.setGeometry(QtCore.QRect(790, 520, 101, 31)) - self.pauseButton.setObjectName("pauseButton") - self.fmBox = QtGui.QGroupBox(self.centralwidget) - self.fmBox.setGeometry(QtCore.QRect(290, 520, 251, 131)) - self.fmBox.setObjectName("fmBox") - self.volumeEdit = QtGui.QLineEdit(self.fmBox) - self.volumeEdit.setGeometry(QtCore.QRect(130, 20, 113, 23)) - self.volumeEdit.setObjectName("volumeEdit") - self.volumeLabel = QtGui.QLabel(self.fmBox) - self.volumeLabel.setGeometry(QtCore.QRect(10, 20, 111, 17)) - self.volumeLabel.setObjectName("volumeLabel") - InterfaceWindow.setCentralWidget(self.centralwidget) - self.menubar = QtGui.QMenuBar(InterfaceWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 909, 24)) - self.menubar.setObjectName("menubar") - self.menuFile = QtGui.QMenu(self.menubar) - self.menuFile.setObjectName("menuFile") - InterfaceWindow.setMenuBar(self.menubar) - self.statusbar = QtGui.QStatusBar(InterfaceWindow) - self.statusbar.setObjectName("statusbar") - InterfaceWindow.setStatusBar(self.statusbar) - self.actionExit = QtGui.QAction(InterfaceWindow) - self.actionExit.setObjectName("actionExit") - self.menuFile.addAction(self.actionExit) - self.menubar.addAction(self.menuFile.menuAction()) - - self.retranslateUi(InterfaceWindow) - QtCore.QObject.connect(self.closeButton, QtCore.SIGNAL("clicked()"), InterfaceWindow.close) - QtCore.QObject.connect(self.actionExit, QtCore.SIGNAL("triggered()"), InterfaceWindow.close) - QtCore.QMetaObject.connectSlotsByName(InterfaceWindow) - InterfaceWindow.setTabOrder(self.closeButton, self.gainEdit) - InterfaceWindow.setTabOrder(self.gainEdit, self.freqEdit) - InterfaceWindow.setTabOrder(self.freqEdit, self.bandwidthEdit) - - def retranslateUi(self, InterfaceWindow): - InterfaceWindow.setWindowTitle(QtGui.QApplication.translate("InterfaceWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) - self.closeButton.setText(QtGui.QApplication.translate("InterfaceWindow", "Close", None, QtGui.QApplication.UnicodeUTF8)) - self.channelModeBox.setTitle(QtGui.QApplication.translate("InterfaceWindow", "USRP Parameters", None, QtGui.QApplication.UnicodeUTF8)) - self.bandwidthabel.setText(QtGui.QApplication.translate("InterfaceWindow", "Bandwidth (Hz)", None, QtGui.QApplication.UnicodeUTF8)) - self.gainLabel.setText(QtGui.QApplication.translate("InterfaceWindow", "Gain (dB)", None, QtGui.QApplication.UnicodeUTF8)) - self.freqLabel.setText(QtGui.QApplication.translate("InterfaceWindow", "Frequency", None, QtGui.QApplication.UnicodeUTF8)) - self.pauseButton.setText(QtGui.QApplication.translate("InterfaceWindow", "Pause", None, QtGui.QApplication.UnicodeUTF8)) - self.fmBox.setTitle(QtGui.QApplication.translate("InterfaceWindow", "FM Tuner Parameters", None, QtGui.QApplication.UnicodeUTF8)) - self.volumeLabel.setText(QtGui.QApplication.translate("InterfaceWindow", "Volume", None, QtGui.QApplication.UnicodeUTF8)) - self.menuFile.setTitle(QtGui.QApplication.translate("InterfaceWindow", "&File", None, QtGui.QApplication.UnicodeUTF8)) - self.actionExit.setText(QtGui.QApplication.translate("InterfaceWindow", "E&xit", None, QtGui.QApplication.UnicodeUTF8)) - diff --git a/gnuradio-examples/python/usrp2/qt_wfm_interface.ui b/gnuradio-examples/python/usrp2/qt_wfm_interface.ui deleted file mode 100644 index 16902d9f4..000000000 --- a/gnuradio-examples/python/usrp2/qt_wfm_interface.ui +++ /dev/null @@ -1,253 +0,0 @@ -<ui version="4.0" > - <class>InterfaceWindow</class> - <widget class="QMainWindow" name="InterfaceWindow" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>909</width> - <height>711</height> - </rect> - </property> - <property name="windowTitle" > - <string>MainWindow</string> - </property> - <widget class="QWidget" name="centralwidget" > - <widget class="QPushButton" name="closeButton" > - <property name="geometry" > - <rect> - <x>790</x> - <y>580</y> - <width>101</width> - <height>31</height> - </rect> - </property> - <property name="text" > - <string>Close</string> - </property> - </widget> - <widget class="QFrame" name="sinkFrame" > - <property name="geometry" > - <rect> - <x>10</x> - <y>10</y> - <width>891</width> - <height>501</height> - </rect> - </property> - <property name="frameShape" > - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>QFrame::Raised</enum> - </property> - <widget class="QWidget" name="horizontalLayoutWidget" > - <property name="geometry" > - <rect> - <x>10</x> - <y>10</y> - <width>871</width> - <height>481</height> - </rect> - </property> - <layout class="QHBoxLayout" name="sinkLayout" /> - </widget> - </widget> - <widget class="QGroupBox" name="channelModeBox" > - <property name="geometry" > - <rect> - <x>10</x> - <y>520</y> - <width>261</width> - <height>131</height> - </rect> - </property> - <property name="title" > - <string>USRP Parameters</string> - </property> - <widget class="QLabel" name="bandwidthabel" > - <property name="geometry" > - <rect> - <x>10</x> - <y>90</y> - <width>101</width> - <height>17</height> - </rect> - </property> - <property name="text" > - <string>Bandwidth (Hz)</string> - </property> - </widget> - <widget class="QLineEdit" name="bandwidthEdit" > - <property name="geometry" > - <rect> - <x>130</x> - <y>90</y> - <width>113</width> - <height>23</height> - </rect> - </property> - </widget> - <widget class="QLineEdit" name="gainEdit" > - <property name="geometry" > - <rect> - <x>130</x> - <y>60</y> - <width>113</width> - <height>23</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="gainLabel" > - <property name="geometry" > - <rect> - <x>10</x> - <y>60</y> - <width>111</width> - <height>20</height> - </rect> - </property> - <property name="text" > - <string>Gain (dB)</string> - </property> - </widget> - <widget class="QLineEdit" name="freqEdit" > - <property name="geometry" > - <rect> - <x>130</x> - <y>30</y> - <width>113</width> - <height>23</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="freqLabel" > - <property name="geometry" > - <rect> - <x>10</x> - <y>30</y> - <width>111</width> - <height>17</height> - </rect> - </property> - <property name="text" > - <string>Frequency</string> - </property> - </widget> - </widget> - <widget class="QPushButton" name="pauseButton" > - <property name="geometry" > - <rect> - <x>790</x> - <y>520</y> - <width>101</width> - <height>31</height> - </rect> - </property> - <property name="text" > - <string>Pause</string> - </property> - </widget> - <widget class="QGroupBox" name="fmBox" > - <property name="geometry" > - <rect> - <x>290</x> - <y>520</y> - <width>251</width> - <height>131</height> - </rect> - </property> - <property name="title" > - <string>FM Tuner Parameters</string> - </property> - <widget class="QLineEdit" name="volumeEdit" > - <property name="geometry" > - <rect> - <x>130</x> - <y>20</y> - <width>113</width> - <height>23</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="volumeLabel" > - <property name="geometry" > - <rect> - <x>10</x> - <y>20</y> - <width>111</width> - <height>17</height> - </rect> - </property> - <property name="text" > - <string>Volume</string> - </property> - </widget> - </widget> - </widget> - <widget class="QMenuBar" name="menubar" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>909</width> - <height>24</height> - </rect> - </property> - <widget class="QMenu" name="menuFile" > - <property name="title" > - <string>&File</string> - </property> - <addaction name="actionExit" /> - </widget> - <addaction name="menuFile" /> - </widget> - <widget class="QStatusBar" name="statusbar" /> - <action name="actionExit" > - <property name="text" > - <string>E&xit</string> - </property> - </action> - </widget> - <tabstops> - <tabstop>closeButton</tabstop> - <tabstop>gainEdit</tabstop> - <tabstop>freqEdit</tabstop> - <tabstop>bandwidthEdit</tabstop> - </tabstops> - <resources/> - <connections> - <connection> - <sender>closeButton</sender> - <signal>clicked()</signal> - <receiver>InterfaceWindow</receiver> - <slot>close()</slot> - <hints> - <hint type="sourcelabel" > - <x>322</x> - <y>623</y> - </hint> - <hint type="destinationlabel" > - <x>66</x> - <y>561</y> - </hint> - </hints> - </connection> - <connection> - <sender>actionExit</sender> - <signal>triggered()</signal> - <receiver>InterfaceWindow</receiver> - <slot>close()</slot> - <hints> - <hint type="sourcelabel" > - <x>-1</x> - <y>-1</y> - </hint> - <hint type="destinationlabel" > - <x>617</x> - <y>327</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/gnuradio-examples/python/usrp2/usrp2_wfm_qt.py b/gnuradio-examples/python/usrp2/usrp2_wfm_qt.py deleted file mode 100755 index 0c7476921..000000000 --- a/gnuradio-examples/python/usrp2/usrp2_wfm_qt.py +++ /dev/null @@ -1,355 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2006,2007,2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp2 -from gnuradio import blks2 -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import sys -import math - - -try: - from gnuradio.qtgui import qtgui - from PyQt4 import QtGui, QtCore - import sip -except ImportError: - print "Please install gr-qtgui." - sys.exit(1) - -try: - from qt_wfm_interface import Ui_InterfaceWindow -except ImportError: - print "Error: could not find qt_wfm_interface.py:" - print "\tPlease run: \"pyuic4 qt_wfm_interface.ui -o qt_wfm_interface.py\"" - sys.exit(1) - -print "This program is not in a proper working state. Comment this out if you want to play." -sys.exit(1) - - -# //////////////////////////////////////////////////////////////////// -# Define the QT Interface and Control Dialog -# //////////////////////////////////////////////////////////////////// - - -class dialog_box(QtGui.QMainWindow): - def __init__(self, snk_usrp, snk_vol, fg, parent=None): - - QtGui.QWidget.__init__(self, parent) - self.gui = Ui_InterfaceWindow() - self.gui.setupUi(self) - - self.fg = fg - - # Set USRP parameters - self.set_bw(self.fg.usrp_bw()) - self.set_freq(self.fg.freq()) - self.set_gain(self.fg.gain()) - self.set_volume(self.fg.volume()) - - # Add the qtsnk widgets to the hlayout box - self.gui.sinkLayout.addWidget(snk_usrp) - self.gui.sinkLayout.addWidget(snk_vol) - - - # Connect up some signals - self.connect(self.gui.pauseButton, QtCore.SIGNAL("clicked()"), - self.pauseFg) - - self.connect(self.gui.bandwidthEdit, QtCore.SIGNAL("editingFinished()"), - self.bwEditText) - self.connect(self.gui.freqEdit, QtCore.SIGNAL("editingFinished()"), - self.freqEditText) - self.connect(self.gui.gainEdit, QtCore.SIGNAL("editingFinished()"), - self.gainEditText) - - self.connect(self.gui.volumeEdit, QtCore.SIGNAL("editingFinished()"), - self.volumeEditText) - - - def pauseFg(self): - if(self.gui.pauseButton.text() == "Pause"): - self.fg.stop() - self.fg.wait() - self.gui.pauseButton.setText("Unpause") - else: - self.fg.start() - self.gui.pauseButton.setText("Pause") - - - # Accessor functions for Gui to manipulate USRP - def set_bw(self, bw): - self.gui.bandwidthEdit.setText(QtCore.QString("%1").arg(bw)) - - def set_freq(self, freq): - self.gui.freqEdit.setText(QtCore.QString("%1").arg(freq)) - - def set_gain(self, gain): - self.gui.gainEdit.setText(QtCore.QString("%1").arg(gain)) - - def set_volume(self, vol): - self.gui.volumeEdit.setText(QtCore.QString("%1").arg(vol)) - - def bwEditText(self): - try: - bw = self.gui.bandwidthEdit.text().toDouble()[0] - self.fg.set_usrp_bw(bw) - except RuntimeError: - pass - - def freqEditText(self): - try: - freq = self.gui.freqEdit.text().toDouble()[0] - self.fg.set_freq(freq) - except RuntimeError: - pass - - def gainEditText(self): - try: - gain = self.gui.gainEdit.text().toDouble()[0] - self.fg.set_gain(gain) - except RuntimeError: - pass - - def volumeEditText(self): - try: - vol = self.gui.volumeEdit.text().toDouble()[0] - self.fg.set_volume(vol) - except RuntimeError: - pass - - - - -# //////////////////////////////////////////////////////////////////// -# Define the GNU Radio Top Block -# //////////////////////////////////////////////////////////////////// - - -class wfm_rx_block (gr.top_block): - def __init__(self): - gr.top_block.__init__(self) - - parser = OptionParser(option_class=eng_option) - parser.add_option("-e", "--interface", type="string", default="eth0", - help="select Ethernet interface, default is eth0") - parser.add_option("-m", "--mac-addr", type="string", default="", - help="select USRP by MAC address, default is auto-select") - #parser.add_option("-A", "--antenna", default=None, - # help="select Rx Antenna (only on RFX-series boards)") - parser.add_option("-f", "--freq", type="eng_float", default=100.1, - 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._volume = options.volume - self._usrp_freq = options.freq - self._usrp_gain = options.gain - self._audio_rate = int(32e3) - - # build graph - - self.u = usrp2.source_32fc(options.interface, options.mac_addr) - - # calculate decimation values to get USRP BW at 320 kHz - self.calculate_usrp_bw(320e3) - - self.set_decim(self._usrp_decim) - - #FIXME: need named constants and text descriptions available to (gr-)usrp2 even - #when usrp(1) module is not built. A usrp_common module, perhaps? - dbid = self.u.daughterboard_id() - print "Using RX d'board 0x%04X" % (dbid,) - #if not (dbid == 0x0001 or #usrp_dbid.BASIC_RX - # dbid == 0x0003 or #usrp_dbid.TV_RX - # dbid == 0x000c or #usrp_dbid.TV_RX_REV_2 - # dbid == 0x0040 or #usrp_dbid.TV_RX_REV_3 - # dbid == 0x0043 or #usrp_dbid.TV_RX_MIMO - # dbid == 0x0044 or #usrp_dbid.TV_RX_REV_2_MIMO - # dbid == 0x0045 ): #usrp_dbid.TV_RX_REV_3_MIMO - # print "This daughterboard does not cover the required frequency range" - # print "for this application. Please use a BasicRX or TVRX daughterboard." - # raw_input("Press ENTER to continue anyway, or Ctrl-C to exit.") - - chan_filt_coeffs = optfir.low_pass (1, # gain - self._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 (self._chanfilt_decim, chan_filt_coeffs) - - self.guts = blks2.wfm_rcv (self._demod_rate, self._audio_decim) - - self.volume_control = gr.multiply_const_ff(1) - - # sound card as final sink - #audio_sink = audio.sink (int (audio_rate), - # options.audio_output, - # False) # ok_to_block - audio_sink = audio.sink (self._audio_rate, - options.audio_output) - - - if self._usrp_gain is None: - # if no gain was specified, use the mid-point in dB - g = self.u.gain_range() - print "Gain range: ", g - self._usrp_gain = float(g[0]+g[1])/2 - - if self._volume is None: - g = self.volume_range() - self._volume = float(g[0]+g[1])/2 - - if abs(self._usrp_freq) < 1e6: - self._usrp_freq *= 1e6 - - # set initial values - self.set_gain(self._usrp_gain) - self.set_volume(self._volume) - if not(self.set_freq(self._usrp_freq)): - print ("Failed to set initial frequency") - - - # Define a GUI sink to display the received signal - self.qapp = QtGui.QApplication(sys.argv) - fftsize = 2048 - - self.usrp_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, - -self._usrp_rate/2.0, self._usrp_rate/2.0, - "Received Signal", True, True, False, True, False, - use_openGL=False) - self.usrp_rx2 = qtgui.sink_f(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, - -self._usrp_rate/2.0, self._usrp_rate/2.0, - "Received Signal", True, True, False, True, False) - - # now wire it all together - self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) - self.connect (self.u, self.usrp_rx) - self.connect (self.volume_control, self.usrp_rx2) - - usrp_rx_widget = sip.wrapinstance(self.usrp_rx.pyqwidget(), QtGui.QWidget) - usrp_rx2_widget = sip.wrapinstance(self.usrp_rx2.pyqwidget(), QtGui.QWidget) - - self.main_box = dialog_box(usrp_rx_widget, usrp_rx2_widget, self) - self.main_box.show() - - - def calculate_usrp_bw(self, bw): - """ - Calculate the different decimation rates that make the USRP BW equal to the - input bandwidth parameter 'bw' and the audio bandwidth equal to the system- - wide bandwidth 'self._audio_rate' - """ - - adc_rate = self.u.adc_rate() - d_usrp = int(adc_rate/bw) - bw_real = adc_rate / float(d_usrp) - - d_chan = 1 - demod_rate = bw_real / d_chan - - d_audio = int(bw_real / self._audio_rate) - audio_rate = demod_rate / d_audio - - self._usrp_decim = d_usrp - self._chanfilt_decim = d_chan - self._audio_decim = d_audio - self._demod_rate = demod_rate - self._usrp_rate = bw_real - - print "USRP Decimation: ", self._usrp_decim - print "USRP Bandwidth: ", bw_real - print "Audio Decimation: ", self._audio_decim - print "Audio Bandwidth: ", audio_rate - - def set_volume (self, vol): - g = self.volume_range() - self._volume = max(g[0], min(g[1], vol)) - self.volume_control.set_k(10**(self._volume/10)) - - 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.set_center_freq(target_freq) - if r: - self._usrp_freq = target_freq - return True - return False - - def set_usrp_bw(self, bw): - self.calculate_usrp_bw(bw) - - def set_gain(self, gain): - self._usrp_gain = gain - self.u.set_gain(gain) - - def set_decim(self, decim): - self._usrp_decim = int(decim) - self.u.set_decim(self._usrp_decim) - - def volume(self): - return self._volume - - def freq(self): - return self._usrp_freq - - def usrp_bw(self): - return self._usrp_rate - - def gain(self): - return self._usrp_gain - - def decim(self): - return self._usrp_decim - - def volume_range(self): - return (-20.0, 0.0, 0.5) - - -if __name__ == '__main__': - tb = wfm_rx_block() - tb.start() - tb.qapp.exec_() - diff --git a/gnuradio-examples/python/usrp2/usrp2_wfm_rcv.py b/gnuradio-examples/python/usrp2/usrp2_wfm_rcv.py deleted file mode 100755 index 2b94c458e..000000000 --- a/gnuradio-examples/python/usrp2/usrp2_wfm_rcv.py +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2006,2007,2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp2 -from gnuradio import blks2 -from gnuradio.eng_option import eng_option -from gnuradio.wxgui import slider, powermate -from gnuradio.wxgui import stdgui2, fftsink2, form -from optparse import OptionParser -import sys -import math -import wx - -class wfm_rx_block (stdgui2.std_top_block): - def __init__(self,frame,panel,vbox,argv): - stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) - - parser = OptionParser(option_class=eng_option) - parser.add_option("-e", "--interface", type="string", default="eth0", - help="select Ethernet interface, default is eth0") - parser.add_option("-m", "--mac-addr", type="string", default="", - help="select USRP by MAC address, default is auto-select") - #parser.add_option("-A", "--antenna", default=None, - # help="select Rx Antenna (only on RFX-series boards)") - parser.add_option("-f", "--freq", type="eng_float", default=100.1, - 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 = usrp2.source_32fc(options.interface, options.mac_addr) - - adc_rate = self.u.adc_rate() # 100 MS/s - usrp_decim = 312 - self.u.set_decim(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 - - #FIXME: need named constants and text descriptions available to (gr-)usrp2 even - #when usrp(1) module is not built. A usrp_common module, perhaps? - dbid = self.u.daughterboard_id() - print "Using RX d'board 0x%04X" % (dbid,) - if not (dbid == 0x0001 or #usrp_dbid.BASIC_RX - dbid == 0x0003 or #usrp_dbid.TV_RX - dbid == 0x000c or #usrp_dbid.TV_RX_REV_2 - dbid == 0x0040 or #usrp_dbid.TV_RX_REV_3 - dbid == 0x0043 or #usrp_dbid.TV_RX_MIMO - dbid == 0x0044 or #usrp_dbid.TV_RX_REV_2_MIMO - dbid == 0x0045 or #usrp_dbid.TV_RX_REV_3_MIMO - dbid == 0x0053 ): #usrp_dbid.WBX - print "This daughterboard does not cover the required frequency range" - print "for this application. Please use a BasicRX or TVRX daughterboard." - raw_input("Press ENTER to continue anyway, or Ctrl-C to exit.") - - 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 = blks2.wfm_rcv (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.u.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 = fftsink2.fft_sink_c(self.panel, title="Data from USRP2", - fft_size=512, sample_rate=usrp_rate, - ref_scale=1.0, ref_level=0, y_divs=12) - self.connect (self.u, self.src_fft) - vbox.Add (self.src_fft.win, 4, wx.EXPAND) - - if 1: - post_filt_fft = fftsink2.fft_sink_f(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 = fftsink2.fft_sink_f(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.u.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: - pass - #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 = self.u.set_center_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.u.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 = stdgui2.stdapp (wfm_rx_block, "USRP2 WFM RX") - app.MainLoop () diff --git a/gr-audio/lib/alsa/audio_alsa_sink.cc b/gr-audio/lib/alsa/audio_alsa_sink.cc index 5fd197ec7..0bda42470 100644 --- a/gr-audio/lib/alsa/audio_alsa_sink.cc +++ b/gr-audio/lib/alsa/audio_alsa_sink.cc @@ -326,7 +326,7 @@ audio_alsa_sink::work_s16 (int noutput_items, gr_vector_void_star &output_items) { typedef gr_int16 sample_t; // the type of samples we're creating - static const int NBITS = 16; // # of bits in a sample + static const float scale_factor = std::pow(2.0f, 16-1) - 1; unsigned int nchan = input_items.size (); const float **in = (const float **) &input_items[0]; @@ -343,7 +343,7 @@ audio_alsa_sink::work_s16 (int noutput_items, bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ for (unsigned int chan = 0; chan < nchan; chan++){ - buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1)); + buf[bi++] = (sample_t) (in[chan][i] * scale_factor); } } @@ -368,7 +368,7 @@ audio_alsa_sink::work_s32 (int noutput_items, gr_vector_void_star &output_items) { typedef gr_int32 sample_t; // the type of samples we're creating - static const int NBITS = 32; // # of bits in a sample + static const float scale_factor = std::pow(2.0f, 32-1) - 1; unsigned int nchan = input_items.size (); const float **in = (const float **) &input_items[0]; @@ -385,7 +385,7 @@ audio_alsa_sink::work_s32 (int noutput_items, bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ for (unsigned int chan = 0; chan < nchan; chan++){ - buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1)); + buf[bi++] = (sample_t) (in[chan][i] * scale_factor); } } @@ -410,7 +410,7 @@ audio_alsa_sink::work_s16_1x2 (int noutput_items, gr_vector_void_star &output_items) { typedef gr_int16 sample_t; // the type of samples we're creating - static const int NBITS = 16; // # of bits in a sample + static const float scale_factor = std::pow(2.0f, 16-1) - 1; assert (input_items.size () == 1); static const unsigned int nchan = 2; @@ -427,7 +427,7 @@ audio_alsa_sink::work_s16_1x2 (int noutput_items, // process one period of data bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ - sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1)); + sample_t t = (sample_t) (in[0][i] * scale_factor); buf[bi++] = t; buf[bi++] = t; } @@ -452,7 +452,7 @@ audio_alsa_sink::work_s32_1x2 (int noutput_items, gr_vector_void_star &output_items) { typedef gr_int32 sample_t; // the type of samples we're creating - static const int NBITS = 32; // # of bits in a sample + static const float scale_factor = std::pow(2.0f, 32-1) - 1; assert (input_items.size () == 1); static unsigned int nchan = 2; @@ -469,7 +469,7 @@ audio_alsa_sink::work_s32_1x2 (int noutput_items, // process one period of data bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ - sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1)); + sample_t t = (sample_t) (in[0][i] * scale_factor); buf[bi++] = t; buf[bi++] = t; } diff --git a/gr-audio/swig/audio_swig.i b/gr-audio/swig/audio_swig.i index 612e96d23..1e3cca299 100644 --- a/gr-audio/swig/audio_swig.i +++ b/gr-audio/swig/audio_swig.i @@ -23,24 +23,6 @@ #define GR_AUDIO_API //////////////////////////////////////////////////////////////////////// -// Language independent exception handler -//////////////////////////////////////////////////////////////////////// -%include exception.i - -%exception { - try { - $action - } - catch(std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } - catch(...) { - SWIG_exception(SWIG_RuntimeError, "Unknown exception"); - } - -} - -//////////////////////////////////////////////////////////////////////// // standard includes //////////////////////////////////////////////////////////////////////// %include "gnuradio.i" diff --git a/gr-shd/.gitignore b/gr-shd/.gitignore new file mode 100644 index 000000000..a37fc0c1a --- /dev/null +++ b/gr-shd/.gitignore @@ -0,0 +1,3 @@ +/Makefile +/Makefile.in +/*.pc diff --git a/gnuradio-examples/python/apps/README b/gr-shd/Makefile.am index b64b9d066..2331831e0 100644 --- a/gnuradio-examples/python/apps/README +++ b/gr-shd/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2005 Free Software Foundation, Inc. +# Copyright 2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -17,10 +17,15 @@ # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -# +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = include lib apps + +if PYTHON +SUBDIRS += swig grc +endif -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. +pkgconfigdir = $(libdir)/pkgconfig +dist_pkgconfig_DATA = gnuradio-shd.pc diff --git a/gr-shd/apps/.gitignore b/gr-shd/apps/.gitignore new file mode 100644 index 000000000..22a4e7292 --- /dev/null +++ b/gr-shd/apps/.gitignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in + diff --git a/gnuradio-examples/python/usrp2/Makefile.am b/gr-shd/apps/Makefile.am index cca813349..16837f575 100644 --- a/gnuradio-examples/python/usrp2/Makefile.am +++ b/gr-shd/apps/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004,2005,2009 Free Software Foundation, Inc. +# Copyright 2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,12 +21,12 @@ include $(top_srcdir)/Makefile.common -ourdatadir = $(exampledir)/usrp2 -dist_ourdata_DATA = \ - qt_wfm_interface.ui \ - qt_wfm_interface.py +EXTRA_DIST += \ + $(bin_SCRIPTS) +ourpythondir = $(grpythondir) + +bin_SCRIPTS = \ + shd_fft.py \ + shd_rx_cfile.py -dist_ourdata_SCRIPTS = \ - usrp2_wfm_qt.py \ - usrp2_wfm_rcv.py diff --git a/gr-shd/apps/shd_fft.py b/gr-shd/apps/shd_fft.py new file mode 100755 index 000000000..81e84d383 --- /dev/null +++ b/gr-shd/apps/shd_fft.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gru +from gnuradio import shd +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2 +from gnuradio.wxgui import scopesink2, form, slider +from optparse import OptionParser +import wx +import sys +import numpy + +class app_top_block(stdgui2.std_top_block): + def __init__(self, frame, panel, vbox, argv): + stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="type=xmini", + help="Address of SHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-W", "--waterfall", action="store_true", default=False, + help="Enable waterfall display") + parser.add_option("-S", "--oscilloscope", action="store_true", default=False, + help="Enable oscilloscope display") + parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1, + help="Set fftsink averaging factor, default=[%default]") + parser.add_option("", "--ref-scale", type="eng_float", default=1.0, + help="Set dBFS=0dB input value, default=[%default]") + parser.add_option("--fft-size", type="int", default=1024, + help="Set number of FFT bins [default=%default]") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + self.options = options + self.show_debug_info = True + + self.src = shd.smini_source(device_addr=options.address, + io_type=shd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.src.set_samp_rate(options.samp_rate) + input_rate = self.src.get_samp_rate() + + if options.waterfall: + self.scope = \ + waterfallsink2.waterfall_sink_c (panel, fft_size=1024, + sample_rate=input_rate) + self.frame.SetMinSize((800, 420)) + elif options.oscilloscope: + self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate) + self.frame.SetMinSize((800, 600)) + else: + self.scope = fftsink2.fft_sink_c (panel, + fft_size=options.fft_size, + sample_rate=input_rate, + ref_scale=options.ref_scale, + ref_level=20.0, + y_divs = 12, + avg_alpha=options.avg_alpha) + self.frame.SetMinSize((800, 420)) + + self.connect(self.src, self.scope) + + self._build_gui(vbox) + self._setup_events() + + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.src.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.src.get_freq_range() + options.freq = float(r.start()+r.stop())/2 + + self.set_gain(options.gain) + + if(options.antenna): + self.src.set_antenna(options.antenna, 0) + + if self.show_debug_info: + self.myform['samprate'].set_value(self.src.get_samp_rate()) + self.myform['fs@gbe'].set_value(input_rate) + 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") + + print "Center Freq: ", self.src.get_center_freq() + print "Freq Range: ", self.src.get_freq_range() + print "Gain: ", self.src.get_gain() + print "Gain Names: ", self.src.get_gain_names() + print "Gain Range: ", self.src.get_gain_range() + + 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.src.get_gain_range() + + # some configurations don't have gain control + if g.stop() > g.start(): + myform['gain'] = form.slider_field(parent=self.panel, + sizer=hbox, label="Gain", + weight=3, + min=int(g.start()), + max=int(g.stop()), + 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_samp_rate(kv): + return self.set_samp_rate(kv['samprate']) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + hbox = wx.BoxSizer(wx.HORIZONTAL) + + hbox.Add((5,0), 0) + myform['samprate'] = form.float_field( + parent=panel, sizer=hbox, label="Sample Rate", + callback=myform.check_input_and_call(_form_set_samp_rate, + self._set_status_msg)) + + hbox.Add((5,0), 1) + myform['fs@gbe'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@GbE") + + hbox.Add((5,0), 1) + myform['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.src.set_center_freq(target_freq, 0) + + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.actual_rf_freq) + self.myform['ddc'].set_value(r.actual_dsp_freq) + if not self.options.oscilloscope: + self.scope.set_baseband_freq(target_freq) + return True + + return False + + def set_gain(self, gain): + if self.myform.has_key('gain'): + self.myform['gain'].set_value(gain) # update displayed value + self.src.set_gain(gain, 0) + + def set_samp_rate(self, samp_rate): + ok = self.src.set_samp_rate(samp_rate) + input_rate = self.src.get_samp_rate() + self.scope.set_sample_rate(input_rate) + if self.show_debug_info: # update displayed values + self.myform['samprate'].set_value(self.src.get_samp_rate()) + self.myform['fs@gbe'].set_value(input_rate) + + # shd set_samp_rate never fails; always falls back to closest requested. + return True + + def _setup_events(self): + if not self.options.waterfall and not self.options.oscilloscope: + self.scope.win.Bind(wx.EVT_LEFT_DCLICK, self.evt_left_dclick) + + def evt_left_dclick(self, event): + (ux, uy) = self.scope.win.GetXY(event) + if event.CmdDown(): + # Re-center on maximum power + points = self.scope.win._points + if self.scope.win.peak_hold: + if self.scope.win.peak_vals is not None: + ind = numpy.argmax(self.scope.win.peak_vals) + else: + ind = int(points.shape()[0]/2) + else: + ind = numpy.argmax(points[:,1]) + (freq, pwr) = points[ind] + target_freq = freq/self.scope.win._scale_factor + print ind, freq, pwr + self.set_freq(target_freq) + else: + # Re-center on clicked frequency + target_freq = ux/self.scope.win._scale_factor + self.set_freq(target_freq) + + +def main (): + app = stdgui2.stdapp(app_top_block, "SHD FFT", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gr-shd/apps/shd_rx_cfile.py b/gr-shd/apps/shd_rx_cfile.py new file mode 100755 index 000000000..007bc809f --- /dev/null +++ b/gr-shd/apps/shd_rx_cfile.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +""" +Read samples from a SHD device 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 shd +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +n2s = eng_notation.num_to_str + +class rx_cfile_block(gr.top_block): + + def __init__(self, options, filename): + gr.top_block.__init__(self) + + # Create a SHD device source + if options.output_shorts: + self._src = shd.smini_source(device_addr=options.address, + io_type=shd.io_type.COMPLEX_INT16, + num_channels=1) + self._sink = gr.file_sink(gr.sizeof_short*2, filename) + else: + self._src = shd.smini_source(device_addr=options.address, + io_type=shd.io_type.COMPLEX_FLOAT32, + num_channels=1) + self._sink = gr.file_sink(gr.sizeof_gr_complex, filename) + + # Set receiver sample rate + self._src.set_samp_rate(options.samp_rate) + + # Set receive daughterboard gain + if options.gain is None: + g = self._src.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + print "Using mid-point gain of", \ + options.gain, "(", g.start(), "-", g.stop(), ")" + self._src.set_gain(options.gain) + + # Set the antenna + if(options.antenna): + self._src.set_antenna(options.antenna, 0) + + # Set frequency (tune request takes lo_offset) + if(options.lo_offset is not None): + treq = shd.tune_request(options.freq, options.lo_offset) + else: + treq = shd.tune_request(options.freq) + tr = self._src.set_center_freq(treq) + if tr == None: + sys.stderr.write('Failed to set center frequency\n') + raise SystemExit, 1 + + # Create head block if needed and wire it up + if options.nsamples is None: + self.connect(self._src, self._sink) + else: + if options.output_shorts: + self._head = gr.head(gr.sizeof_short*2, + int(options.nsamples)) + else: + self._head = gr.head(gr.sizeof_gr_complex, + int(options.nsamples)) + + self.connect(self._src, self._head, self._sink) + + input_rate = self._src.get_samp_rate() + + if options.verbose: + print "Address:", options.address + print "Rx gain:", options.gain + print "Rx baseband frequency:", n2s(tr.actual_rf_freq) + print "Rx DDC frequency:", n2s(tr.actual_dsp_freq) + print "Rx Sample Rate:", n2s(input_rate) + if options.nsamples is None: + print "Receiving samples until Ctrl-C" + else: + print "Receving", n2s(options.nsamples), "samples" + if options.output_shorts: + print "Writing 16-bit complex shorts" + else: + print "Writing 32-bit complex floats" + print "Output filename:", filename + +def get_options(): + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", default="type=xmini", + help="Address of SHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [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( "-s","--output-shorts", action="store_true", default=False, + help="output interleaved shorts instead of complex floats") + parser.add_option("-N", "--nsamples", type="eng_float", default=None, + help="number of samples to collect [default=+inf]") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="verbose output") + parser.add_option("", "--lo-offset", type="eng_float", default=None, + help="set daughterboard LO offset to OFFSET [default=hw default]") + + (options, args) = parser.parse_args () + if len(args) != 1: + 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 + + return (options, args[0]) + + +if __name__ == '__main__': + (options, filename) = get_options() + tb = rx_cfile_block(options, filename) + + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gr-shd/apps/shd_siggen.py b/gr-shd/apps/shd_siggen.py new file mode 100755 index 000000000..112eeea15 --- /dev/null +++ b/gr-shd/apps/shd_siggen.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +""" +Read samples from a SHD device 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 shd +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +n2s = eng_notation.num_to_str + +class shd_siggen(gr.top_block): + + def __init__(self, options): + gr.top_block.__init__(self) + + self._src = gr.sig_source_c(options.samp_rate, gr.GR_SIN_WAVE, + 200, 1) + + self._snk = shd.smini_sink(device_addr=options.address, + io_type=shd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + # Set receiver sample rate + self._snk.set_samp_rate(options.samp_rate) + + # Set receive daughterboard gain + if options.gain is None: + g = self._snk.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + print "Using mid-point gain of", \ + options.gain, "(", g.start(), "-", g.stop(), ")" + self._snk.set_gain(options.gain) + + # Set the antenna + if(options.antenna): + self._snk.set_antenna(options.antenna, 0) + + # Set frequency (tune request takes lo_offset) + if(options.lo_offset is not None): + treq = shd.tune_request(options.freq, options.lo_offset) + else: + treq = shd.tune_request(options.freq) + tr = self._snk.set_center_freq(treq) + if tr == None: + sys.stderr.write('Failed to set center frequency\n') + raise SystemExit, 1 + + # Create head block if needed and wire it up + self.connect(self._src, self._snk) + input_rate = self._snk.get_samp_rate() + + if options.verbose: + print "Address:", options.address + print "Rx gain:", options.gain + print "Rx baseband frequency:", n2s(tr.actual_rf_freq) + print "Rx DDC frequency:", n2s(tr.actual_dsp_freq) + print "Rx Sample Rate:", n2s(input_rate) + +def get_options(): + usage="%prog: [options]" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", default="type=xmini", + help="Address of SHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [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("-v", "--verbose", action="store_true", default=False, + help="verbose output") + parser.add_option("", "--lo-offset", type="eng_float", default=None, + help="set daughterboard LO offset to OFFSET [default=hw default]") + + (options, args) = parser.parse_args () + + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + + return (options) + + +if __name__ == '__main__': + options = get_options() + tb = shd_siggen(options) + + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gr-shd/gnuradio-shd.pc.in b/gr-shd/gnuradio-shd.pc.in new file mode 100644 index 000000000..cff0dcf00 --- /dev/null +++ b/gr-shd/gnuradio-shd.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnuradio-shd +Description: GNU Radio blocks for the Symplex Hardware Driver (SHD) +Requires: gnuradio-core +Version: @LIBVER@ +Libs: -L${libdir} -lgnuradio-shd +Cflags: -I${includedir} diff --git a/gr-shd/grc/.gitignore b/gr-shd/grc/.gitignore new file mode 100644 index 000000000..2c261c55b --- /dev/null +++ b/gr-shd/grc/.gitignore @@ -0,0 +1,3 @@ +/shd_smini*.xml +/Makefile +/Makefile.in diff --git a/gr-shd/grc/Makefile.am b/gr-shd/grc/Makefile.am new file mode 100644 index 000000000..c44ad1b4e --- /dev/null +++ b/gr-shd/grc/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +grcblocksdir = $(grc_blocksdir) + +generated_shd_smini_blocks = \ + shd_smini_source.xml \ + shd_smini_sink.xml + +BUILT_SOURCES += $(generated_shd_smini_blocks) + +dist_grcblocks_DATA = \ + shd_block_tree.xml \ + $(BUILT_SOURCES) + +######################################################################## +# Rules for generating the source and sink xml wrappers +######################################################################## +EXTRA_DIST += $(srcdir)/gen_shd_smini_blocks.py + +$(generated_shd_smini_blocks): $(srcdir)/gen_shd_smini_blocks.py + @echo "generating $@..." + $(PYTHON) $< $@ diff --git a/gr-shd/grc/gen_shd_smini_blocks.py b/gr-shd/grc/gen_shd_smini_blocks.py new file mode 100644 index 000000000..652b6cf51 --- /dev/null +++ b/gr-shd/grc/gen_shd_smini_blocks.py @@ -0,0 +1,297 @@ +""" +Copyright 2011 Free Software Foundation, Inc. + +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +MAIN_TMPL = """\ +<?xml version="1.0"?> +<block> + <name>SHD: SMINI $sourk.title()</name> + <key>shd_smini_$(sourk)</key> + <import>from gnuradio import shd</import> + <make>shd.smini_$(sourk)( + device_addr=\$dev_addr, + io_type=shd.io_type.\$type.type, + num_channels=\$nchan, +) +\#if \$clock_rate() +self.\$(id).set_clock_rate(\$clock_rate, shd.ALL_MBOARDS) +\#end if +#for $m in range($max_mboards) +######################################################################## +\#if \$num_mboards() > $m and \$ref_source$(m)() == 'external' +self.\$(id).set_clock_config(shd.clock_config.external(), $m) +\#end if +######################################################################## +\#if \$num_mboards() > $m and \$ref_source$(m)() == 'internal' +self.\$(id).set_clock_config(shd.clock_config.internal(), $m) +\#end if +######################################################################## +\#if \$num_mboards() > $m and \$ref_source$(m)() == 'mimo' +_config = shd.clock_config() +_config.ref_source = shd.clock_config.REF_MIMO +_config.pps_source = shd.clock_config.PPS_MIMO +self.\$(id).set_clock_config(_config, $m) +\#end if +######################################################################## +\#if \$num_mboards() > $m and \$sd_spec$(m)() +self.\$(id).set_subdev_spec(\$sd_spec$(m), $m) +\#end if +######################################################################## +#end for +\#if \$sync() +self.\$(id).set_time_unknown_pps(shd.time_spec()) +\#end if +self.\$(id).set_samp_rate(\$samp_rate) +#for $n in range($max_nchan) +\#if \$nchan() > $n +self.\$(id).set_center_freq(\$center_freq$(n), $n) +self.\$(id).set_gain(\$gain$(n), $n) +\#end if +#end for +</make> + <callback>set_samp_rate(\$samp_rate)</callback> + #for $n in range($max_nchan) + <callback>set_center_freq(\$center_freq$(n), $n)</callback> + <callback>set_gain(\$gain$(n), $n)</callback> + #end for + <param> + <name>$(direction.title())put Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>type:COMPLEX_FLOAT32</opt> + <opt>vlen:1</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>type:COMPLEX_INT16</opt> + <opt>vlen:2</opt> + </option> + </param> + <param> + <name>Device Addr</name> + <key>dev_addr</key> + <value></value> + <type>string</type> + <hide> + \#if \$dev_addr() + none + \#else + part + \#end if + </hide> + </param> + <param> + <name>Sync</name> + <key>sync</key> + <value></value> + <type>enum</type> + <hide>\#if \$sync() then 'none' else 'part'#</hide> + <option> + <name>unknown PPS</name> + <key>sync</key> + </option> + <option> + <name>don't sync</name> + <key></key> + </option> + </param> + <param> + <name>Clock Rate (Hz)</name> + <key>clock_rate</key> + <value>0.0</value> + <type>real</type> + <hide>\#if \$clock_rate() then 'none' else 'part'#</hide> + <option> + <name>Default</name> + <key>0.0</key> + </option> + </param> + <param> + <name>Num Mboards</name> + <key>num_mboards</key> + <value>1</value> + <type>int</type> + <hide>part</hide> + #for $m in range(1, $max_mboards+1) + <option> + <name>$(m)</name> + <key>$m</key> + </option> + #end for + </param> + #for $m in range($max_mboards) + <param> + <name>Mb$(m): Ref Source</name> + <key>ref_source$(m)</key> + <value></value> + <type>enum</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$ref_source$(m)() + none + \#else + part + \#end if + </hide> + <option><name>Default</name><key></key></option> + <option><name>Internal</name><key>internal</key></option> + <option><name>External</name><key>external</key></option> + <option><name>MIMO Cable</name><key>mimo</key></option> + </param> + <param> + <name>Mb$(m): Subdev Spec</name> + <key>sd_spec$(m)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$sd_spec$(m)() + none + \#else + part + \#end if + </hide> + </param> + #end for + <param> + <name>Num Channels</name> + <key>nchan</key> + <value>1</value> + <type>int</type> + #for $n in range(1, $max_nchan+1) + <option> + <name>$(n)</name> + <key>$n</key> + </option> + #end for + </param> + <param> + <name>Samp Rate (Sps)</name> + <key>samp_rate</key> + <value>samp_rate</value> + <type>real</type> + </param> + $params + <check>$max_nchan >= \$nchan</check> + <check>\$nchan > 0</check> + <check>$max_mboards >= \$num_mboards</check> + <check>\$num_mboards > 0</check> + <check>\$nchan >= \$num_mboards</check> + <$sourk> + <name>$direction</name> + <type>\$type</type> + <vlen>\$type.vlen</vlen> + <nports>\$nchan</nports> + </$sourk> + <doc> +The SHD SMINI $sourk.title() Block: + +Device Address: +The device address is a delimited string used to locate SHD devices on your system. \\ +If left blank, the first SHD device found will be used. \\ +Use the device address to specify a specific device or list of devices. +SMINI1 Example: serial=12345678 +SMINI2 Example: type=xmini + +Num Motherboards: +Selects the number of SMINI motherboards in this device configuration. + +Reference Source: +Where the motherboard should sync its time and clock references. +If source and sink blocks reference the same device, +it is only necessary to set the reference source on one of the blocks. + +Subdevice specification: +Each motherboard should have its own subdevice specification \\ +and all subdevice specifications should be the same length. \\ +Select the subdevice or subdevices for each channel using a markup string. \\ +The markup string consists of a list of dboard_slot:subdev_name pairs (one pair per channel). \\ +If left blank, the SHD will try to select the first subdevice on your system. \\ +See the application notes for further details. +Single channel example: :AB +Dual channel example: :A :B + +Num Channels: +Selects the total number of channels in this multi-SMINI configuration. +Ex: 4 motherboards with 2 channels per board = 8 channels total + +Sample rate: +The sample rate is the number of samples per second input by this block. \\ +The SHD device driver will try its best to match the requested sample rate. \\ +If the requested rate is not possible, the SHD block will print an error at runtime. + +Center frequency: +The center frequency is the overall frequency of the RF chain. \\ +For greater control of how the SHD tunes elements in the RF chain, \\ +pass a tune_request object rather than a simple target frequency. +Tuning with an LO offset example: shd.tune_request(freq, lo_off) + + </doc> +</block> +""" + +PARAMS_TMPL = """ + <param> + <name>Ch$(n): Center Freq (Hz)</name> + <key>center_freq$(n)</key> + <value>0</value> + <type>real</type> + <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> + </param> + <param> + <name>Ch$(n): Gain (dB)</name> + <key>gain$(n)</key> + <value>0</value> + <type>real</type> + <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> + </param> +""" + +def parse_tmpl(_tmpl, **kwargs): + from Cheetah import Template + return str(Template.Template(_tmpl, kwargs)) + +max_num_mboards = 8 +max_num_channels = max_num_mboards*4 + +if __name__ == '__main__': + import sys + for file in sys.argv[1:]: + if 'source' in file: + sourk = 'source' + direction = 'out' + elif 'sink' in file: + sourk = 'sink' + direction = 'in' + else: raise Exception, 'is %s a source or sink?'%file + + params = ''.join([parse_tmpl(PARAMS_TMPL, n=n) for n in range(max_num_channels)]) + open(file, 'w').write(parse_tmpl(MAIN_TMPL, + max_nchan=max_num_channels, + max_mboards=max_num_mboards, + params=params, + sourk=sourk, + direction=direction, + )) diff --git a/gr-shd/grc/shd_block_tree.xml b/gr-shd/grc/shd_block_tree.xml new file mode 100644 index 000000000..5d9786f67 --- /dev/null +++ b/gr-shd/grc/shd_block_tree.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Block Tree for shd blocks. +################################################### + --> +<cat> + <name></name> <!-- Blank for Root Name --> + <cat> + <name>SHD</name> + <block>shd_smini_source</block> + <block>shd_smini_sink</block> + </cat> +</cat> diff --git a/gnuradio-examples/python/apps/.gitignore b/gr-shd/include/.gitignore index b336cc7ce..b336cc7ce 100644 --- a/gnuradio-examples/python/apps/.gitignore +++ b/gr-shd/include/.gitignore diff --git a/gnuradio-examples/python/apps/Makefile.am b/gr-shd/include/Makefile.am index 50fe75151..2cb1597df 100644 --- a/gnuradio-examples/python/apps/Makefile.am +++ b/gr-shd/include/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2006 Free Software Foundation, Inc. +# Copyright 2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -17,10 +17,11 @@ # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -# +# include $(top_srcdir)/Makefile.common -SUBDIRS = hf_explorer hf_radio -EXTRA_DIST += README - +grinclude_HEADERS = \ + gr_shd_api.h \ + gr_shd_smini_source.h \ + gr_shd_smini_sink.h
\ No newline at end of file diff --git a/gr-shd/include/gr_shd_api.h b/gr-shd/include/gr_shd_api.h new file mode 100644 index 000000000..e6773c3f3 --- /dev/null +++ b/gr-shd/include/gr_shd_api.h @@ -0,0 +1,33 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SHD_API_H +#define INCLUDED_GR_SHD_API_H + +#include <shd/config.hpp> + +#ifdef gnuradio_shd_EXPORTS +# define GR_SHD_API SHD_EXPORT +#else +# define GR_SHD_API SHD_IMPORT +#endif + +#endif /* INCLUDED_GR_SHD_API_H */ diff --git a/gr-shd/include/gr_shd_smini_sink.h b/gr-shd/include/gr_shd_smini_sink.h new file mode 100644 index 000000000..938958687 --- /dev/null +++ b/gr-shd/include/gr_shd_smini_sink.h @@ -0,0 +1,282 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SHD_SMINI_SINK_H +#define INCLUDED_GR_SHD_SMINI_SINK_H + +#include <gr_shd_api.h> +#include <gr_sync_block.h> +#include <shd/xmini/multi_xmini.hpp> + +class shd_smini_sink; + +GR_SHD_API boost::shared_ptr<shd_smini_sink> shd_make_smini_sink( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels +); + +class GR_SHD_API shd_smini_sink : virtual public gr_sync_block +{ + public: + + /*! + * Set the subdevice specification. + * \param spec the subdev spec markup string + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0; + + /*! + * Set the sample rate for the smini device. + * \param rate a new rate in Sps + */ + virtual void set_samp_rate(double rate) = 0; + + /*! + * Get the sample rate for the smini device. + * This is the actual sample rate and may differ from the rate set. + * \return the actual rate in Sps + */ + virtual double get_samp_rate(void) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * \param tune_request the tune request instructions + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + virtual shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, size_t chan = 0 + ) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * This is a wrapper around set center freq so that in this case, + * the user can pass a single frequency in the call through swig. + * \param freq the desired frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + shd::tune_result_t set_center_freq(double freq, size_t chan = 0){ + return set_center_freq(shd::tune_request_t(freq), chan); + } + + /*! + * Get the center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ + virtual double get_center_freq(size_t chan = 0) = 0; + + /*! + * Get the tunable frequency range. + * \param chan the channel index 0 to N-1 + * \return the frequency range in Hz + */ + virtual shd::freq_range_t get_freq_range(size_t chan = 0) = 0; + + /*! + * Set the gain for the dboard. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, size_t chan = 0) = 0; + + /*! + * Set the named gain on the dboard. + * \param gain the gain in dB + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Set the antenna to use. + * \param ant the antenna string + * \param chan the channel index 0 to N-1 + */ + virtual void set_antenna(const std::string &ant, + size_t chan = 0) = 0; + + /*! + * Get the antenna in use. + * \param chan the channel index 0 to N-1 + * \return the antenna string + */ + virtual std::string get_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible antennas. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna strings + */ + virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0; + + /*! + * Set the subdevice bandpass filter. + * \param chan the channel index 0 to N-1 + * \param bandwidth the filter bandwidth in Hz + */ + virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get a daughterboard sensor value. + * \param name the name of the sensor + * \param chan the channel index 0 to N-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get a list of possible daughterboard sensor names. + * \param chan the channel index 0 to N-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_dboard_sensor_names(size_t chan = 0) = 0; + + /*! + * Get a motherboard sensor value. + * \param name the name of the sensor + * \param mboard the motherboard index 0 to M-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard = 0) = 0; + + /*! + * Get a list of possible motherboard sensor names. + * \param mboard the motherboard index 0 to M-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; + + /*! + * Set the clock configuration. + * \param clock_config the new configuration + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard = 0) = 0; + + /*! + * Get the master clock rate. + * \param mboard the motherboard index 0 to M-1 + * \return the clock rate in Hz + */ + virtual double get_clock_rate(size_t mboard = 0) = 0; + + /*! + * Set the master clock rate. + * \param rate the new rate in Hz + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_rate(double rate, size_t mboard = 0) = 0; + + /*! + * Get the current time registers. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_now(size_t mboard = 0) = 0; + + /*! + * Get the time when the last pps pulse occured. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0; + + /*! + * Sets the time registers immediately. + * \param time_spec the new time + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard = 0) = 0; + + /*! + * Set the time registers at the next pps. + * \param time_spec the new time + */ + virtual void set_time_next_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Sync the time registers with an unknown pps edge. + * \param time_spec the new time + */ + virtual void set_time_unknown_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Get access to the underlying shd dboard iface object. + * \return the dboard_iface object + */ + virtual shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0; + + /*! + * Get access to the underlying shd device object. + * \return the multi smini device object + */ + virtual shd::xmini::multi_xmini::sptr get_device(void) = 0; +}; + +#endif /* INCLUDED_GR_SHD_SMINI_SINK_H */ diff --git a/gr-shd/include/gr_shd_smini_source.h b/gr-shd/include/gr_shd_smini_source.h new file mode 100644 index 000000000..3e3dbf427 --- /dev/null +++ b/gr-shd/include/gr_shd_smini_source.h @@ -0,0 +1,286 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SHD_SMINI_SOURCE_H +#define INCLUDED_GR_SHD_SMINI_SOURCE_H + +#include <gr_shd_api.h> +#include <gr_sync_block.h> +#include <shd/xmini/multi_xmini.hpp> + +class shd_smini_source; + +GR_SHD_API boost::shared_ptr<shd_smini_source> shd_make_smini_source( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels +); + +class GR_SHD_API shd_smini_source : virtual public gr_sync_block +{ + public: + + /*! + * Set the subdevice specification. + * \param spec the subdev spec markup string + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_subdev_spec(const std::string &spec, + size_t mboard = 0) = 0; + + /*! + * Set the sample rate for the smini device. + * \param rate a new rate in Sps + */ + virtual void set_samp_rate(double rate) = 0; + + /*! + * Get the sample rate for the smini device. + * This is the actual sample rate and may differ from the rate set. + * \return the actual rate in Sps + */ + virtual double get_samp_rate(void) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * \param tune_request the tune request instructions + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + virtual shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, + size_t chan = 0 + ) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * This is a wrapper around set center freq so that in this case, + * the user can pass a single frequency in the call through swig. + * \param freq the desired frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + shd::tune_result_t set_center_freq(double freq, size_t chan = 0){ + return set_center_freq(shd::tune_request_t(freq), chan); + } + + /*! + * Get the center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ + virtual double get_center_freq(size_t chan = 0) = 0; + + /*! + * Get the tunable frequency range. + * \param chan the channel index 0 to N-1 + * \return the frequency range in Hz + */ + virtual shd::freq_range_t get_freq_range(size_t chan = 0) = 0; + + /*! + * Set the gain for the dboard. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, size_t chan = 0) = 0; + + /*! + * Set the named gain on the dboard. + * \param gain the gain in dB + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Set the antenna to use. + * \param ant the antenna string + * \param chan the channel index 0 to N-1 + */ + virtual void set_antenna(const std::string &ant, + size_t chan = 0) = 0; + + /*! + * Get the antenna in use. + * \param chan the channel index 0 to N-1 + * \return the antenna string + */ + virtual std::string get_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible antennas. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna strings + */ + virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0; + + /*! + * Set the subdevice bandpass filter. + * \param bandwidth the filter bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ + virtual void set_bandwidth(double bandwidth, + size_t chan = 0) = 0; + + /*! + * Get a daughterboard sensor value. + * \param name the name of the sensor + * \param chan the channel index 0 to N-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get a list of possible daughterboard sensor names. + * \param chan the channel index 0 to N-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_dboard_sensor_names(size_t chan = 0) = 0; + + /*! + * Get a motherboard sensor value. + * \param name the name of the sensor + * \param mboard the motherboard index 0 to M-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard = 0) = 0; + + /*! + * Get a list of possible motherboard sensor names. + * \param mboard the motherboard index 0 to M-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; + + /*! + * Set the clock configuration. + * \param clock_config the new configuration + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard = 0) = 0; + + /*! + * Get the master clock rate. + * \param mboard the motherboard index 0 to M-1 + * \return the clock rate in Hz + */ + virtual double get_clock_rate(size_t mboard = 0) = 0; + + /*! + * Set the master clock rate. + * \param rate the new rate in Hz + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_rate(double rate, + size_t mboard = 0) = 0; + + /*! + * Get the current time registers. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_now(size_t mboard = 0) = 0; + + /*! + * Get the time when the last pps pulse occured. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0; + + /*! + * Sets the time registers immediately. + * \param time_spec the new time + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard = 0) = 0; + + /*! + * Set the time registers at the next pps. + * \param time_spec the new time + */ + virtual void set_time_next_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Sync the time registers with an unknown pps edge. + * \param time_spec the new time + */ + virtual void set_time_unknown_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Get access to the underlying shd dboard iface object. + * \return the dboard_iface object + */ + virtual shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0; + + /*! + * Get access to the underlying shd device object. + * \return the multi smini device object + */ + virtual shd::xmini::multi_xmini::sptr get_device(void) = 0; +}; + +#endif /* INCLUDED_GR_SHD_SMINI_SOURCE_H */ diff --git a/gnuradio-examples/python/usrp2/.gitignore b/gr-shd/lib/.gitignore index b336cc7ce..b336cc7ce 100644 --- a/gnuradio-examples/python/usrp2/.gitignore +++ b/gr-shd/lib/.gitignore diff --git a/gr-shd/lib/Makefile.am b/gr-shd/lib/Makefile.am new file mode 100644 index 000000000..7a887aebf --- /dev/null +++ b/gr-shd/lib/Makefile.am @@ -0,0 +1,42 @@ +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +AM_CPPFLAGS = \ + $(STD_DEFINES_AND_INCLUDES) \ + $(WITH_INCLUDES) \ + $(SHD_CPPFLAGS) \ + -Dgnuradio_shd_EXPORTS + +lib_LTLIBRARIES = libgnuradio-shd.la + +libgnuradio_shd_la_SOURCES = \ + gr_shd_smini_source.cc \ + gr_shd_smini_sink.cc + +libgnuradio_shd_la_LIBADD = \ + $(GNURADIO_CORE_LA) \ + $(SHD_LIBS) + +libgnuradio_shd_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS) + +noinst_HEADERS = diff --git a/gr-shd/lib/gr_shd_smini_sink.cc b/gr-shd/lib/gr_shd_smini_sink.cc new file mode 100644 index 000000000..c9fb222d0 --- /dev/null +++ b/gr-shd/lib/gr_shd_smini_sink.cc @@ -0,0 +1,276 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gr_shd_smini_sink.h> +#include <gr_io_signature.h> +#include <stdexcept> + +/********************************************************************* + * SHD Multi SMINI Sink Impl + ********************************************************************/ +class shd_smini_sink_impl : public shd_smini_sink +{ +public: + shd_smini_sink_impl(const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels): + gr_sync_block("gr shd smini sink", + gr_make_io_signature(num_channels, num_channels, io_type.size), + gr_make_io_signature(0, 0, 0)), + _type(io_type), + _nchan(num_channels), + _has_time_spec(_nchan > 1) + { + _dev = shd::xmini::multi_xmini::make(device_addr); + } + + void set_subdev_spec(const std::string &spec, + size_t mboard) + { + return _dev->set_tx_subdev_spec(spec, mboard); + } + + void set_samp_rate(double rate){ + _dev->set_tx_rate(rate); + _sample_rate = this->get_samp_rate(); + } + + double get_samp_rate(void){ + return _dev->get_tx_rate(); + } + + shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, size_t chan) + { + return _dev->set_tx_freq(tune_request, chan); + } + + double get_center_freq(size_t chan) + { + return _dev->get_tx_freq(chan); + } + + shd::freq_range_t get_freq_range(size_t chan) + { + return _dev->get_tx_freq_range(chan); + } + + void set_gain(double gain, size_t chan) + { + return _dev->set_tx_gain(gain, chan); + } + + void set_gain(double gain, const std::string &name, + size_t chan) + { + return _dev->set_tx_gain(gain, name, chan); + } + + double get_gain(size_t chan){ + return _dev->get_tx_gain(chan); + } + + double get_gain(const std::string &name, size_t chan) + { + return _dev->get_tx_gain(name, chan); + } + + std::vector<std::string> get_gain_names(size_t chan) + { + return _dev->get_tx_gain_names(chan); + } + + shd::gain_range_t get_gain_range(size_t chan) + { + return _dev->get_tx_gain_range(chan); + } + + shd::gain_range_t get_gain_range(const std::string &name, + size_t chan) + { + return _dev->get_tx_gain_range(name, chan); + } + + void set_antenna(const std::string &ant, size_t chan) + { + return _dev->set_tx_antenna(ant, chan); + } + + std::string get_antenna(size_t chan) + { + return _dev->get_tx_antenna(chan); + } + + std::vector<std::string> get_antennas(size_t chan) + { + return _dev->get_tx_antennas(chan); + } + + void set_bandwidth(double bandwidth, size_t chan) + { + return _dev->set_tx_bandwidth(bandwidth, chan); + } + + shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan) + { + return _dev->get_tx_sensor(name, chan); + } + + std::vector<std::string> get_dboard_sensor_names(size_t chan) + { + return _dev->get_tx_sensor_names(chan); + } + + shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard) + { + return _dev->get_mboard_sensor(name, mboard); + } + + std::vector<std::string> get_mboard_sensor_names(size_t mboard) + { + return _dev->get_mboard_sensor_names(mboard); + } + + void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard) + { + return _dev->set_clock_config(clock_config, mboard); + } + + double get_clock_rate(size_t mboard) + { + return _dev->get_master_clock_rate(mboard); + } + + void set_clock_rate(double rate, size_t mboard) + { + return _dev->set_master_clock_rate(rate, mboard); + } + + shd::time_spec_t get_time_now(size_t mboard = 0) + { + return _dev->get_time_now(mboard); + } + + shd::time_spec_t get_time_last_pps(size_t mboard) + { + return _dev->get_time_last_pps(mboard); + } + + void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard) + { + return _dev->set_time_now(time_spec, mboard); + } + + void set_time_next_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_next_pps(time_spec); + } + + void set_time_unknown_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_unknown_pps(time_spec); + } + + shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan) + { + return _dev->get_tx_dboard_iface(chan); + } + + shd::xmini::multi_xmini::sptr get_device(void) + { + return _dev; + } + + /******************************************************************* + * Work + ******************************************************************/ + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //send a mid-burst packet with time spec + _metadata.start_of_burst = false; + _metadata.end_of_burst = false; + _metadata.has_time_spec = _has_time_spec; + + size_t num_sent = _dev->get_device()->send( + input_items, noutput_items, _metadata, + _type, shd::device::SEND_MODE_FULL_BUFF, 1.0); + + //increment the timespec by the number of samples sent + _metadata.time_spec += shd::time_spec_t(0, num_sent, _sample_rate); + return num_sent; + } + + //Send an empty start-of-burst packet to begin streaming. + //Set at a time in the near future to avoid late packets. + bool start(void) + { + _metadata.start_of_burst = true; + _metadata.end_of_burst = false; + _metadata.has_time_spec = _has_time_spec; + _metadata.time_spec = get_time_now() + shd::time_spec_t(0.01); + + _dev->get_device()->send( + gr_vector_const_void_star(_nchan), 0, _metadata, + _type, shd::device::SEND_MODE_ONE_PACKET, 1.0); + return true; + } + + //Send an empty end-of-burst packet to end streaming. + //Ending the burst avoids an underflow error on stop. + bool stop(void) + { + _metadata.start_of_burst = false; + _metadata.end_of_burst = true; + _metadata.has_time_spec = false; + + _dev->get_device()->send( + gr_vector_const_void_star(_nchan), 0, _metadata, + _type, shd::device::SEND_MODE_ONE_PACKET, 1.0); + return true; + } + +protected: + shd::xmini::multi_xmini::sptr _dev; + const shd::io_type_t _type; + size_t _nchan; + bool _has_time_spec; + shd::tx_metadata_t _metadata; + double _sample_rate; +}; + +/********************************************************************* + * Make SHD Multi SMINI Sink + ********************************************************************/ + +boost::shared_ptr<shd_smini_sink> shd_make_smini_sink( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels) +{ + return boost::shared_ptr<shd_smini_sink>( + new shd_smini_sink_impl(device_addr, io_type, num_channels)); +} diff --git a/gr-shd/lib/gr_shd_smini_source.cc b/gr-shd/lib/gr_shd_smini_source.cc new file mode 100644 index 000000000..caf98f311 --- /dev/null +++ b/gr-shd/lib/gr_shd_smini_source.cc @@ -0,0 +1,299 @@ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gr_shd_smini_source.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> +#include <boost/format.hpp> + +/********************************************************************* + * SHD Multi S-MINI Source Impl + ********************************************************************/ +class shd_smini_source_impl : public shd_smini_source +{ +public: + shd_smini_source_impl( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels + ): + gr_sync_block( + "gr shd smini source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(num_channels, num_channels, io_type.size) + ), + _type(io_type), + _nchan(num_channels), + _stream_now(_nchan == 1), + _tmp_buffs(_nchan) + { + _dev = shd::xmini::multi_xmini::make(device_addr); + } + + void set_subdev_spec(const std::string &spec, size_t mboard) + { + return _dev->set_rx_subdev_spec(spec, mboard); + } + + void set_samp_rate(double rate) + { + _dev->set_rx_rate(rate); + } + + double get_samp_rate(void) + { + return _dev->get_rx_rate(); + } + + shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, size_t chan) + { + return _dev->set_rx_freq(tune_request, chan); + } + + double get_center_freq(size_t chan) + { + return _dev->get_rx_freq(chan); + } + + shd::freq_range_t get_freq_range(size_t chan) + { + return _dev->get_rx_freq_range(chan); + } + + void set_gain(double gain, size_t chan) + { + return _dev->set_rx_gain(gain, chan); + } + + void set_gain(double gain, const std::string &name, + size_t chan) + { + return _dev->set_rx_gain(gain, name, chan); + } + + double get_gain(size_t chan) + { + return _dev->get_rx_gain(chan); + } + + double get_gain(const std::string &name, size_t chan) + { + return _dev->get_rx_gain(name, chan); + } + + std::vector<std::string> get_gain_names(size_t chan) + { + return _dev->get_rx_gain_names(chan); + } + + shd::gain_range_t get_gain_range(size_t chan) + { + return _dev->get_rx_gain_range(chan); + } + + shd::gain_range_t get_gain_range(const std::string &name, + size_t chan) + { + return _dev->get_rx_gain_range(name, chan); + } + + void set_antenna(const std::string &ant, size_t chan) + { + return _dev->set_rx_antenna(ant, chan); + } + + std::string get_antenna(size_t chan) + { + return _dev->get_rx_antenna(chan); + } + + std::vector<std::string> get_antennas(size_t chan) + { + return _dev->get_rx_antennas(chan); + } + + void set_bandwidth(double bandwidth, size_t chan) + { + return _dev->set_rx_bandwidth(bandwidth, chan); + } + + shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan) + { + return _dev->get_rx_sensor(name, chan); + } + + std::vector<std::string> get_dboard_sensor_names(size_t chan) + { + return _dev->get_rx_sensor_names(chan); + } + + shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard) + { + return _dev->get_mboard_sensor(name, mboard); + } + + std::vector<std::string> get_mboard_sensor_names(size_t mboard) + { + return _dev->get_mboard_sensor_names(mboard); + } + + void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard) + { + return _dev->set_clock_config(clock_config, mboard); + } + + double get_clock_rate(size_t mboard) + { + return _dev->get_master_clock_rate(mboard); + } + + void set_clock_rate(double rate, size_t mboard) + { + return _dev->set_master_clock_rate(rate, mboard); + } + + shd::time_spec_t get_time_now(size_t mboard = 0) + { + return _dev->get_time_now(mboard); + } + + shd::time_spec_t get_time_last_pps(size_t mboard) + { + return _dev->get_time_last_pps(mboard); + } + + void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard) + { + return _dev->set_time_now(time_spec, mboard); + } + + void set_time_next_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_next_pps(time_spec); + } + + void set_time_unknown_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_unknown_pps(time_spec); + } + + shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan) + { + return _dev->get_rx_dboard_iface(chan); + } + + shd::xmini::multi_xmini::sptr get_device(void) + { + return _dev; + } + + /******************************************************************* + * Work + ******************************************************************/ + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //In order to allow for low-latency: + //We receive all available packets without timeout. + //This call can timeout under regular operation... + size_t num_samps = _dev->get_device()->recv( + output_items, noutput_items, _metadata, + _type, shd::device::RECV_MODE_FULL_BUFF, 0.0); + + //If receive resulted in a timeout condition: + //We now receive a single packet with a large timeout. + if(_metadata.error_code == shd::rx_metadata_t::ERROR_CODE_TIMEOUT) { + num_samps = _dev->get_device()->recv( + output_items, noutput_items, _metadata, + _type, shd::device::RECV_MODE_ONE_PACKET, 1.0); + } + + //handle possible errors conditions + switch(_metadata.error_code) { + case shd::rx_metadata_t::ERROR_CODE_NONE: + //TODO insert tag for time stamp + break; + + case shd::rx_metadata_t::ERROR_CODE_TIMEOUT: + //Assume that the user called stop() on the flow graph. + //However, a timeout can occur under error conditions. + return WORK_DONE; + + case shd::rx_metadata_t::ERROR_CODE_OVERFLOW: + //ignore overflows and try work again + //TODO insert tag for overflow + return work(noutput_items, input_items, output_items); + + default: + std::cout << boost::format("SHD source block got error code 0x%x" + ) % _metadata.error_code << std::endl; + return num_samps; + } + + return num_samps; + } + + bool start(void) + { + //setup a stream command that starts streaming slightly in the future + static const double reasonable_delay = 0.1; //order of magnitude over RTT + shd::stream_cmd_t stream_cmd(shd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + stream_cmd.stream_now = _stream_now; + stream_cmd.time_spec = get_time_now() + shd::time_spec_t(reasonable_delay); + _dev->issue_stream_cmd(stream_cmd); + return true; + } + + bool stop(void) + { + _dev->issue_stream_cmd(shd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + return true; + } + +private: + shd::xmini::multi_xmini::sptr _dev; + const shd::io_type_t _type; + size_t _nchan; + bool _stream_now; + gr_vector_void_star _tmp_buffs; + shd::rx_metadata_t _metadata; +}; + + +/********************************************************************* + * Make SHD Multi SMINI Source + ********************************************************************/ + +boost::shared_ptr<shd_smini_source> shd_make_smini_source( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels) +{ + return boost::shared_ptr<shd_smini_source>( + new shd_smini_source_impl(device_addr, io_type, num_channels)); +} diff --git a/gr-shd/swig/.gitignore b/gr-shd/swig/.gitignore new file mode 100644 index 000000000..23ae38f9b --- /dev/null +++ b/gr-shd/swig/.gitignore @@ -0,0 +1,8 @@ +/shd_swig.cc +/shd_swig.py +/Makefile +/Makefile.in +/guile +/python +/run_guile_tests +/run_tests diff --git a/gr-shd/swig/Makefile.am b/gr-shd/swig/Makefile.am new file mode 100644 index 000000000..3e155ba41 --- /dev/null +++ b/gr-shd/swig/Makefile.am @@ -0,0 +1,82 @@ +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common +include $(top_srcdir)/Makefile.swig + +TESTS = +EXTRA_DIST += run_tests.in run_guile_tests.in $(nobase_guile_DATA) +DISTCLEANFILES += run_tests run_guile_tests + +noinst_PYTHON = qa_shd.py +noinst_GUILE = shd.test + +AM_CPPFLAGS = \ + $(STD_DEFINES_AND_INCLUDES) \ + $(PYTHON_CPPFLAGS) \ + $(SHD_CPPFLAGS) \ + $(WITH_INCLUDES) + +shd_swig_swig_args = $(SHD_CPPFLAGS) + +if GUILE +nobase_guile_DATA = \ + gnuradio/shd.scm +endif + +# ---------------------------------------------------------------- +# The SWIG library + +TOP_SWIG_IFILES = \ + shd_swig.i + +# Install so that they end up available as: +# import gnuradio.shd +# This ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/shd +shd_swig_pythondir_category = \ + gnuradio/shd + +# additional libraries for linking with the SWIG-generated library +shd_swig_la_swig_libadd = \ + $(top_builddir)/gr-shd/lib/libgnuradio-shd.la + +# additional Python files to be installed along with the SWIG-generated one +shd_swig_python = \ + __init__.py + +# additional SWIG files to be installed +shd_swig_swiginclude_headers = + +shd_swig_swig_args = $(SHD_CPPFLAGS) + +## If SHD was installed, defined GR_HAVE_SHD for swigging headers +if GR_DEFINE_HAVE_SHD + shd_swig_swig_args += -DGR_HAVE_SHD +endif + +if PYTHON +TESTS += run_tests +endif + +if GUILE +TESTS += run_guile_tests +endif diff --git a/gr-shd/swig/Makefile.swig.gen b/gr-shd/swig/Makefile.swig.gen new file mode 100644 index 000000000..ebe843bbe --- /dev/null +++ b/gr-shd/swig/Makefile.swig.gen @@ -0,0 +1,145 @@ +# -*- Makefile -*- +# +# Copyright 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +# Makefile.swig.gen for shd_swig.i + +## Default install locations for these files: +## +## Default location for the Python directory is: +## ${prefix}/lib/python${python_version}/site-packages/[category]/shd_swig +## Default location for the Python exec directory is: +## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/shd_swig +## +## The following can be overloaded to change the install location, but +## this has to be done in the including Makefile.am -before- +## Makefile.swig is included. + +shd_swig_pythondir_category ?= gnuradio/shd_swig +shd_swig_pylibdir_category ?= $(shd_swig_pythondir_category) +shd_swig_pythondir = $(pythondir)/$(shd_swig_pythondir_category) +shd_swig_pylibdir = $(pyexecdir)/$(shd_swig_pylibdir_category) + +# The .so libraries for the guile modules get installed whereever guile +# is installed, usually /usr/lib/guile/gnuradio/ +# FIXME: determince whether these should be installed with gnuradio. +shd_swig_scmlibdir = $(libdir) + +# The scm files for the guile modules get installed where ever guile +# is installed, usually /usr/share/guile/site/shd_swig +# FIXME: determince whether these should be installed with gnuradio. +shd_swig_scmdir = $(guiledir) + +## SWIG headers are always installed into the same directory. + +shd_swig_swigincludedir = $(swigincludedir) + +## This is a template file for a "generated" Makefile addition (in +## this case, "Makefile.swig.gen"). By including the top-level +## Makefile.swig, this file will be used to generate the SWIG +## dependencies. Assign the variable TOP_SWIG_FILES to be the list of +## SWIG .i files to generated wrappings for; there can be more than 1 +## so long as the names are unique (no sorting is done on the +## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i +## file will generate .cc, .py, and possibly .h files -- meaning that +## all of these files will have the same base name (that provided for +## the SWIG .i file). +## +## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the +## right thing. For more info, see < +## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > + +## Other cleaned files: dependency files generated by SWIG or this Makefile + +MOSTLYCLEANFILES += $(DEPDIR)/*.S* + +## Various SWIG variables. These can be overloaded in the including +## Makefile.am by setting the variable value there, then including +## Makefile.swig . + +shd_swig_swiginclude_HEADERS = \ + shd_swig.i \ + $(shd_swig_swiginclude_headers) + +if PYTHON +shd_swig_pylib_LTLIBRARIES = \ + _shd_swig.la + +_shd_swig_la_SOURCES = \ + python/shd_swig.cc \ + $(shd_swig_la_swig_sources) + +shd_swig_python_PYTHON = \ + shd_swig.py \ + $(shd_swig_python) + +_shd_swig_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(shd_swig_la_swig_libadd) + +_shd_swig_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(shd_swig_la_swig_ldflags) + +_shd_swig_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(shd_swig_la_swig_cxxflags) + +python/shd_swig.cc: shd_swig.py +shd_swig.py: shd_swig.i + +# Include the python dependencies for this file +-include python/shd_swig.d + +endif # end of if python + +if GUILE + +shd_swig_scmlib_LTLIBRARIES = \ + libguile-gnuradio-shd_swig.la +libguile_gnuradio_shd_swig_la_SOURCES = \ + guile/shd_swig.cc \ + $(shd_swig_la_swig_sources) +nobase_shd_swig_scm_DATA = \ + gnuradio/shd_swig.scm \ + gnuradio/shd_swig-primitive.scm +libguile_gnuradio_shd_swig_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(shd_swig_la_swig_libadd) +libguile_gnuradio_shd_swig_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(shd_swig_la_swig_ldflags) +libguile_gnuradio_shd_swig_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(shd_swig_la_swig_cxxflags) + +guile/shd_swig.cc: gnuradio/shd_swig.scm +gnuradio/shd_swig.scm: shd_swig.i +gnuradio/shd_swig-primitive.scm: gnuradio/shd_swig.scm + +# Include the guile dependencies for this file +-include guile/shd_swig.d + +endif # end of GUILE + + diff --git a/gr-shd/swig/__init__.py b/gr-shd/swig/__init__.py new file mode 100644 index 000000000..17589625c --- /dev/null +++ b/gr-shd/swig/__init__.py @@ -0,0 +1,88 @@ +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +######################################################################## +# Prepare shd swig module to make it more pythonic +######################################################################## +def _prepare_shd_swig(): + import shd_swig + + #some useful typedefs for the user + setattr(shd_swig, 'freq_range_t', shd_swig.meta_range_t) + setattr(shd_swig, 'gain_range_t', shd_swig.meta_range_t) + + #Make the python tune request object inherit from float + #so that it can be passed in GRC as a frequency parameter. + #The type checking in GRC will accept the tune request. + class tune_request_t(shd_swig.tune_request_t, float): + def __new__(self, *args): return float.__new__(self) + def __float__(self): return self.target_freq + setattr(shd_swig, 'tune_request_t', tune_request_t) + + #Make the python tune request object inherit from string + #so that it can be passed in GRC as a string parameter. + #The type checking in GRC will accept the device address. + #Define the set/get item special methods for dict access. + class device_addr_t(shd_swig.device_addr_t, str): + def __new__(self, *args): return str.__new__(self) + def __getitem__(self, key): return self.get(key) + def __setitem__(self, key, val): self.set(key, val) + setattr(shd_swig, 'device_addr_t', device_addr_t) + + #handle general things on all shd_swig attributes + #Install the __str__ and __repr__ handlers if applicable + #Create aliases for shd swig attributes to avoid the "_t" + for attr in dir(shd_swig): + myobj = getattr(shd_swig, attr) + if hasattr(myobj, 'to_string'): myobj.__repr__ = lambda o: o.to_string().strip() + if hasattr(myobj, 'to_pp_string'): myobj.__str__ = lambda o: o.to_pp_string().strip() + if hasattr(myobj, 'to_bool'): myobj.__nonzero__ = lambda o: o.to_bool() + if hasattr(myobj, 'to_int'): myobj.__int__ = lambda o: o.to_int() + if hasattr(myobj, 'to_real'): myobj.__float__ = lambda o: o.to_real() + if attr.endswith('_t'): setattr(shd_swig, attr[:-2], myobj) + + #Cast constructor args (FIXME swig handle overloads?) + for attr in ('smini_source', 'smini_sink'): + def constructor_factory(old_constructor): + def constructor_interceptor(*args, **kwargs): + args = list(args) + kwargs = dict(kwargs) + for index, key, cast in ( + (0, 'device_addr', device_addr), + (1, 'io_type', io_type), + ): + if len(args) > index: args[index] = cast(args[index]) + if kwargs.has_key(key): kwargs[key] = cast(kwargs[key]) + return old_constructor(*args, **kwargs) + return constructor_interceptor + setattr(shd_swig, attr, constructor_factory(getattr(shd_swig, attr))) + + #Aliases for deprecated constructors + setattr(shd_swig, 'single_smini_source', shd_swig.smini_source) + setattr(shd_swig, 'single_smini_sink', shd_swig.smini_sink) + setattr(shd_swig, 'multi_smini_source', shd_swig.smini_source) + setattr(shd_swig, 'multi_smini_sink', shd_swig.smini_sink) + +######################################################################## +# Initialize this module with the contents of shd swig +######################################################################## +_prepare_shd_swig() +from shd_swig import * diff --git a/gr-shd/swig/gnuradio/.gitignore b/gr-shd/swig/gnuradio/.gitignore new file mode 100644 index 000000000..adf5c3727 --- /dev/null +++ b/gr-shd/swig/gnuradio/.gitignore @@ -0,0 +1,2 @@ +shd_swig-primitive.scm +shd_swig.scm diff --git a/gr-shd/swig/gnuradio/shd.scm b/gr-shd/swig/gnuradio/shd.scm new file mode 100644 index 000000000..91af98dd8 --- /dev/null +++ b/gr-shd/swig/gnuradio/shd.scm @@ -0,0 +1,27 @@ +;;; +;;; Copyright 2011 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;; + +;;; Semi bogus module that just reexports the shd_swig module + +(define-module (gnuradio shd) + #:use-module (gnuradio export-safely) + #:use-module (gnuradio shd_swig) + #:duplicates (merge-generics replace check)) + +(re-export-all '(gnuradio shd_swig)) diff --git a/gr-shd/swig/qa_shd.py b/gr-shd/swig/qa_shd.py new file mode 100755 index 000000000..538de918c --- /dev/null +++ b/gr-shd/swig/qa_shd.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005,2008,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import shd_swig + +class test_shd(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have a SHD device connected, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.run(test_shd, "test_shd.xml") diff --git a/gr-shd/swig/run_guile_tests.in b/gr-shd/swig/run_guile_tests.in new file mode 100644 index 000000000..5d08b0dd5 --- /dev/null +++ b/gr-shd/swig/run_guile_tests.in @@ -0,0 +1,14 @@ +#!/bin/sh + +. @top_builddir@/setup_guile_test_env + +# 1st argument is absolute path to hand coded guile source directory +# 2nd argument is absolute path to component C++ shared library build directory +# 3nd argument is absolute path to component SWIG build directory + +add_local_paths \ + @srcdir@ \ + @abs_builddir@ \ + @abs_builddir@ + +@GUILE@ -e main -c '(use-modules (gnuradio test-suite guile-test))' -t @srcdir@ diff --git a/gr-shd/swig/run_tests.in b/gr-shd/swig/run_tests.in new file mode 100644 index 000000000..580296374 --- /dev/null +++ b/gr-shd/swig/run_tests.in @@ -0,0 +1,10 @@ +#!/bin/sh + +# 1st parameter is absolute path to component source directory +# 2nd parameter is absolute path to component build directory +# 3rd parameter is path to Python QA directory + +@top_builddir@/run_tests.sh \ + @abs_top_srcdir@/gr-shd \ + @abs_top_builddir@/gr-shd \ + @srcdir@ diff --git a/gr-shd/swig/shd.test b/gr-shd/swig/shd.test new file mode 100644 index 000000000..7b118a081 --- /dev/null +++ b/gr-shd/swig/shd.test @@ -0,0 +1,37 @@ +;;; -*- Scheme -*- +;;; +;;; Copyright 2010 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;; + +;;; If you're using Emacs's Scheme mode: +;;; (put 'with-test-prefix 'scheme-indent-function 1) + +;;; See the comments in gnuradio/test-suite/lib.scm for info on writing tests. +;;; See also the very end of the file, where the test-equal, test-eqv +;;; and test-eq macros are defined. + +(define-module (test-module) + #:use-module (oop goops) + #:use-module (gnuradio core) + #:use-module (gnuradio test-suite lib) + #:duplicates (merge-generics replace check)) + +;;; Just see if we can import the module... +;;; They may not have a SHD device attached, powered up etc. + +(use-modules (gnuradio shd)) diff --git a/gr-shd/swig/shd_swig.i b/gr-shd/swig/shd_swig.i new file mode 100644 index 000000000..217b2f1af --- /dev/null +++ b/gr-shd/swig/shd_swig.i @@ -0,0 +1,135 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// Defined during configure; avoids trying to locate +// header files if SHD was not installed. +#ifdef GR_HAVE_SHD + +#define GR_SHD_API + +//////////////////////////////////////////////////////////////////////// +// Language independent exception handler +//////////////////////////////////////////////////////////////////////// +%include exception.i + +%exception { + try { + $action + } + catch(std::exception &e) { + SWIG_exception(SWIG_RuntimeError, e.what()); + } + catch(...) { + SWIG_exception(SWIG_RuntimeError, "Unknown exception"); + } + +} + +//////////////////////////////////////////////////////////////////////// +// standard includes +//////////////////////////////////////////////////////////////////////// +%include "gnuradio.i" + +//////////////////////////////////////////////////////////////////////// +// block headers +//////////////////////////////////////////////////////////////////////// +%{ +#include <gr_shd_smini_source.h> +#include <gr_shd_smini_sink.h> +%} + +//////////////////////////////////////////////////////////////////////// +// used types +//////////////////////////////////////////////////////////////////////// +%template(string_vector_t) std::vector<std::string>; + +%include <shd/config.hpp> + +%include <shd/utils/pimpl.hpp> + +%ignore shd::dict::operator[]; //ignore warnings about %extend +%include <shd/types/dict.hpp> +%template(string_string_dict_t) shd::dict<std::string, std::string>; //define after dict + +%include <shd/types/device_addr.hpp> + +%include <shd/types/io_type.hpp> + +%template(range_vector_t) std::vector<shd::range_t>; //define before range +%include <shd/types/ranges.hpp> + +%include <shd/types/tune_request.hpp> + +%include <shd/types/tune_result.hpp> + +%include <shd/types/io_type.hpp> + +%include <shd/types/time_spec.hpp> + +%include <shd/types/clock_config.hpp> + +%include <shd/types/metadata.hpp> + +%ignore shd::device::register_device; //causes compile to choke in MSVC +%include <shd/device.hpp> +%template(device_addr_vector_t) std::vector<shd::device_addr_t>; + +%include <shd/types/sensors.hpp> + +//////////////////////////////////////////////////////////////////////// +// swig dboard_iface for python access +//////////////////////////////////////////////////////////////////////// +%include stdint.i +%include <shd/types/serial.hpp> +%template(byte_vector_t) std::vector<uint8_t>; +%include <shd/xmini/dboard_iface.hpp> + +%template(dboard_iface_sptr) boost::shared_ptr<shd::xmini::dboard_iface>; + +//////////////////////////////////////////////////////////////////////// +// block magic +//////////////////////////////////////////////////////////////////////// +GR_SWIG_BLOCK_MAGIC(shd,smini_source) +%include <gr_shd_smini_source.h> + +GR_SWIG_BLOCK_MAGIC(shd,smini_sink) +%include <gr_shd_smini_sink.h> + +//////////////////////////////////////////////////////////////////////// +// helpful constants +//////////////////////////////////////////////////////////////////////// +%{ +static const size_t ALL_MBOARDS = shd::xmini::multi_xmini::ALL_MBOARDS; +%} +static const size_t ALL_MBOARDS; + +#if SWIGGUILE +%scheme %{ +(load-extension-global "libguile-gnuradio-shd_swig" "scm_init_gnuradio_shd_swig_module") +%} + +%goops %{ +(use-modules (gnuradio gnuradio_core_runtime)) +%} +#endif /* SWIGGUILE */ + +#endif /* GR_HAVE_SHD */ diff --git a/gr-uhd/Makefile.am b/gr-uhd/Makefile.am index ea16c863c..c81a1a049 100644 --- a/gr-uhd/Makefile.am +++ b/gr-uhd/Makefile.am @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common -SUBDIRS = include lib apps +SUBDIRS = include lib apps examples if PYTHON SUBDIRS += swig grc diff --git a/gr-uhd/apps/Makefile.am b/gr-uhd/apps/Makefile.am index 9bb9b6cdd..a9e28b9cd 100644 --- a/gr-uhd/apps/Makefile.am +++ b/gr-uhd/apps/Makefile.am @@ -24,6 +24,8 @@ include $(top_srcdir)/Makefile.common EXTRA_DIST += \ $(bin_SCRIPTS) +SUBDIRS = hf_explorer hf_radio + ourpythondir = $(grpythondir) bin_SCRIPTS = \ diff --git a/gnuradio-examples/python/apps/hf_explorer/.gitignore b/gr-uhd/apps/hf_explorer/.gitignore index b6950912c..b6950912c 100644 --- a/gnuradio-examples/python/apps/hf_explorer/.gitignore +++ b/gr-uhd/apps/hf_explorer/.gitignore diff --git a/gnuradio-examples/python/apps/hf_explorer/Makefile.am b/gr-uhd/apps/hf_explorer/Makefile.am index 88ad52128..c8e7ecb25 100644 --- a/gnuradio-examples/python/apps/hf_explorer/Makefile.am +++ b/gr-uhd/apps/hf_explorer/Makefile.am @@ -28,4 +28,4 @@ dist_ourdata_DATA = \ hfx_help dist_ourdata_SCRIPTS = \ - hfx2.py + hfx.py diff --git a/gr-uhd/apps/hf_explorer/README b/gr-uhd/apps/hf_explorer/README new file mode 100644 index 000000000..57f45ceba --- /dev/null +++ b/gr-uhd/apps/hf_explorer/README @@ -0,0 +1,42 @@ +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. + +---------------------------------------------------------- + +Powermate knob supported but not required, tooltip frequency display, +single click tuning, AGC, record to disk, play from disk and record +audio. 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/gr-uhd/apps/hf_explorer/hfx.py index 00a3b9047..687adf82b 100755 --- a/gnuradio-examples/python/apps/hf_explorer/hfx2.py +++ b/gr-uhd/apps/hf_explorer/hfx.py @@ -1,8 +1,7 @@ #!/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. +# Copyright 2006,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -81,10 +80,13 @@ AM_SYNC_DISPLAY = False import os, wx, sys, math import wx.lib.evtmgr as em from gnuradio.wxgui import powermate, fftsink2 -from gnuradio import gr, audio, eng_notation, usrp, gru +from gnuradio import gr, audio, eng_notation from gnuradio.eng_option import eng_option +from gnuradio import uhd from optparse import OptionParser +n2s = eng_notation.num_to_str + ID_BUTTON_1 = wx.NewId() # LSB button ID_BUTTON_2 = wx.NewId() # USB ID_BUTTON_3 = wx.NewId() # AM @@ -111,20 +113,6 @@ 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__ @@ -135,7 +123,8 @@ class MyFrame(wx.Frame): 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) + 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 @@ -145,9 +134,11 @@ class MyFrame(wx.Frame): 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.slider_fcutoff_hi = wx.Slider(self, ID_SLIDER_1, 0, -15798, 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.slider_fcutoff_lo = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15798, + 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, "") @@ -169,9 +160,11 @@ class MyFrame(wx.Frame): 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.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.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") @@ -184,26 +177,30 @@ class MyFrame(wx.Frame): # end wxGlade parser = OptionParser (option_class=eng_option) + parser.add_option("", "--address", type="string", default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") parser.add_option ("-c", "--ddc-freq", type="eng_float", default=3.9e6, help="set Rx DDC frequency to FREQ", metavar="FREQ") + parser.add_option ("-s", "--samp-rate", type="eng_float", default=256e3, + help="set sample rate (bandwidth) [default=%default]") 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)") + parser.add_option ("-O", "--audio-output", type="string", default="", + help="audio output device name. E.g., hw:0,0, /dev/dsp, or pulse") + (options, args) = parser.parse_args () self.usrp_center = options.ddc_freq - usb_rate = 64e6 / options.decim - self.slider_range = usb_rate * 0.9375 + input_rate = options.samp_rate + self.slider_range = input_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) + fir_decim = long (input_rate / self.af_sample_rate) # data point arrays for antenna tuner self.xdata = [] @@ -215,7 +212,7 @@ class MyFrame(wx.Frame): 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.f_slider_scale = 10000 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) @@ -245,40 +242,40 @@ class MyFrame(wx.Frame): else: self.PLAY_FROM_USRP = False if self.PLAY_FROM_USRP: - self.src = usrp.source_s(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) + self.src = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + self.src.set_samp_rate(input_rate) + input_rate = self.src.get_samp_rate() + + self.src.set_center_freq(self.usrp_center, 0) + self.tune_offset = 0 else: self.src = gr.file_source (gr.sizeof_short,options.input_file) self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band + # convert rf data in interleaved short int form to complex + s2ss = gr.stream_to_streams(gr.sizeof_short,2) + s2f1 = gr.short_to_float() + s2f2 = gr.short_to_float() + src_f2c = gr.float_to_complex() + self.tb.connect(self.src,s2ss) + self.tb.connect((s2ss,0),s2f1) + self.tb.connect((s2ss,1),s2f2) + self.tb.connect(s2f1,(src_f2c,0)) + self.tb.connect(s2f2,(src_f2c,1)) + # save radio data to a file if SAVE_RADIO_TO_FILE: - file = gr.file_sink(gr.sizeof_short, options.radio_file) - self.tb.connect (self.src, file) + radio_file = gr.file_sink(gr.sizeof_short, options.radio_file) + self.tb.connect (self.src, radio_file) # 2nd DDC xlate_taps = gr.firdes.low_pass ( \ - 1.0, usb_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING ) + 1.0, input_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING ) self.xlate = gr.freq_xlating_fir_filter_ccf ( \ - fir_decim, xlate_taps, self.tune_offset, usb_rate ) - - # convert rf data in interleaved short int form to complex - s2ss = gr.stream_to_streams(gr.sizeof_short,2) - s2f1 = gr.short_to_float() - s2f2 = gr.short_to_float() - src_f2c = gr.float_to_complex() - self.tb.connect(self.src,s2ss) - self.tb.connect((s2ss,0),s2f1) - self.tb.connect((s2ss,1),s2f2) - self.tb.connect(s2f1,(src_f2c,0)) - self.tb.connect(s2f2,(src_f2c,1)) - + fir_decim, xlate_taps, self.tune_offset, input_rate ) # Complex Audio filter audio_coeffs = gr.firdes.complex_band_pass ( @@ -288,17 +285,22 @@ class MyFrame(wx.Frame): 0, # high cutoff 100, # transition gr.firdes.WIN_HAMMING) # window - self.slider_1.SetValue(0) - self.slider_2.SetValue(-3000) + self.slider_fcutoff_hi.SetValue(0) + self.slider_fcutoff_lo.SetValue(-3000) - self.audio_filter = gr.fir_filter_ccc ( 1, audio_coeffs) + self.audio_filter = gr.fir_filter_ccc(1, audio_coeffs) # Main +/- 16Khz spectrum display - self.fft = fftsink2.fft_sink_c (self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240)) + self.fft = fftsink2.fft_sink_c(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.tb, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240)) + self.fft2 = fftsink.fft_sink_c(self.tb, 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() @@ -307,7 +309,8 @@ class MyFrame(wx.Frame): # 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)) + 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 @@ -327,7 +330,7 @@ class MyFrame(wx.Frame): 100, # transition gr.firdes.WIN_HAMMING) # window - self.pll_carrier_filter = gr.fir_filter_ccc ( 1, pll_carrier_coeffs) + self.pll_carrier_filter = gr.fir_filter_ccc (1, pll_carrier_coeffs) self.sel_sb = gr.multiply_const_ff(1) combine = gr.add_ff() @@ -338,20 +341,29 @@ class MyFrame(wx.Frame): 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)) + dst = audio.sink(long(self.af_sample_rate), + options.audio_output) + + + if self.PLAY_FROM_USRP: + self.tb.connect(self.src, self.xlate, self.fft) + else: + self.tb.connect(src_f2c, self.xlate, self.fft) - self.tb.connect(src_f2c,self.xlate,self.fft) self.tb.connect(self.xlate,self.audio_filter,self.sel_am,(am_det,0)) - self.tb.connect(self.sel_am,pll,self.pll_carrier_scale,self.pll_carrier_filter,c2f3) + self.tb.connect(self.sel_am,pll,self.pll_carrier_scale, + self.pll_carrier_filter,c2f3) self.tb.connect((c2f3,0),phaser1,(f2c,0)) self.tb.connect((c2f3,1),phaser2,(f2c,1)) self.tb.connect(f2c,(am_det,1)) self.tb.connect(am_det,c2f2,(combine,0)) - self.tb.connect(self.audio_filter,c2f,self.sel_sb,(combine,1)) + self.tb.connect(self.audio_filter,c2f, + self.sel_sb,(combine,1)) + if AM_SYNC_DISPLAY: self.tb.connect(self.pll_carrier_filter,self.fft2) + self.tb.connect(combine,self.scale) self.tb.connect(self.scale,(sqr1,0)) self.tb.connect(self.scale,(sqr1,1)) @@ -368,9 +380,9 @@ class MyFrame(wx.Frame): self.tb.start() # for mouse position reporting on fft display - em.eventManager.Register(self.Mouse, wx.EVT_MOTION, self.fft.win) + self.fft.win.Bind(wx.EVT_LEFT_UP, self.Mouse) # and left click to re-tune - em.eventManager.Register(self.Click, wx.EVT_LEFT_DOWN, self.fft.win) + self.fft.win.Bind(wx.EVT_LEFT_DOWN, self.Click) # start a timer to check for web commands if WEB_CONTROL: @@ -403,9 +415,9 @@ class MyFrame(wx.Frame): 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.SetTitle("HF Explorer") + self.slider_fcutoff_hi.SetMinSize((450, 38)) + self.slider_fcutoff_lo.SetMinSize((450, 38)) self.panel_2.SetMinSize((640, 240)) self.button_7.SetValue(1) self.slider_3.SetMinSize((450, 19)) @@ -434,11 +446,14 @@ class MyFrame(wx.Frame): 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.slider_fcutoff_hi, 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) + grid_sizer_1.Add(self.slider_fcutoff_lo, 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.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) @@ -461,9 +476,11 @@ class MyFrame(wx.Frame): 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.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.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) @@ -488,14 +505,14 @@ class MyFrame(wx.Frame): # 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.slider_fcutoff_hi.SetValue(self.slider_fcutoff_hi.GetValue()+event.delta) + if self.slider_fcutoff_lo.GetValue() > (self.slider_fcutoff_hi.GetValue() - 200) : + self.slider_fcutoff_lo.SetValue(self.slider_fcutoff_hi.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.slider_fcutoff_lo.SetValue(self.slider_fcutoff_lo.GetValue()+event.delta) + if self.slider_fcutoff_hi.GetValue() < (self.slider_fcutoff_lo.GetValue() + 200) : + self.slider_fcutoff_hi.SetValue(self.slider_fcutoff_lo.GetValue() + 200) self.filter() if self.active_button == 7: new = max(0, min(6000, self.slider_3.GetValue() + event.delta)) @@ -581,14 +598,14 @@ class MyFrame(wx.Frame): # Make sure filter settings are legal def set_filter(self, event): slider = event.GetId() - slider1 = self.slider_1.GetValue() - slider2 = self.slider_2.GetValue() + slider1 = self.slider_fcutoff_hi.GetValue() + slider2 = self.slider_fcutoff_lo.GetValue() if slider == ID_SLIDER_1: - if slider2 > (self.slider_1.GetValue() - 200) : - self.slider_2.SetValue(slider1 - 200) + if slider2 > (self.slider_fcutoff_hi.GetValue() - 200) : + self.slider_fcutoff_lo.SetValue(slider1 - 200) elif slider == ID_SLIDER_2: - if slider1 < (self.slider_2.GetValue() + 200) : - self.slider_1.SetValue(slider2 + 200) + if slider1 < (self.slider_fcutoff_lo.GetValue() + 200) : + self.slider_fcutoff_hi.SetValue(slider2 + 200) self.filter() # Calculate taps and apply @@ -596,8 +613,8 @@ class MyFrame(wx.Frame): 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 + self.slider_fcutoff_lo.GetValue(), # low cutoff + self.slider_fcutoff_hi.GetValue(), # high cutoff 100, # transition gr.firdes.WIN_HAMMING) # window self.audio_filter.set_taps(audio_coeffs) @@ -607,8 +624,8 @@ class MyFrame(wx.Frame): 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.slider_fcutoff_hi.SetValue(0) + self.slider_fcutoff_lo.SetValue(-3000) self.filter() def set_usb(self, event): @@ -616,8 +633,8 @@ class MyFrame(wx.Frame): 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.slider_fcutoff_hi.SetValue(3000) + self.slider_fcutoff_lo.SetValue(0) self.filter() def set_am(self, event): @@ -625,8 +642,8 @@ class MyFrame(wx.Frame): 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.slider_fcutoff_hi.SetValue(12500) + self.slider_fcutoff_lo.SetValue(2500) self.filter() def set_cw(self, event): @@ -635,8 +652,8 @@ class MyFrame(wx.Frame): 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.slider_fcutoff_hi.SetValue(-400) + self.slider_fcutoff_lo.SetValue(-800) self.filter() def set_volume(self, event): @@ -644,7 +661,7 @@ class MyFrame(wx.Frame): def set_pga(self,event): if self.PLAY_FROM_USRP: - self.subdev.set_gain(self.slider_5.GetValue()) + self.src.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 @@ -731,8 +748,11 @@ class MyFrame(wx.Frame): # 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()) - + dev = self.src.get_dboard_iface() + dev.write_aux_dac(uhd.dboard_iface.UNIT_RX, + uhd.dboard_iface.AUX_DAC_C, + float(self.slider_7.GetValue())) + # Timer events - check for web commands def OnUpdate(self): cmds = os.listdir("/var/www/cgi-bin/commands/") @@ -791,11 +811,13 @@ class UpdateTimer(wx.Timer): class MyApp(wx.App): def OnInit(self): - frame = MyFrame(None, -1, "HF Explorer 2") + frame = MyFrame(None, -1, "HF Explorer") frame.Show(True) self.SetTopWindow(frame) return True -app = MyApp(0) -app.MainLoop() + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx_help b/gr-uhd/apps/hf_explorer/hfx_help index 9a52dd2bb..9a52dd2bb 100644 --- a/gnuradio-examples/python/apps/hf_explorer/hfx_help +++ b/gr-uhd/apps/hf_explorer/hfx_help diff --git a/gnuradio-examples/python/apps/hf_radio/.gitignore b/gr-uhd/apps/hf_radio/.gitignore index b6950912c..b6950912c 100644 --- a/gnuradio-examples/python/apps/hf_radio/.gitignore +++ b/gr-uhd/apps/hf_radio/.gitignore diff --git a/gnuradio-examples/python/apps/hf_radio/Makefile.am b/gr-uhd/apps/hf_radio/Makefile.am index e514076f6..e514076f6 100644 --- a/gnuradio-examples/python/apps/hf_radio/Makefile.am +++ b/gr-uhd/apps/hf_radio/Makefile.am diff --git a/gnuradio-examples/python/apps/hf_radio/README.TXT b/gr-uhd/apps/hf_radio/README.TXT index 7c7edf5e0..7c7edf5e0 100644 --- a/gnuradio-examples/python/apps/hf_radio/README.TXT +++ b/gr-uhd/apps/hf_radio/README.TXT diff --git a/gnuradio-examples/python/apps/hf_radio/hfir.sci b/gr-uhd/apps/hf_radio/hfir.sci index a2d5e2a62..a2d5e2a62 100644 --- a/gnuradio-examples/python/apps/hf_radio/hfir.sci +++ b/gr-uhd/apps/hf_radio/hfir.sci diff --git a/gr-uhd/apps/hf_radio/input.py b/gr-uhd/apps/hf_radio/input.py new file mode 100644 index 000000000..2626ddfb5 --- /dev/null +++ b/gr-uhd/apps/hf_radio/input.py @@ -0,0 +1,78 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +# 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 +from gnuradio import uhd + +class uhd_input(gr.hier_block2): + def __init__( self, address, samp_rate): + gr.hier_block2.__init__(self, "uhd_input", + gr.io_signature(0,0,0), + gr.io_signature(1,1,gr.sizeof_gr_complex)) + + self.src = uhd.usrp_source(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.src.set_samp_rate(samp_rate) + self.usrp_rate = self.src.get_samp_rate() + + self.connect(self.src, self) + + def set_freq(self, target_freq): + """ + Set the center frequency. + + @param target_freq: frequency in Hz + @type: bool + """ + r = self.src.set_center_freq(target_freq, 0) + + if r: + self.freq = target_freq + return True + else: + return False + + def get_freq(self): + return self.src.get_center_freq(0) + + def set_gain(self, gain): + self.gain = gain + self.src.set_gain(gain, 0) + + def add_options(parser): + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + 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)") + add_options = staticmethod(add_options) diff --git a/gr-uhd/apps/hf_radio/output.py b/gr-uhd/apps/hf_radio/output.py new file mode 100644 index 000000000..8ee7dc54c --- /dev/null +++ b/gr-uhd/apps/hf_radio/output.py @@ -0,0 +1,42 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + + +# Audio output with a volume control. +# +# M. Revnell 2005-Dec + +from gnuradio import gr, gru +from gnuradio import audio + +class output( gr.hier_block2 ): + def __init__( self, rate, device ): + gr.hier_block2.__init__(self, "output", + gr.io_signature(1,1,gr.sizeof_float), + gr.io_signature(0,0,0)) + + self.vol = gr.multiply_const_ff( 0.1 ) + self.out = audio.sink( int(rate), device ) + + self.connect( self, self.vol, self.out ) + + def set( self, val ): + self.vol.set_k( val ) + diff --git a/gnuradio-examples/python/apps/hf_radio/radio.py b/gr-uhd/apps/hf_radio/radio.py index 9f444b916..32e26c7eb 100755 --- a/gnuradio-examples/python/apps/hf_radio/radio.py +++ b/gr-uhd/apps/hf_radio/radio.py @@ -1,11 +1,29 @@ #!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# # 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 * @@ -15,11 +33,11 @@ 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 gnuradio import uhd +from gnuradio import blks2 +from gnuradio.wxgui import fftsink2 +from gnuradio.wxgui import waterfallsink2 +from gnuradio.wxgui import scopesink2 from input import * from output import * @@ -28,35 +46,36 @@ 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 +class radio_top_block( gr.top_block ): + def __init__( self ): + gr.top_block.__init__(self, "radio_top_block") + + self.address = "addr=192.168.11.2" + self.samp_rate = 256e3 + self.freq = -2.5e6 + self.gain = 0 + self.src = uhd_input( self.address, + self.samp_rate) + self.src.set_freq(self.freq) + self.src.set_gain(self.gain) + + self.fe_rate = self.src.usrp_rate 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.audio_dev = "pulse" - 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 ) + self.demod = ssb_demod( self.demod_rate, self.audio_rate ) + self.agc = agc() + self.out = output( self.audio_rate, self.audio_dev ) - fg.connect( self.src.src, - self.demod, - self.agc, - self.out ) - - gr.hier_block.__init__( self, fg, None, None ) + self.connect( self.src, self.demod, self.agc, self.out ) 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 + demod_cf = fe_target - self.src.get_freq() self.demod.tune( demod_cf ) class radio_frame( ui_frame ): @@ -88,35 +107,30 @@ class radio_frame( ui_frame ): 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.fespectrum = fftsink2.fft_sink_c( self.fe_panel, fft_size=512, sample_rate = block.fe_rate, - baseband_freq = 0, - average = False, - size = ( 680, 140 ) ) + ref_scale = 1.0, + ref_level = 20.0, + y_divs = 12, + avg_alpha = 0.1) - self.ifspectrum = fftsink.fft_sink_c( - self.block.graph, + self.ifspectrum = fftsink2.fft_sink_c( 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 ) + ref_scale = 1.0, + ref_level = 20.0, + y_divs = 12, + avg_alpha = 0.1) - em.eventManager.Register( self.fe_click, - wx.EVT_LEFT_DOWN, - self.fespectrum.win ) + self.fespectrum.win.Bind( wx.EVT_MOTION, self.fe_mouse) + self.fespectrum.win.Bind( wx.EVT_LEFT_DOWN, self.fe_click) - block.graph.connect( block.src.src, self.fespectrum ) - block.graph.connect( block.demod.xlate, self.ifspectrum ) + block.connect( block.src.src, self.fespectrum ) + block.connect( block.demod.xlate, self.ifspectrum ) def agc_ref_up( self, event ): self.agc_ref_s.SetValue( 5 ) @@ -232,7 +246,7 @@ class radio_frame( ui_frame ): self.tune( self.freq_disp.GetValue() - 1e6 ) def event_pga( self, event ): - self.block.src.src.set_pga( 0, self.pga.GetValue()) + self.block.src.set_gain(self.pga.GetValue()) def event_vol( self, event ): self.block.out.set( self.volume.GetValue()/20.0 ) @@ -267,38 +281,39 @@ class radio_frame( ui_frame ): 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.block = radio_top_block() + self.frame = radio_frame( self.block, None, -1, "HF Receiver" ) self.frame.Show( True ) self.SetTopWindow( self.frame ) + self.block.start() 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() + global radio_obj + global sig_probe + + go = True + while go: + try: + level = sig_probe.level() + wx.CallAfter( radio_obj.frame.setrssi, level ) + time.sleep( .1 ) + except: + go = False + +def main(): + global radio_obj, sig_probe + + radio_obj = radio( 0 ) + sig_probe = gr.probe_signal_f() + radio_obj.block.connect(radio_obj.block.agc.offs, sig_probe) + + thread2 = Thread( target = rssi_function ) + thread2.start() + + radio_obj.MainLoop() + + +if __name__ == "__main__": + main() diff --git a/gnuradio-examples/python/apps/hf_radio/radio.xml b/gr-uhd/apps/hf_radio/radio.xml index 81daa19b0..81daa19b0 100644 --- a/gnuradio-examples/python/apps/hf_radio/radio.xml +++ b/gr-uhd/apps/hf_radio/radio.xml diff --git a/gnuradio-examples/python/apps/hf_radio/ssb_taps b/gr-uhd/apps/hf_radio/ssb_taps index 0ef3bbf26..0ef3bbf26 100644 --- a/gnuradio-examples/python/apps/hf_radio/ssb_taps +++ b/gr-uhd/apps/hf_radio/ssb_taps diff --git a/gr-uhd/apps/hf_radio/ssbagc.py b/gr-uhd/apps/hf_radio/ssbagc.py new file mode 100644 index 000000000..494712863 --- /dev/null +++ b/gr-uhd/apps/hf_radio/ssbagc.py @@ -0,0 +1,70 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + + +# post detection agc processing +# +# 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 + +class agc( gr.hier_block2 ): + def __init__( self ): + gr.hier_block2.__init__(self, "agc", + gr.io_signature(1,1,gr.sizeof_float), + gr.io_signature(1,1,gr.sizeof_float)) + + 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( ) + + self.connect(self, self.split) + self.connect(self.split, (self.agc, 0)) + self.connect(self.split, (self.sqr, 0)) + self.connect(self.split, (self.sqr, 1)) + self.connect(self.sqr, self.int0) + self.connect(self.int0, self.log) + self.connect(self.log, self.offs) + self.connect(self.offs, self.gain) + self.connect(self.gain, (self.agc, 1)) + self.connect(self.agc, self) diff --git a/gnuradio-examples/python/apps/hf_radio/ssbdemod.py b/gr-uhd/apps/hf_radio/ssbdemod.py index c73567b66..072d317a2 100644 --- a/gnuradio-examples/python/apps/hf_radio/ssbdemod.py +++ b/gr-uhd/apps/hf_radio/ssbdemod.py @@ -1,8 +1,26 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + # 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 @@ -13,16 +31,17 @@ # 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 +from gnuradio import gr -class ssb_demod( gr.hier_block ): - def __init__( self, fg, if_rate, af_rate ): +class ssb_demod( gr.hier_block2 ): + def __init__( self, if_rate, af_rate ): + gr.hier_block2.__init__(self, "ssb_demod", + gr.io_signature(1,1,gr.sizeof_gr_complex), + gr.io_signature(1,1,gr.sizeof_float)) - self.if_rate = if_rate - self.af_rate = af_rate - self.if_decim = if_rate / af_rate + self.if_rate = int(if_rate) + self.af_rate = int(af_rate) + self.if_decim = int(if_rate / af_rate) self.sideband = 1 self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) @@ -51,17 +70,17 @@ class ssb_demod( gr.hier_block ): 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 ) + self.connect(self, self.xlate) + self.connect(self.xlate, self.split) + self.connect((self.split, 0), (self.sum, 0)) + self.connect((self.split, 1), (self.sum, 1)) + self.connect(self.sum, self.sb_sel) + self.connect(self.xlate, self.am_det) + self.connect(self.sb_sel, (self.mixer, 0)) + self.connect(self.am_det, self.am_sel) + self.connect(self.am_sel, (self.mixer, 1)) + self.connect(self.mixer, self.lpf) + self.connect(self.lpf, self) def upper_sb( self ): self.xlate.set_taps([v.conjugate() for v in self.xlate_taps]) diff --git a/gnuradio-examples/python/apps/hf_radio/startup.py b/gr-uhd/apps/hf_radio/startup.py index 093369b57..093369b57 100644 --- a/gnuradio-examples/python/apps/hf_radio/startup.py +++ b/gr-uhd/apps/hf_radio/startup.py diff --git a/gnuradio-examples/python/apps/hf_radio/ui.py b/gr-uhd/apps/hf_radio/ui.py index 71b73c128..551a30415 100755 --- a/gnuradio-examples/python/apps/hf_radio/ui.py +++ b/gr-uhd/apps/hf_radio/ui.py @@ -1,4 +1,25 @@ #!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + # -*- coding: UTF-8 -*- # generated by wxGlade 0.4 on Mon Jan 2 19:02:03 2006 diff --git a/gr-uhd/examples/.gitignore b/gr-uhd/examples/.gitignore new file mode 100644 index 000000000..ad8a13c08 --- /dev/null +++ b/gr-uhd/examples/.gitignore @@ -0,0 +1,5 @@ +/Makefile +/Makefile.in +*.dat +*.32f +*.32fc diff --git a/gr-uhd/examples/Makefile.am b/gr-uhd/examples/Makefile.am new file mode 100644 index 000000000..b10b48928 --- /dev/null +++ b/gr-uhd/examples/Makefile.am @@ -0,0 +1,44 @@ +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = multi-antenna + +ourdatadir = $(exampledir)/uhd + +dist_ourdata_SCRIPTS = \ + fm_tx4.py \ + fm_tx_2_daughterboards.py \ + max_power.py \ + usrp_am_mw_rcv.py \ + usrp_nbfm_ptt.py \ + usrp_nbfm_rcv.py \ + usrp_spectrum_sense.py \ + usrp_tv_rcv_nogui.py \ + usrp_tv_rcv.py \ + usrp_wfm_rcv2_nogui.py \ + usrp_wfm_rcv_fmdet.py \ + usrp_wfm_rcv_nogui.py \ + usrp_wfm_rcv_pll.py \ + usrp_wfm_rcv.py \ + usrp_wfm_rcv_sca.py \ + usrp_wxapt_rcv.py diff --git a/gnuradio-examples/python/usrp/fm_tx4.py b/gr-uhd/examples/fm_tx4.py index a51668dde..9b39752c1 100755 --- a/gnuradio-examples/python/usrp/fm_tx4.py +++ b/gr-uhd/examples/fm_tx4.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -33,8 +33,7 @@ audio_to_file.py """ from gnuradio import gr, eng_notation -from gnuradio import usrp -from gnuradio import audio +from gnuradio import uhd from gnuradio import blks2 from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -43,7 +42,6 @@ import math import sys from gnuradio.wxgui import stdgui2, fftsink2 -#from gnuradio import tx_debug_gui import wx @@ -54,10 +52,17 @@ class pipeline(gr.hier_block2): def __init__(self, filename, lo_freq, audio_rate, if_rate): gr.hier_block2.__init__(self, "pipeline", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - src = gr.file_source (gr.sizeof_float, filename, True) + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + + try: + src = gr.file_source (gr.sizeof_float, filename, True) + except RuntimeError: + sys.stderr.write(("\nError: Could not open file '%s'\n\n" % \ + filename)) + sys.exit(1) + + print audio_rate, if_rate fmtx = blks2.nbfm_tx (audio_rate, if_rate, max_dev=5e3, tau=75e-6) # Local oscillator @@ -78,10 +83,17 @@ class fm_tx_block(stdgui2.std_top_block): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=400e3, + help="set sample rate (bandwidth) [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=None, - help="set Tx frequency to FREQ [required]", metavar="FREQ") + 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", "--nchannels", type="int", default=4, help="number of Tx channels [1,4]") #parser.add_option("","--debug", action="store_true", default=False, @@ -104,57 +116,54 @@ class fm_tx_block(stdgui2.std_top_block): # ---------------------------------------------------------------- # Set up constants and parameters - self.u = usrp.sink_c () # the USRP sink (consumes samples) + self.u = uhd.usrp_sink(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.usrp_rate = options.samp_rate + self.u.set_samp_rate(self.usrp_rate) + self.usrp_rate = self.u.get_samp_rate() - 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) + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2 - 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.set_gain(options.gain) + self.set_freq(options.freq) - self.subdev.set_gain(self.subdev.gain_range()[1]) # set max Tx gain - if not self.set_freq(options.freq): - freq_range = self.subdev.freq_range() - print "Failed to set frequency to %s. Daughterboard supports %s to %s" % ( - eng_notation.num_to_str(options.freq), - eng_notation.num_to_str(freq_range[0]), - eng_notation.num_to_str(freq_range[1])) - raise SystemExit - self.subdev.set_enable(True) # enable transmitter + if(options.antenna): + self.u.set_antenna(options.antenna, 0) - sum = gr.add_cc () + self.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) + offset = (0 * step, 1 * step, -1 * step, + 2 * step, -2 * step, 3 * step, -3 * step) + for i in range (options.nchannels): t = pipeline("audio-%d.dat" % (i % 4), offset[i], self.audio_rate, self.usrp_rate) - self.connect(t, (sum, i)) + self.connect(t, (self.sum, i)) - gain = gr.multiply_const_cc (4000.0 / options.nchannels) + self.gain = gr.multiply_const_cc (1.0 / options.nchannels) # connect it all - self.connect (sum, gain) - self.connect (gain, self.u) + self.connect (self.sum, self.gain) + self.connect (self.gain, self.u) # plot an FFT to verify we are sending what we want if 1: post_mod = fftsink2.fft_sink_c(panel, title="Post Modulation", - fft_size=512, sample_rate=self.usrp_rate, - y_per_div=20, ref_level=40) - self.connect (sum, post_mod) + fft_size=512, + sample_rate=self.usrp_rate, + y_per_div=20, + ref_level=40) + self.connect (self.gain, post_mod) vbox.Add (post_mod.win, 1, wx.EXPAND) @@ -177,18 +186,17 @@ class fm_tx_block(stdgui2.std_top_block): any residual_freq to the s/w freq translater. """ - r = self.u.tune(self.subdev.which(), self.subdev, target_freq) + r = self.u.set_center_freq(target_freq, 0) 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 + print "Frequency =", eng_notation.num_to_str(self.u.get_center_freq()) return True return False + def set_gain(self, gain): + self.u.set_gain(gain, 0) + + def main (): app = stdgui2.stdapp(fm_tx_block, "Multichannel FM Tx", nstatus=1) app.MainLoop () diff --git a/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py b/gr-uhd/examples/fm_tx_2_daughterboards.py index 15fdf2831..36d237616 100755 --- a/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py +++ b/gr-uhd/examples/fm_tx_2_daughterboards.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -30,14 +30,10 @@ Side A is 600 Hz tone. Side B is 350 + 440 Hz tones. """ -from gnuradio import gr +from gnuradio import gr, uhd, blks2 from gnuradio.eng_notation import num_to_str, str_to_num -from gnuradio import usrp -from gnuradio import audio -from gnuradio import blks2 from gnuradio.eng_option import eng_option from optparse import OptionParser -from usrpm import usrp_dbid import math import sys @@ -90,8 +86,17 @@ class my_top_block(gr.top_block): def __init__(self): gr.top_block.__init__(self) - usage="%prog: [options] side-A-tx-freq side-B-tx-freq" + usage="%prog: [options] tx-freq0 tx-freq1" parser = OptionParser (option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=320e3, + help="set sample rate [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") (options, args) = parser.parse_args () if len(args) != 2: @@ -104,32 +109,45 @@ class my_top_block(gr.top_block): # ---------------------------------------------------------------- # Set up USRP to transmit on both daughterboards - self.u = usrp.sink_c(nchan=2) # say we want two channels + d = uhd.device_find(uhd.device_addr(options.address)) + uhd_type = d[0].get('type') - 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.u = uhd.usrp_sink(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=2) - # 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) + # Set up USRP system based on type + if(uhd_type == "usrp"): + self.u.set_subdev_spec("A:0 B:0") + tr0 = uhd.tune_request(freq0) + tr1 = uhd.tune_request(freq1) - 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 + else: + if abs(freq0 - freq1) > 5.5e6: + sys.stderr.write("\nError: When not using two separate d'boards, frequencies must bewithin 5.5MHz of each other.\n") + raise SystemExit + + self.u.set_subdev_spec("A:0 A:0") + + mid_freq = (freq0 + freq1)/2.0 + tr0 = uhd.tune_request(freq0, rf_freq=mid_freq, + rf_freq_policy=uhd.tune_request.POLICY_MANUAL) + + tr1 = uhd.tune_request(freq1, rf_freq=mid_freq, + rf_freq_policy=uhd.tune_request.POLICY_MANUAL) + + # Use the tune requests to tune each channel + self.set_freq(tr0, 0) + self.set_freq(tr1, 1) + + self.usrp_rate = options.samp_rate - 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 + self.u.set_samp_rate(self.usrp_rate) + dev_rate = self.u.get_samp_rate() # ---------------------------------------------------------------- - # build two signal sources, interleave them, amplify and connect them to usrp + # build two signal sources, interleave them, amplify and + # connect them to usrp sig0 = example_signal_0(self.usrp_rate) sig1 = example_signal_1(self.usrp_rate) @@ -138,43 +156,45 @@ class my_top_block(gr.top_block): self.connect(sig0, (intl, 0)) self.connect(sig1, (intl, 1)) - # apply some gain - if_gain = 10000 - ifamp = gr.multiply_const_cc(if_gain) - + # Correct for any difference in requested and actual rates + rrate = self.usrp_rate / dev_rate + resamp = blks2.pfb_arb_resampler_ccf(rrate) + # and wire them up - self.connect(intl, ifamp, self.u) - + self.connect(intl, resamp, self.u) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 + + self.set_gain(options.gain, 0) + self.set_gain(options.gain, 1) - def set_freq(self, side, target_freq): + def set_freq(self, target_freq, chan): """ 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) + print "Tuning channel %s to %sHz" % \ + (chan, num_to_str(target_freq)) + + r = self.u.set_center_freq(target_freq, chan) + 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!" + print " Set Frequency Failed!" return False + def set_gain(self, gain, chan): + self.u.set_gain(gain, chan) if __name__ == '__main__': try: diff --git a/gr-uhd/examples/max_power.py b/gr-uhd/examples/max_power.py new file mode 100755 index 000000000..44d3beeee --- /dev/null +++ b/gr-uhd/examples/max_power.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +""" +Setup USRP for maximum power consumption. +""" + + +from gnuradio import gr +from gnuradio import uhd +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +from gnuradio import eng_notation + +n2s = eng_notation.num_to_str + +# Set this to a huge number; UHD will adjust to the +# maximum the USRP xxxx device can handle +MAX_RATE = 1000e6 + +class build_block(gr.top_block): + def __init__(self, address, tx_enable, rx_enable): + gr.top_block.__init__(self) + + d = uhd.device_find(uhd.device_addr(address)) + uhd_type = d[0].get('type') + + print "\nFound '%s' at address '%s'" % \ + (uhd_type, address) + + # Test the type of USRP; if it's a USRP (v1), it has + # 2 channels; otherwise, it has 1 channel + if uhd_type == "usrp": + tx_nchan = 2 + rx_nchan = 2 + else: + tx_nchan = 1 + rx_nchan = 1 + + if tx_enable: + print "\nTRANSMIT CHAIN" + self.u_tx = uhd.usrp_sink(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=tx_nchan) + self.u_tx.set_samp_rate(MAX_RATE) + + self.tx_src0 = gr.sig_source_c(self.u_tx.get_samp_rate(), + gr.GR_CONST_WAVE, + 0, 1.0, 0) + + # Get dboard gain range and select maximum + tx_gain_range = self.u_tx.get_gain_range() + tx_gain = tx_gain_range.stop() + + # Get dboard freq range and select midpoint + tx_freq_range = self.u_tx.get_freq_range() + tx_freq_mid = (tx_freq_range.start() + tx_freq_range.stop())/2.0 + + for i in xrange(tx_nchan): + self.u_tx.set_center_freq (tx_freq_mid + i*1e6, i) + self.u_tx.set_gain(tx_gain, i) + + print "\nTx Sample Rate: %ssps" % (n2s(self.u_tx.get_samp_rate())) + for i in xrange(tx_nchan): + print "Tx Channel %d: " % (i) + print "\tFrequency = %sHz" % \ + (n2s(self.u_tx.get_center_freq(i))) + print "\tGain = %f dB" % (self.u_tx.get_gain(i)) + print "" + + self.connect (self.tx_src0, self.u_tx) + + if rx_enable: + print "\nRECEIVE CHAIN" + self.u_rx = uhd.usrp_source(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=rx_nchan) + self.rx_dst0 = gr.null_sink (gr.sizeof_gr_complex) + + self.u_rx.set_samp_rate(MAX_RATE) + + # Get dboard gain range and select maximum + rx_gain_range = self.u_rx.get_gain_range() + rx_gain = rx_gain_range.stop() + + # Get dboard freq range and select midpoint + rx_freq_range = self.u_rx.get_freq_range() + rx_freq_mid = (rx_freq_range.start() + rx_freq_range.stop())/2.0 + + for i in xrange(tx_nchan): + self.u_rx.set_center_freq (rx_freq_mid + i*1e6, i) + self.u_rx.set_gain(rx_gain, i) + + print "\nRx Sample Rate: %ssps" % (n2s(self.u_rx.get_samp_rate())) + for i in xrange(rx_nchan): + print "Rx Channel %d: " % (i) + print "\tFrequency = %sHz" % \ + (n2s(self.u_rx.get_center_freq(i))) + print "\tGain = %f dB" % (self.u_rx.get_gain(i)) + print "" + + self.connect (self.u_rx, self.rx_dst0) + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + 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 () + + tb = build_block (options.address, options.tx_enable, options.rx_enable) + + tb.start () + raw_input ('Press Enter to quit: ') + tb.stop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/.gitignore b/gr-uhd/examples/multi-antenna/.gitignore index ff40c06f3..ff40c06f3 100644 --- a/gnuradio-examples/python/multi-antenna/.gitignore +++ b/gr-uhd/examples/multi-antenna/.gitignore diff --git a/gnuradio-examples/python/multi-antenna/Makefile.am b/gr-uhd/examples/multi-antenna/Makefile.am index 0cb944589..0cb944589 100644 --- a/gnuradio-examples/python/multi-antenna/Makefile.am +++ b/gr-uhd/examples/multi-antenna/Makefile.am diff --git a/gr-uhd/examples/multi-antenna/multi_fft.py b/gr-uhd/examples/multi-antenna/multi_fft.py new file mode 100755 index 000000000..d4c878c84 --- /dev/null +++ b/gr-uhd/examples/multi-antenna/multi_fft.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, eng_notation +from gnuradio import uhd +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2 +from gnuradio.wxgui import scopesink2, form, slider +import wx +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + +class my_graph(stdgui2.std_top_block): + + def __init__(self, frame, panel, vbox, argv): + stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [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("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + parser.add_option("-N", "--nchans", type="int", default=1, + help="set number of channels (default=%default)") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + self.nchans = options.nchans + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=self.nchans) + self.u.set_samp_rate(options.samp_rate) + input_rate = self.u.get_samp_rate() + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.u.get_freq_range() + options.freq = float(r.start()+r.stop())/2 + + self.set_gain(options.gain) + self.set_freq(options.freq) + + #if self.u.nddcs() < nchan: + # sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + # nchan, self.u.nddcs())) + # raise SystemExit + + #if (len (self.subdev) < 4 or + # self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or + # self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX): + # sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + # sys.exit(1) + + # 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(self.nchans): + scope = fftsink2.fft_sink_c(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) + + def set_gain(self, gain): + for i in range(self.nchans): + self.u.set_gain(gain, i) + + + def set_freq(self, target_freq): + for i in range(self.nchans): + r = self.u.set_center_freq(target_freq, 0) + + if r: + return True + else: + print "set_freq: failed to set subdev[%d] freq to %f" % \ + (i, target_freq) + return False + +def main (): + app = stdgui2.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/gr-uhd/examples/multi-antenna/multi_file.py index 87d9085e3..87d9085e3 100755 --- a/gnuradio-examples/python/multi-antenna/multi_file.py +++ b/gr-uhd/examples/multi-antenna/multi_file.py diff --git a/gnuradio-examples/python/multi-antenna/multi_scope.py b/gr-uhd/examples/multi-antenna/multi_scope.py index d1e28ad18..d1e28ad18 100755 --- a/gnuradio-examples/python/multi-antenna/multi_scope.py +++ b/gr-uhd/examples/multi-antenna/multi_scope.py diff --git a/gnuradio-examples/python/usrp/usrp_am_mw_rcv.py b/gr-uhd/examples/usrp_am_mw_rcv.py index 60f6c5825..130bdcf56 100755 --- a/gnuradio-examples/python/usrp/usrp_am_mw_rcv.py +++ b/gr-uhd/examples/usrp_am_mw_rcv.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,9 +20,9 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import gr, eng_notation, optfir from gnuradio import audio -from gnuradio import usrp +from gnuradio import uhd from gnuradio import blks2 from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate @@ -33,30 +33,18 @@ 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: BASIC_RX,TV_RX, BASIC_RX, whatever is on side A. - - @return a subdev_spec - """ - return usrp.pick_subdev(u, (usrp_dbid.BASIC_RX, - usrp_dbid.LF_RX, - usrp_dbid.TV_RX, - usrp_dbid.TV_RX_REV_2, - usrp_dbid.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO)) - - class wfm_rx_block (stdgui2.std_top_block): - def __init__(self,frame,panel,vbox,argv): - stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) + def __init__(self, frame, panel, vbox, argv): + stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=1008.0e3, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-I", "--use-if-freq", action="store_true", default=False, @@ -86,77 +74,72 @@ class wfm_rx_block (stdgui2.std_top_block): self.freq = 0 # build graph + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + usrp_rate = 256e3 + demod_rate = 64e3 + audio_rate = 32e3 + chanfilt_decim = int(usrp_rate // demod_rate) + audio_decim = int(demod_rate // audio_rate) + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() - #TODO: add an AGC after the channel filter and before the AM_demod + # Resample signal to exactly self.usrp_rate + # FIXME: make one of the follow-on filters an arb resampler + rrate = usrp_rate / dev_rate + self.resamp = blks2.pfb_arb_resampler_ccf(rrate) - self.u = usrp.source_c() # usrp is data source - - adc_rate = self.u.adc_rate() # 64 MS/s - usrp_decim = 250 - self.u.set_decim_rate(usrp_decim) - usrp_rate = adc_rate / usrp_decim # 256 kS/s - chanfilt_decim = 4 - demod_rate = usrp_rate / chanfilt_decim # 64 kHz - audio_decimation = 2 - 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 - 8e3, # passband cutoff - 12e3, # stopband cutoff - 1.0, # passband ripple - 60) # stopband attenuation - #print len(chan_filt_coeffs) - self.chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + chan_filt_coeffs = gr.firdes.low_pass_2 (1, # gain + usrp_rate, # sampling rate + 8e3, # passband cutoff + 4e3, # transition bw + 60) # stopband attenuation + if self.use_IF: # Turn If to baseband and filter. - self.chan_filt = gr.freq_xlating_fir_filter_ccf (chanfilt_decim, chan_filt_coeffs, self.IF_freq, usrp_rate) + self.chan_filt = gr.freq_xlating_fir_filter_ccf (chanfilt_decim, + chan_filt_coeffs, + self.IF_freq, + usrp_rate) else: self.chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) - self.am_demod = gr.complex_to_mag() + self.agc = gr.agc_cc(0.1, 1, 1, 100000) + self.am_demod = gr.complex_to_mag() self.volume_control = gr.multiply_const_ff(self.vol) - audio_filt_coeffs = optfir.low_pass (1, # gain - demod_rate, # sampling rate - 8e3, # passband cutoff - 10e3, # stopband cutoff - 0.1, # passband ripple - 60) # stopband attenuation - self.audio_filt=gr.fir_filter_fff(audio_decimation,audio_filt_coeffs) + audio_filt_coeffs = gr.firdes.low_pass_2 (1, # gain + demod_rate, # sampling rate + 8e3, # passband cutoff + 2e3, # transition bw + 60) # stopband attenuation + self.audio_filt=gr.fir_filter_fff(audio_decim, audio_filt_coeffs) + # sound card as final sink - audio_sink = audio.sink (int (audio_rate), - options.audio_output, - False) # ok_to_block + self.audio_sink = audio.sink (int (audio_rate), + options.audio_output, + False) # ok_to_block # now wire it all together - self.connect (self.u, self.chan_filt, self.am_demod, self.audio_filt, self.volume_control, audio_sink) + self.connect (self.u, self.resamp, self.chan_filt, self.agc, + self.am_demod, self.audio_filt, + self.volume_control, self.audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: - g = self.subdev.gain_range() + g = self.u.get_gain_range() if True: - # if no gain was specified, use the maximum gain available - # (usefull for Basic_RX which is relatively deaf and the most probable board to be used for AM) - # TODO: check db type to decide on default gain. - options.gain = float(g[1]) - else: - # if no gain was specified, use the mid-point in dB - options.gain = float(g[0]+g[1])/2 - + # if no gain was specified, use the mid gain + options.gain = (g.start() + g.stop())/2.0 + options.gain = g.stop() if options.volume is None: - g = self.volume_range() - options.volume = float(g[0]*3+g[1])/4 + v = self.volume_range() + options.volume = float(v[0]*3+v[1])/4.0 if abs(options.freq) < 1e3: options.freq *= 1e3 @@ -168,6 +151,8 @@ class wfm_rx_block (stdgui2.std_top_block): if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") + if(options.antenna): + self.u.set_antenna(options.antenna, 0) def _set_status_msg(self, msg, which=0): self.frame.GetStatusBar().SetStatusText(msg, which) @@ -179,7 +164,7 @@ class wfm_rx_block (stdgui2.std_top_block): return self.set_freq(kv['freq']) - if 1: + if 0: self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP", fft_size=512, sample_rate=usrp_rate, ref_scale=32768.0, ref_level=0.0, y_divs=12) @@ -233,9 +218,10 @@ class wfm_rx_block (stdgui2.std_top_block): callback=self.set_vol) hbox.Add((5,0), 1) + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -291,14 +277,8 @@ class wfm_rx_block (stdgui2.std_top_block): @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 + self.IF_freq) - #TODO: check if db is inverting the spectrum or not to decide if we should do + self.IF_freq or - self.IF_freq + r = self.u.set_center_freq(target_freq + self.IF_freq, 0) if r: self.freq = target_freq @@ -313,7 +293,7 @@ class wfm_rx_block (stdgui2.std_top_block): def set_gain(self, gain): self.myform['gain'].set_value(gain) # update displayed value - self.subdev.set_gain(gain) + self.u.set_gain(gain) def update_status_bar (self): msg = "Volume:%r Setting:%s" % (self.vol, self.state) diff --git a/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py b/gr-uhd/examples/usrp_nbfm_ptt.py index 3ce1e0c49..af3b132f4 100755 --- a/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py +++ b/gr-uhd/examples/usrp_nbfm_ptt.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2007 Free Software Foundation, Inc. +# Copyright 2005,2007.2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,10 +25,7 @@ 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 blks2 +from gnuradio import gr, audio, blks2, uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import stdgui2, fftsink2, scopesink2, slider, form from usrpm import usrp_dbid @@ -51,14 +48,17 @@ class ptt_block(stdgui2.std_top_block): 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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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 ("", "--tx-gain", type="eng_float", default=None, + help="set tx 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="", @@ -73,8 +73,10 @@ class ptt_block(stdgui2.std_top_block): if options.freq < 1e6: options.freq *= 1e6 - self.txpath = transmit_path(options.tx_subdev_spec, options.audio_input) - self.rxpath = receive_path(options.rx_subdev_spec, options.rx_gain, options.audio_output) + self.txpath = transmit_path(options.address, options.tx_gain, + options.audio_input) + self.rxpath = receive_path(options.address, options.rx_gain, + options.audio_output) self.connect(self.txpath) self.connect(self.rxpath) @@ -152,10 +154,10 @@ class ptt_block(stdgui2.std_top_block): vbox.Add (rx_fft.win, 1, wx.EXPAND) if 1 and not(no_gui): - rx_fft = fftsink2.fft_sink_c(panel, title="Post s/w DDC", + rx_fft = fftsink2.fft_sink_c(panel, title="Post s/w Resampler", fft_size=512, sample_rate=self.rxpath.quad_rate, ref_level=80, y_per_div=20) - self.connect (self.rxpath.ddc, rx_fft) + self.connect (self.rxpath.resamp, rx_fft) vbox.Add (rx_fft.win, 1, wx.EXPAND) if 0 and not(no_gui): @@ -199,10 +201,12 @@ class ptt_block(stdgui2.std_top_block): form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Squelch", weight=3, range=self.rxpath.squelch_range(), callback=self.set_squelch) + + g = self.rxpath.u.get_gain_range() 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(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_rx_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -269,19 +273,20 @@ class ptt_block(stdgui2.std_top_block): # //////////////////////////////////////////////////////////////////////// class transmit_path(gr.hier_block2): - def __init__(self, subdev_spec, audio_input): + def __init__(self, address, gain, audio_input): gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.u = usrp.sink_c () + self.u = uhd.usrp_sink(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.if_rate = 320e3 + self.audio_rate = 32e3 - 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.u.set_samp_rate(self.if_rate) + dev_rate = self.u.get_samp_rate() self.audio_gain = 10 self.normal_gain = 32000 @@ -289,16 +294,16 @@ class transmit_path(gr.hier_block2): 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 + 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 + 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)) @@ -311,18 +316,21 @@ class transmit_path(gr.hier_block2): self.fmtx = blks2.nbfm_tx(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() + rrate = dev_rate / self.if_rate + self.resamp = blks2.pfb_arb_resampler_ccf(rrate) self.connect(self.audio, self.audio_amp, self.audio_filt, - (self.add_pl,0), self.fmtx, self.amp, self.u) + (self.add_pl,0), self.fmtx, self.amp, + self.resamp, self.u) + + if gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + gain = float(g.start() + g.stop())/2.0 - self.set_gain(self.subdev.gain_range()[1]) # set max Tx gain + self.set_gain(gain) + self.set_enable(False) def set_freq(self, target_freq): """ @@ -330,26 +338,17 @@ class transmit_path(gr.hier_block2): @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) + r = self.u.set_center_freq(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) + self.u.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: @@ -362,64 +361,53 @@ class transmit_path(gr.hier_block2): # //////////////////////////////////////////////////////////////////////// class receive_path(gr.hier_block2): - def __init__(self, subdev_spec, gain, audio_output): + def __init__(self, address, gain, audio_output): gr.hier_block2.__init__(self, "receive_path", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - 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 + self.u = uhd.usrp_source(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) - 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.if_rate = 256e3 + self.quad_rate = 64e3 + self.audio_rate = 32e3 - self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec)) + self.u.set_samp_rate(self.if_rate) + dev_rate = self.u.get_samp_rate() # Create filter to get actual channel we want - chan_coeffs = gr.firdes.low_pass (1.0, # gain - self.if_rate, # sampling rate + nfilts = 32 + chan_coeffs = gr.firdes.low_pass (nfilts, # gain + nfilts*dev_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 + rrate = self.quad_rate / dev_rate + self.resamp = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) # instantiate the guts of the single channel receiver - self.fmrx = blks2.nbfm_rx(audio_rate, self.quad_rate) + self.fmrx = blks2.nbfm_rx(self.audio_rate, self.quad_rate) # standard squelch block - self.squelch = blks2.standard_squelch(audio_rate) + self.squelch = blks2.standard_squelch(self.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) + audio_sink = audio.sink (int(self.audio_rate), audio_output) # now wire it all together - self.connect (self.u, self.ddc, self.fmrx, self.squelch, self._audio_gain, audio_sink) + self.connect (self.u, self.resamp, self.fmrx, self.squelch, + self._audio_gain, 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 + g = self.u.get_gain_range() + gain = float(g.start() + g.stop())/2.0 self.enabled = True self.set_gain(gain) @@ -463,26 +451,15 @@ class receive_path(gr.hier_block2): @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) + r = self.u.set_center_freq(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) + self.u.set_gain(gain) # //////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py b/gr-uhd/examples/usrp_nbfm_rcv.py index 4c66fc970..2dc69423c 100755 --- a/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py +++ b/gr-uhd/examples/usrp_nbfm_rcv.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2007 Free Software Foundation, Inc. +# Copyright 2005,2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,20 +20,15 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 +from gnuradio import gr, audio, blks2, uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form from optparse import OptionParser -from usrpm import usrp_dbid import sys import math import wx - #//////////////////////////////////////////////////////////////////////// # Control Stuff #//////////////////////////////////////////////////////////////////////// @@ -43,8 +38,11 @@ class my_top_block (stdgui2.std_top_block): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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, @@ -70,7 +68,8 @@ class my_top_block (stdgui2.std_top_block): self.freq = 0 self.freq_step = 25e3 - self.rxpath = receive_path(options.rx_subdev_spec, options.gain, options.audio_output) + self.rxpath = receive_path(options.address, options.antenna, + options.gain, options.audio_output) self.connect(self.rxpath) self._build_gui(vbox, options.no_gui) @@ -99,34 +98,47 @@ class my_top_block (stdgui2.std_top_block): self.src_fft = None - if 1 and not(no_gui): - self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP", - fft_size=512, sample_rate=self.rxpath.if_rate, - ref_scale=32768.0, ref_level=0, y_per_div=10, y_divs=12) + if 0 and not(no_gui): + self.src_fft = fftsink2.fft_sink_c(self.panel, + title="Data from USRP", + fft_size=512, + sample_rate=self.rxpath.if_rate, + ref_scale=32768.0, + ref_level=0, + y_per_div=10, + y_divs=12) 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 = fftsink2.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) + rx_fft = fftsink2.fft_sink_c(self.panel, + title="Post s/w Resampling", + fft_size=512, + sample_rate=self.rxpath.quad_rate, + ref_level=80, + y_per_div=20) + self.connect (self.rxpath.resamp, rx_fft) vbox.Add (rx_fft.win, 4, wx.EXPAND) if 1 and not(no_gui): - post_deemph_fft = fftsink2.fft_sink_f(self.panel, title="Post Deemph", - fft_size=512, sample_rate=self.rxpath.audio_rate, - y_per_div=10, ref_level=-40) + post_deemph_fft = fftsink2.fft_sink_f(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 = fftsink2.fft_sink_f(self.panel, title="Post Filter", - fft_size=512, sample_rate=audio_rate, - y_per_div=10, ref_level=-40) + post_filt_fft = fftsink2.fft_sink_f(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() @@ -134,7 +146,8 @@ class my_top_block (stdgui2.std_top_block): 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)) + callback=myform.check_input_and_call(_form_set_freq, + self._set_status_msg)) #hbox.Add((5,0), 0) #myform['freq_slider'] = \ @@ -157,10 +170,11 @@ class my_top_block (stdgui2.std_top_block): form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Squelch", weight=3, range=self.rxpath.squelch_range(), callback=self.set_squelch) + g = self.rxpath.u.get_gain_range() 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(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -246,45 +260,31 @@ class my_top_block (stdgui2.std_top_block): USE_SIMPLE_SQUELCH = False class receive_path(gr.hier_block2): - def __init__(self, subdev_spec, gain, audio_output): + def __init__(self, address, antenna, gain, audio_output): gr.hier_block2.__init__(self, "receive_path", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.u = usrp.source_c () - adc_rate = self.u.adc_rate() + self.u = uhd.usrp_source(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) - 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 + self.if_rate = 256e3 + self.quad_rate = 64e3 + self.audio_rate = 32e3 - - 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)) + self.u.set_samp_rate(self.if_rate) + dev_rate = self.u.get_samp_rate() # Create filter to get actual channel we want - chan_coeffs = gr.firdes.low_pass (1.0, # gain - self.if_rate, # sampling rate - 8e3, # low pass cutoff freq - 2e3, # 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 + nfilts = 32 + chan_coeffs = gr.firdes.low_pass (nfilts, # gain + nfilts*dev_rate, # sampling rate + 8e3, # low pass cutoff freq + 2e3, # width of trans. band + gr.firdes.WIN_HANN) # filter type + rrate = self.quad_rate / dev_rate + self.resamp = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) if USE_SIMPLE_SQUELCH: self.squelch = gr.simple_squelch_cc(20) @@ -302,24 +302,28 @@ class receive_path(gr.hier_block2): # now wire it all together if USE_SIMPLE_SQUELCH: - self.connect (self.u, self.ddc, self.squelch, self.fmrx, + self.connect (self.u, self.resamp, self.squelch, self.fmrx, self._audio_gain, audio_sink) else: - self.connect (self.u, self.ddc, self.fmrx, self.squelch, + self.connect (self.u, self.resamp, self.fmrx, self.squelch, self._audio_gain, 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 + g = self.u.get_gain_range() + gain = float(g.start()+g.stop())/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) + if(antenna): + self.u.set_antenna(antenna, 0) + def volume_range(self): return (-20.0, 0.0, 0.5) @@ -351,27 +355,16 @@ class receive_path(gr.hier_block2): @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) + r = self.u.set_center_freq(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) + self.u.set_gain(gain) # //////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-examples/python/usrp/usrp_spectrum_sense.py b/gr-uhd/examples/usrp_spectrum_sense.py index 90adf1671..e89745b3b 100755 --- a/gnuradio-examples/python/usrp/usrp_spectrum_sense.py +++ b/gr-uhd/examples/usrp_spectrum_sense.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2007 Free Software Foundation, Inc. +# Copyright 2005,2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,16 +20,16 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir, window +from gnuradio import gr, eng_notation, window from gnuradio import audio -from gnuradio import usrp +from gnuradio import uhd from gnuradio.eng_option import eng_option from optparse import OptionParser -from usrpm import usrp_dbid import sys import math import struct +sys.stderr.write("Warning: this is known to have issues on some machines+Python version combinations to seg fault due to the callback in bin_statitics. If you figure out why, we'd love to hear about it!\n") class tune(gr.feval_dd): """ @@ -41,17 +41,20 @@ class tune(gr.feval_dd): def eval(self, ignore): """ - This method is called from gr.bin_statistics_f when it wants to change - the center frequency. This method tunes the front end to the new center - frequency, and returns the new frequency as its result. + This method is called from gr.bin_statistics_f when it wants + to change the center frequency. This method tunes the front + end to the new center frequency, and returns the new frequency + as its result. """ + try: - # We use this try block so that if something goes wrong from here - # down, at least we'll have a prayer of knowing what went wrong. - # Without this, you get a very mysterious: + # We use this try block so that if something goes wrong + # from here down, at least we'll have a prayer of knowing + # what went wrong. Without this, you get a very + # mysterious: # - # terminate called after throwing an instance of 'Swig::DirectorMethodException' - # Aborted + # terminate called after throwing an instance of + # 'Swig::DirectorMethodException' Aborted # # message on stderr. Not exactly helpful ;) @@ -68,7 +71,7 @@ class parse_msg(object): self.vlen = int(msg.arg2()) assert(msg.length() == self.vlen * gr.sizeof_float) - # FIXME consider using Numarray or NumPy vector + # FIXME consider using NumPy array t = msg.to_string() self.raw_data = t self.data = struct.unpack('%df' % (self.vlen,), t) @@ -81,24 +84,25 @@ class my_top_block(gr.top_block): usage = "usage: %prog [options] min_freq max_freq" 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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate [default=%default]") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") - parser.add_option("", "--tune-delay", type="eng_float", default=1e-3, metavar="SECS", + parser.add_option("", "--tune-delay", type="eng_float", + default=1e-3, metavar="SECS", help="time to delay (in seconds) after changing frequency [default=%default]") - parser.add_option("", "--dwell-delay", type="eng_float", default=10e-3, metavar="SECS", + parser.add_option("", "--dwell-delay", type="eng_float", + default=10e-3, metavar="SECS", help="time to dwell (in seconds) at a given frequncy [default=%default]") parser.add_option("-F", "--fft-size", type="int", default=256, help="specify number of FFT bins [default=%default]") - parser.add_option("-d", "--decim", type="intx", default=16, - help="set decimation to DECIM [default=%default]") parser.add_option("", "--real-time", action="store_true", default=False, help="Attempt to enable real-time scheduling") - 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]") (options, args) = parser.parse_args() if len(args) != 2: @@ -109,11 +113,11 @@ class my_top_block(gr.top_block): self.max_freq = eng_notation.str_to_num(args[1]) if self.min_freq > self.max_freq: - self.min_freq, self.max_freq = self.max_freq, self.min_freq # swap them + # swap them + self.min_freq, self.max_freq = self.max_freq, self.min_freq self.fft_size = options.fft_size - if not options.real_time: realtime = False else: @@ -125,36 +129,14 @@ class my_top_block(gr.top_block): 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 1: - 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 - # build graph - - self.u = usrp.source_c(fusb_block_size=options.fusb_block_size, - fusb_nblocks=options.fusb_nblocks) - - - adc_rate = self.u.adc_rate() # 64 MS/s - usrp_decim = options.decim - self.u.set_decim_rate(usrp_decim) - usrp_rate = adc_rate / usrp_decim - - 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(),) + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + usrp_rate = options.samp_rate + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() s2v = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) @@ -186,7 +168,8 @@ class my_top_block(gr.top_block): self.msgq = gr.msg_queue(16) self._tune_callback = tune(self) # hang on to this to keep it from being GC'd stats = gr.bin_statistics_f(self.fft_size, self.msgq, - self._tune_callback, tune_delay, dwell_delay) + self._tune_callback, tune_delay, + dwell_delay) # FIXME leave out the log10 until we speed it up #self.connect(self.u, s2v, fft, c2mag, log, stats) @@ -194,8 +177,8 @@ class my_top_block(gr.top_block): 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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 self.set_gain(options.gain) print "gain =", options.gain @@ -209,6 +192,7 @@ class my_top_block(gr.top_block): if not self.set_freq(target_freq): print "Failed to set frequency to", target_freq + sys.exit(1) return target_freq @@ -219,17 +203,15 @@ class my_top_block(gr.top_block): @param target_freq: frequency in Hz @rypte: bool - - Tuning is a two step process. First we ask the front-end to - tune as close to the desired frequency as it can. Then we use - the result of that operation and our target_frequency to - determine the value for the digital down converter. """ - return self.u.tune(0, self.subdev, target_freq) + r = self.u.set_center_freq(target_freq) + if r: + return True + return False def set_gain(self, gain): - self.subdev.set_gain(gain) + self.u.set_gain(gain) def main_loop(tb): @@ -254,7 +236,7 @@ def main_loop(tb): if __name__ == '__main__': tb = my_top_block() try: - tb.start() # start executing flow graph in another thread... + tb.start() main_loop(tb) except KeyboardInterrupt: diff --git a/gnuradio-examples/python/usrp/usrp_tv_rcv.py b/gr-uhd/examples/usrp_tv_rcv.py index 4e13a83ab..a68867365 100755 --- a/gnuradio-examples/python/usrp/usrp_tv_rcv.py +++ b/gr-uhd/examples/usrp_tv_rcv.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,51 +22,38 @@ """ 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. +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. + +When you use a file source, instead 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 + +from gnuradio import gr 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 uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - class tv_rx_block (stdgui2.std_top_block): def __init__(self,frame,panel,vbox,argv): @@ -74,11 +61,14 @@ class tv_rx_block (stdgui2.std_top_block): 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=OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate") 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, @@ -87,8 +77,6 @@ class tv_rx_block (stdgui2.std_top_block): 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, @@ -97,8 +85,10 @@ class tv_rx_block (stdgui2.std_top_block): 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") + parser.add_option("", "--freq-min", type="eng_float", default=50.25e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=900.25e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if not ((len(args) == 1) or (len(args) == 0)): @@ -118,68 +108,70 @@ class tv_rx_block (stdgui2.std_top_block): self.state = "FREQ" self.freq = 0 - # build graph + self.tv_freq_min = options.freq_min + self.tv_freq_max = options.freq_max + # build graph self.u=None - usrp_decim = options.decim # 32 - if not (options.out_filename=="sdl"): options.repeat=False + usrp_rate = options.samp_rate + if not ((filename is None) or (filename=="usrp")): - self.filesource = gr.file_source(gr.sizeof_short,filename,options.repeat) # file is data source + # file is data source + self.filesource = gr.file_source(gr.sizeof_short,filename,options.repeat) 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(),) + + else: # use a UHD device + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 + self.src=self.u - usrp_rate = adc_rate / usrp_decim # 320 kS/s + self.gain = options.gain 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) + #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) + 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" @@ -188,7 +180,8 @@ class tv_rx_block (stdgui2.std_top_block): 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 "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) @@ -204,11 +197,23 @@ class tv_rx_block (stdgui2.std_top_block): 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) + 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) + #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) + + #note, this block is not yet in cvs + self.tv_sync_adv=gr.tv_sync_adv(usrp_rate, 0, False, False, + 0.0, 255.0, 0.01, 1.0, 0.0, False) + 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() @@ -221,18 +226,30 @@ class tv_rx_block (stdgui2.std_top_block): 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 + + #Note: this block is not yet in cvs + tv_corr=gr.tv_correlator_ff(frame_size,nframes, search_window, + video_alpha, corr_alpha,debug) 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, + + self.connect (self.src, self.agc, self.am_demod, tv_corr, + self.invert_and_scale, self.set_blacklevel, + f2uc, self.dst) 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) + 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 + frange = self.u.get_freq_range() + if(frange.start() > self.tv_freq_max or frange.stop() < self.tv_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.tv_freq_min or options.freq > self.tv_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) # set initial values self.set_gain(options.gain) @@ -286,7 +303,7 @@ class tv_rx_block (stdgui2.std_top_block): 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), + range=(self.tv_freq_min, self.tv_freq_max, 0.25e6), callback=self.set_freq) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -307,9 +324,10 @@ class tv_rx_block (stdgui2.std_top_block): hbox.Add((5,0), 0) if not (self.u is None): + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -387,7 +405,7 @@ class tv_rx_block (stdgui2.std_top_block): determine the value for the digital down converter. """ if not (self.u is None): - r = usrp.tune(self.u, 0, self.subdev, target_freq) + r = self.u.set_center_freq(target_freq) if r: self.freq = target_freq self.myform['freq'].set_value(target_freq) # update displayed value @@ -400,17 +418,17 @@ class tv_rx_block (stdgui2.std_top_block): 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() - + if not (self.u is None): + self.gain=gain + self.myform['gain'].set_value(gain) # update displayed value + self.u.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) + 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__': diff --git a/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py b/gr-uhd/examples/usrp_tv_rcv_nogui.py index e6a8de1be..a44e20d39 100755 --- a/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py +++ b/gr-uhd/examples/usrp_tv_rcv_nogui.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,17 +22,21 @@ """ 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. +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 import uhd from gnuradio.eng_option import eng_option from optparse import OptionParser import sys @@ -49,24 +53,31 @@ class my_top_block(gr.top_block): def __init__(self): gr.top_block.__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" + usage=("%prog: [options] output_filename.\nSpecial 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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate") 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="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=519.25e6, 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)") @@ -76,12 +87,12 @@ class my_top_block(gr.top_block): 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") + parser.add_option("", "--freq-min", type="eng_float", default=50.25e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=900.25e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args () if not (len(args) == 1): parser.print_help() @@ -90,6 +101,9 @@ class my_top_block(gr.top_block): filename = args[0] + self.tv_freq_min = options.freq_min + self.tv_freq_max = options.freq_max + if options.in_filename is None: parser.print_help() sys.stderr.write('You must specify the input -i FILENAME or -i usrp\n'); @@ -98,61 +112,51 @@ class my_top_block(gr.top_block): if not (filename=="sdl"): options.repeat=False + input_rate = options.samp_rate + print "video sample rate %s" % (eng_notation.num_to_str(input_rate)) + 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 + # file is data source, capture with usr_rx_csfile.py + self.filesource = gr.file_source(gr.sizeof_short, + options.in_filename, + options.repeat) 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.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.u.set_samp_rate(input_rate) + dev_rate = self.u.get_samp_rate() + 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) + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 + self.u.set_gain(options.gain) - r = self.u.tune(0, self.subdev, options.freq) + r = self.u.set_center_freq(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.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.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() + self.f2uc = gr.float_to_uchar() - # sdl window as final sink + # sdl window as final sink if not (options.pal or options.ntsc): options.pal=True #set default to PAL if options.pal: @@ -167,9 +171,12 @@ class my_top_block(gr.top_block): 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) + #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) + 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" @@ -189,9 +196,9 @@ class my_top_block(gr.top_block): 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) + self.connect (self.agc, self.am_demod, self.invert_and_scale, + self.set_blacklevel, self.f2uc, self.dst) - if __name__ == '__main__': try: my_top_block().run() diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv.py b/gr-uhd/examples/usrp_wfm_rcv.py index fba2a1210..7b35fbbe4 100755 --- a/gnuradio-examples/python/usrp/usrp_wfm_rcv.py +++ b/gr-uhd/examples/usrp_wfm_rcv.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc. +# Copyright 2005-2007,2009,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,42 +20,25 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 +from gnuradio import gr, optfir, audio, blks2, uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - class wfm_rx_block (stdgui2.std_top_block): def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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, @@ -64,6 +47,10 @@ class wfm_rx_block (stdgui2.std_top_block): 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("", "--freq-min", type="eng_float", default=87.9e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: @@ -77,72 +64,64 @@ class wfm_rx_block (stdgui2.std_top_block): self.state = "FREQ" self.freq = 0 + self.fm_freq_min = options.freq_min + self.fm_freq_max = options.freq_max + # 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(),) - dbid = self.subdev.dbid() - if not (dbid == usrp_dbid.BASIC_RX or - dbid == usrp_dbid.TV_RX or - dbid == usrp_dbid.TV_RX_REV_2 or - dbid == usrp_dbid.TV_RX_REV_3 or - dbid == usrp_dbid.TV_RX_MIMO or - dbid == usrp_dbid.TV_RX_REV_2_MIMO or - dbid == usrp_dbid.TV_RX_REV_3_MIMO -): - print "This daughterboard does not cover the required frequency range" - print "for this application. Please use a BasicRX or TVRX daughterboard." - raw_input("Press ENTER to continue anyway, or Ctrl-C to exit.") - - 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 = blks2.wfm_rcv (demod_rate, audio_decimation) + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 32e3 + audio_decim = int(demod_rate / audio_rate) + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() + + nfilts = 32 + chan_coeffs = optfir.low_pass (nfilts, # gain + nfilts*usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + rrate = usrp_rate / dev_rate + self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) + + self.guts = blks2.wfm_rcv (demod_rate, audio_decim) 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 + self.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.connect (self.u, self.chan_filt, self.guts, + self.volume_control, self.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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2 if options.volume is None: g = self.volume_range() options.volume = float(g[0]+g[1])/2 + + frange = self.u.get_freq_range() + if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) - if abs(options.freq) < 1e6: - options.freq *= 1e6 # set initial values @@ -196,7 +175,7 @@ class wfm_rx_block (stdgui2.std_top_block): 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), + range=(self.fm_freq_min, self.fm_freq_max, 0.1e6), callback=self.set_freq) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -210,9 +189,10 @@ class wfm_rx_block (stdgui2.std_top_block): callback=self.set_vol) hbox.Add((5,0), 1) + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -268,14 +248,9 @@ class wfm_rx_block (stdgui2.std_top_block): @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) - + + r = self.u.set_center_freq(target_freq) if r: self.freq = target_freq self.myform['freq'].set_value(target_freq) # update displayed value @@ -289,7 +264,7 @@ class wfm_rx_block (stdgui2.std_top_block): def set_gain(self, gain): self.myform['gain'].set_value(gain) # update displayed value - self.subdev.set_gain(gain) + self.u.set_gain(gain) def update_status_bar (self): msg = "Volume:%r Setting:%s" % (self.vol, self.state) diff --git a/gr-uhd/examples/usrp_wfm_rcv2_nogui.py b/gr-uhd/examples/usrp_wfm_rcv2_nogui.py new file mode 100755 index 000000000..013a6864f --- /dev/null +++ b/gr-uhd/examples/usrp_wfm_rcv2_nogui.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# +# Copyright 2005-2007,2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, optfir, audio, blks2, uhd +from gnuradio.eng_option import eng_option +from optparse import OptionParser +from usrpm import usrp_dbid +import sys +import math + +class wfm_rx_block (gr.top_block): + + def __init__(self): + gr.top_block.__init__(self) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + 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") + parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, + help="Set a maximum frequency [default=%default]") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + 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" + + self.fm_freq_min = options.freq_min + self.fm_freq_max = options.freq_max + + # build graph + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=2) + + # Set front end channel mapping + self.u.set_subdev_spec("A:0 A:0") + + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 32e3 + audio_decim = int(demod_rate / audio_rate) + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() + + # Make sure dboard can suppor the required frequencies + frange = self.u.get_freq_range() + if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + + # sound card as final sink + self.audio_sink = audio.sink(int(audio_rate), options.audio_output) + + # taps for channel filter + nfilts = 32 + chan_coeffs = optfir.low_pass (nfilts, # gain + nfilts*usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + rrate = usrp_rate / dev_rate + + # set front end PLL to middle frequency + mid_freq = (f[0] + f[1]) / 2.0 + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 + + for n in range(2): + chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) + guts = blks2.wfm_rcv (demod_rate, audio_decim) + volume_control = gr.multiply_const_ff(self.vol) + + #self.connect((self.di, n), chan_filt) + self.connect((self.u, n), chan_filt) + self.connect(chan_filt, guts, volume_control) + self.connect(volume_control, (self.audio_sink, n)) + + # Test the the requested frequencies are in range + if(f[n] < self.fm_freq_min or f[n] > self.fm_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) + + # Tune each channel by setting the RF freq to mid_freq and the + # DDC freq to f[n]. + tr = uhd.tune_request(f[n], rf_freq=mid_freq, + rf_freq_policy=uhd.tune_request.POLICY_MANUAL) + self.u.set_center_freq(tr, n) + + # Set gain for each channel + self.set_gain(options.gain, n) + + def set_vol (self, vol): + self.vol = vol + self.volume_control.set_k(self.vol) + + + def set_gain(self, gain, n): + self.u.set_gain(gain, n) + +if __name__ == '__main__': + tb = wfm_rx_block() + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_fmdet.py b/gr-uhd/examples/usrp_wfm_rcv_fmdet.py index 30744ee01..53ad6edbf 100755 --- a/gnuradio-examples/python/usrp/usrp_wfm_rcv_fmdet.py +++ b/gr-uhd/examples/usrp_wfm_rcv_fmdet.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,41 +20,28 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 +from gnuradio import gr, optfir, audio, blks2, uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form, scopesink2 from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) +import os +print os.getpid() +raw_input() class wfm_rx_block (stdgui2.std_top_block): def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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, @@ -65,6 +52,10 @@ class wfm_rx_block (stdgui2.std_top_block): 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("", "--freq-min", type="eng_float", default=87.9e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() @@ -79,55 +70,52 @@ class wfm_rx_block (stdgui2.std_top_block): 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 = 3*demod_rate / audio_decimation/2 # 48 kHz - - if options.rx_subdev_spec is None: - options.rx_subdev_spec = pick_subdevice(self.u) + self.fm_freq_min = options.freq_min + self.fm_freq_max = options.freq_max - 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) + # build graph + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 48e3 + audio_decim = 10 - chan_filt_coeffs = gr.firdes.low_pass_2 (1, # gain - usrp_rate, # sampling rate - 90e3, # passband cutoff - 30e3, # transition bandwidth - 70, # stopband attenuation - gr.firdes.WIN_BLACKMAN) - print len(chan_filt_coeffs) - chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() - self.rchan_sample = blks2.rational_resampler_fff(3,2) - self.lchan_sample = blks2.rational_resampler_fff(3,2) + nfilts = 32 + chan_coeffs = gr.firdes.low_pass_2(10*nfilts, # gain + nfilts*usrp_rate, # sampling rate + 90e3, # passband cutoff + 30e3, # transition bw + 70) # stopband attenuation + rrate = usrp_rate / dev_rate + self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) + self.guts = blks2.wfm_rcv_fmdet (demod_rate, audio_decim) - #self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) - self.guts = blks2.wfm_rcv_fmdet (demod_rate, audio_decimation) + chan_rate = audio_rate / (demod_rate/audio_decim) + self.rchan_filt = blks2.pfb_arb_resampler_fff(chan_rate) + self.lchan_filt = blks2.pfb_arb_resampler_fff(chan_rate) # 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 + self.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.lchan_sample,self.volume_control_l,(audio_sink,0)) - self.connect((self.guts, 1), self.rchan_sample,self.volume_control_r,(audio_sink,1)) + self.connect (self.u, self.chan_filt, self.guts) + self.connect((self.guts, 0), self.lchan_filt, + self.volume_control_l, (self.audio_sink,0)) + self.connect((self.guts, 1), self.rchan_filt, + self.volume_control_r, (self.audio_sink,1)) try: self.guts.stereo_carrier_pll_recovery.squelch_enable(True) @@ -139,8 +127,8 @@ class wfm_rx_block (stdgui2.std_top_block): 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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 if options.volume is None: g = self.volume_range() @@ -149,8 +137,15 @@ class wfm_rx_block (stdgui2.std_top_block): if abs(options.freq) < 1e6: options.freq *= 1e6 - # set initial values + frange = self.u.get_freq_range() + if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) + # set initial values self.set_gain(options.gain) self.set_vol(options.volume) try: @@ -232,7 +227,7 @@ class wfm_rx_block (stdgui2.std_top_block): 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), + range=(self.fm_freq_min, self.fm_freq_max, 0.1e6), callback=self.set_freq) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -246,9 +241,10 @@ class wfm_rx_block (stdgui2.std_top_block): callback=self.set_vol) hbox.Add((5,0), 1) + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) @@ -311,20 +307,17 @@ class wfm_rx_block (stdgui2.std_top_block): except: print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" + 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) + r = self.u.set_center_freq(target_freq) + if r: self.freq = target_freq self.myform['freq'].set_value(target_freq) # update displayed value @@ -335,10 +328,10 @@ class wfm_rx_block (stdgui2.std_top_block): 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) + self.u.set_gain(gain) def update_status_bar (self): msg = "Volume:%r Setting:%s" % (self.vol, self.state) diff --git a/gr-uhd/examples/usrp_wfm_rcv_nogui.py b/gr-uhd/examples/usrp_wfm_rcv_nogui.py new file mode 100755 index 000000000..ffeda4493 --- /dev/null +++ b/gr-uhd/examples/usrp_wfm_rcv_nogui.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# +# Copyright 2005-2007,2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, optfir, audio, blks2, uhd +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +class wfm_rx_block (gr.top_block): + + def __init__(self): + gr.top_block.__init__(self) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + 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("-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("", "--freq-min", type="eng_float", default=87.9e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, + help="Set a maximum frequency [default=%default]") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.state = "FREQ" + self.freq = 0 + + self.fm_freq_min = options.freq_min + self.fm_freq_max = options.freq_max + + # build graph + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 32e3 + audio_decim = int(demod_rate / audio_rate) + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() + + nfilts = 32 + chan_coeffs = optfir.low_pass (nfilts, # gain + nfilts*usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + rrate = usrp_rate / dev_rate + self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) + + self.guts = blks2.wfm_rcv (demod_rate, audio_decim) + + self.volume_control = gr.multiply_const_ff(1) + + # sound card as final sink + self.audio_sink = audio.sink(int(audio_rate), + options.audio_output, + False) # ok_to_block + + # now wire it all together + self.connect (self.u, self.chan_filt, self.guts, + self.volume_control, self.audio_sink) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 + + if options.volume is None: + g = self.volume_range() + options.volume = float(g[0]+g[1])/2 + + frange = self.u.get_freq_range() + if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) + + # 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_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.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 + """ + + r = self.u.set_center_freq(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.u.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 + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + +if __name__ == '__main__': + tb = wfm_rx_block() + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py b/gr-uhd/examples/usrp_wfm_rcv_pll.py index 0d52ed7ee..2cb4e4068 100755 --- a/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py +++ b/gr-uhd/examples/usrp_wfm_rcv_pll.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,41 +20,25 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 +from gnuradio import gr, optfir, audio, blks2, uhd +from gnuradio import eng_notation from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form, scopesink2 from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - class wfm_rx_block (stdgui2.std_top_block): def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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, @@ -65,7 +49,10 @@ class wfm_rx_block (stdgui2.std_top_block): 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("", "--freq-min", type="eng_float", default=87.9e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: @@ -79,55 +66,53 @@ class wfm_rx_block (stdgui2.std_top_block): self.state = "FREQ" self.freq = 0 + self.fm_freq_min = options.freq_min + self.fm_freq_max = options.freq_max + # build graph + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 48e3 + audio_decim = 10 + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() + + nfilts = 32 + chan_coeffs = gr.firdes.low_pass_2 (nfilts, # gain + nfilts*usrp_rate, # sampling rate + 90e3, # passband cutoff + 30e3, # stopband cutoff + 70) # stopband attenuation + rrate = usrp_rate / dev_rate + self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) - 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 = 3*demod_rate / audio_decimation/2 # 48 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 = gr.firdes.low_pass_2 (1, # gain - usrp_rate, # sampling rate - 90e3, # passband cutoff - 30e3, # transition bandwidth - 70, # stopband attenuation - gr.firdes.WIN_BLACKMAN) - print len(chan_filt_coeffs) - chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) - self.rchan_sample = blks2.rational_resampler_fff(3,2) - self.lchan_sample = blks2.rational_resampler_fff(3,2) + self.guts = blks2.wfm_rcv_pll (demod_rate, audio_decim) - - #self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) - self.guts = blks2.wfm_rcv_pll (demod_rate, audio_decimation) + chan_rate = audio_rate / (demod_rate/audio_decim) + self.rchan_filt = blks2.pfb_arb_resampler_fff(chan_rate) + self.lchan_filt = blks2.pfb_arb_resampler_fff(chan_rate) # 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 + self.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.lchan_sample,self.volume_control_l,(audio_sink,0)) - self.connect((self.guts, 1), self.rchan_sample,self.volume_control_r,(audio_sink,1)) + self.connect (self.u, self.chan_filt, self.guts) + self.connect((self.guts, 0), self.lchan_filt, + self.volume_control_l, (self.audio_sink,0)) + self.connect((self.guts, 1), self.rchan_filt, + self.volume_control_r, (self.audio_sink,1)) try: self.guts.stereo_carrier_pll_recovery.squelch_enable(True) @@ -139,18 +124,22 @@ class wfm_rx_block (stdgui2.std_top_block): 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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 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 + frange = self.u.get_freq_range() + if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) # set initial values - self.set_gain(options.gain) self.set_vol(options.volume) try: @@ -232,7 +221,7 @@ class wfm_rx_block (stdgui2.std_top_block): 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), + range=(self.fm_freq_min, self.fm_freq_max, 0.1e6), callback=self.set_freq) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -246,9 +235,10 @@ class wfm_rx_block (stdgui2.std_top_block): callback=self.set_vol) hbox.Add((5,0), 1) + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) @@ -317,14 +307,10 @@ class wfm_rx_block (stdgui2.std_top_block): @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) + r = self.u.set_center_freq(target_freq) + if r: self.freq = target_freq self.myform['freq'].set_value(target_freq) # update displayed value @@ -335,10 +321,10 @@ class wfm_rx_block (stdgui2.std_top_block): 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) + self.u.set_gain(gain) def update_status_bar (self): msg = "Volume:%r Setting:%s" % (self.vol, self.state) diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_sca.py b/gr-uhd/examples/usrp_wfm_rcv_sca.py index 39547b3ae..1c6154871 100755 --- a/gnuradio-examples/python/usrp/usrp_wfm_rcv_sca.py +++ b/gr-uhd/examples/usrp_wfm_rcv_sca.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007 Free Software Foundation, Inc. +# Copyright 2006,2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -50,42 +50,25 @@ OFDM. """ -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio.blks2impl.fm_emph import fm_deemph +from gnuradio import gr, optfir, audio, blks2, uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - - class wfm_rx_sca_block (stdgui2.std_top_block): def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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, @@ -94,6 +77,10 @@ class wfm_rx_sca_block (stdgui2.std_top_block): 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("", "--freq-min", type="eng_float", default=87.9e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: @@ -107,58 +94,57 @@ class wfm_rx_sca_block (stdgui2.std_top_block): self.state = "FREQ" self.freq = 0 + self.fm_freq_min = options.freq_min + self.fm_freq_max = options.freq_max + # 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 - sca_chanfilt_decim = 5 - sca_demod_rate = demod_rate / sca_chanfilt_decim #64 kHz - audio_decimation = 2 - audio_rate = sca_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(),) - - #Create filter to get main FM Channel we want - chan_filt_coeffs = optfir.low_pass (1, # gain - usrp_rate, # sampling rate - 100e3, # passband cutoff - 140e3, # 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.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 32e3 + sca_demod_rate = 64e3 + audio_decim = int(demod_rate / audio_rate) + sca_chanfilt_decim = int(demod_rate / sca_demod_rate) + + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() + + nfilts = 32 + chan_coeffs = optfir.low_pass (nfilts, # gain + nfilts*usrp_rate, # sampling rate + 100e3, # passband cutoff + 140e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + rrate = usrp_rate / dev_rate + self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) #Create demodulator block for Main FM Channel max_dev = 75e3 fm_demod_gain = demod_rate/(2*math.pi*max_dev) self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) - # Note - deemphasis is not applied to the Main FM Channel as main audio is not decoded + # Note - deemphasis is not applied to the Main FM Channel as + # main audio is not decoded - # SCA Devation is 10% of carrier but some references say 20% if mono with one SCA (6 KHz seems typical) + # SCA Devation is 10% of carrier but some references say 20% + # if mono with one SCA (6 KHz seems typical) max_sca_dev = 6e3 # Create filter to get SCA channel we want sca_chan_coeffs = gr.firdes.low_pass (1.0, # gain - demod_rate, # sampling rate - max_sca_dev, # low pass cutoff freq - max_sca_dev/3, # width of trans. band - gr.firdes.WIN_HANN) # filter type + demod_rate, # sampling rate + max_sca_dev, # cutoff freq + max_sca_dev/3, # trans. band + gr.firdes.WIN_HANN) # filter type - self.ddc = gr.freq_xlating_fir_filter_fcf(sca_chanfilt_decim, # decimation rate + self.ddc = gr.freq_xlating_fir_filter_fcf(sca_chanfilt_decim, # decim rate sca_chan_coeffs, # taps - 0, # frequency translation amount (Gets set by the UI) + 0, # freq translation amount (Gets set by the UI) demod_rate) # input sample rate #Create demodulator block for SCA Channel @@ -168,46 +154,55 @@ class wfm_rx_sca_block (stdgui2.std_top_block): # SCA analog audio is bandwidth limited to 5 KHz max_sca_audio_freq = 5.0e3 + # SCA analog deephasis is 150 uS (75 uS may be used) sca_tau = 150e-6 # compute FIR filter taps for SCA audio filter - audio_coeffs = gr.firdes.low_pass (1.0, # gain - sca_demod_rate, # sampling rate - max_sca_audio_freq, # low pass cutoff freq - max_sca_audio_freq/2.5, # width of trans. band + audio_coeffs = gr.firdes.low_pass (1.0, # gain + sca_demod_rate, # sampling rate + max_sca_audio_freq, # cutoff freq + max_sca_audio_freq/2.5, # trans. band gr.firdes.WIN_HAMMING) # input: float; output: float - self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + self.audio_filter = gr.fir_filter_fff (audio_decim, audio_coeffs) # Create deemphasis block that is applied after SCA demodulation - self.deemph = fm_deemph (audio_rate, sca_tau) + self.deemph = blks2.fm_deemph (audio_rate, sca_tau) 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 + self.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.fm_demod, self.ddc, self.fm_demod_sca) - self.connect (self.fm_demod_sca, self.audio_filter, self.deemph, self.volume_control, audio_sink) + self.connect (self.u, self.chan_filt, self.fm_demod, + self.ddc, self.fm_demod_sca) + self.connect (self.fm_demod_sca, self.audio_filter, + self.deemph, self.volume_control, + self.audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, sca_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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/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 + frange = self.u.get_freq_range() + if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) # set initial values @@ -271,7 +266,7 @@ class wfm_rx_sca_block (stdgui2.std_top_block): 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), + range=(self.fm_freq_min, self.fm_freq_max, 0.1e6), callback=self.set_freq) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -299,9 +294,10 @@ class wfm_rx_sca_block (stdgui2.std_top_block): callback=self.set_vol) hbox.Add((5,0), 1) + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.stop(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -363,8 +359,7 @@ class wfm_rx_sca_block (stdgui2.std_top_block): 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) - + r = self.u.set_center_freq(target_freq) if r: self.freq = target_freq self.myform['freq'].set_value(target_freq) # update displayed value @@ -372,7 +367,6 @@ class wfm_rx_sca_block (stdgui2.std_top_block): self.update_status_bar() self._set_status_msg("OK", 0) return True - self._set_status_msg("Failed", 0) return False @@ -387,7 +381,7 @@ class wfm_rx_sca_block (stdgui2.std_top_block): def set_gain(self, gain): self.myform['gain'].set_value(gain) # update displayed value - self.subdev.set_gain(gain) + self.u.set_gain(gain) def update_status_bar (self): msg = "Volume:%r Setting:%s" % (self.vol, self.state) diff --git a/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py b/gr-uhd/examples/usrp_wxapt_rcv.py index b356702a6..5b44398d1 100755 --- a/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py +++ b/gr-uhd/examples/usrp_wxapt_rcv.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2005-2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,42 +20,25 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, eng_notation, optfir -from gnuradio import audio -from gnuradio import usrp -from gnuradio import blks2 +from gnuradio import gr, audio, blks2, uhd from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui2, fftsink2, form from optparse import OptionParser -from usrpm 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.TV_RX_REV_3, - usrp_dbid.TV_RX_MIMO, - usrp_dbid.TV_RX_REV_2_MIMO, - usrp_dbid.TV_RX_REV_3_MIMO, - usrp_dbid.BASIC_RX)) - class wxapt_rx_block (stdgui2.std_top_block): def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__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("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") 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, @@ -64,6 +47,10 @@ class wxapt_rx_block (stdgui2.std_top_block): 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("", "--freq-min", type="eng_float", default=137e6, + help="Set a minimum frequency [default=%default]") + parser.add_option("", "--freq-max", type="eng_float", default=138e6, + help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: @@ -77,62 +64,62 @@ class wxapt_rx_block (stdgui2.std_top_block): 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 + self.freq_min = options.freq_min + self.freq_max = options.freq_max - if options.rx_subdev_spec is None: - options.rx_subdev_spec = pick_subdevice(self.u) + # build graph + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) - 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(),) + usrp_rate = 320e3 + demod_rate = 320e3 + audio_rate = 32e3 + audio_decim = int(demod_rate / audio_rate) + self.u.set_samp_rate(usrp_rate) + dev_rate = self.u.get_samp_rate() - 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) + nfilts = 32 + chan_coeffs = gr.firdes.low_pass_2 (nfilts, # gain + nfilts*usrp_rate, # sampling rate + 40e3, # passband cutoff + 20e3, # transition bw + 60) # stopband attenuation + rrate = usrp_rate / dev_rate + self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) - self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) + self.guts = blks2.wfm_rcv (demod_rate, audio_decim) self.volume_control = gr.multiply_const_ff(self.vol) # sound card as final sink - audio_sink = audio.sink (int (audio_rate), options.audio_output) + self.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.connect (self.u, self.chan_filt, self.guts, + self.volume_control, self.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 + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2.0 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 + frange = self.u.get_freq_range() + if(frange.start() > self.freq_max or frange.stop() < self.freq_min): + sys.stderr.write("Radio does not support required frequency range.\n") + sys.exit(1) + if(options.freq < self.freq_min or options.freq > self.freq_max): + sys.stderr.write("Requested frequency is outside of required frequency range.\n") + sys.exit(1) + # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): @@ -183,7 +170,7 @@ class wxapt_rx_block (stdgui2.std_top_block): 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), + range=(self.freq_min, self.freq_max, 0.0005e6), callback=self.set_freq) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -197,9 +184,10 @@ class wxapt_rx_block (stdgui2.std_top_block): callback=self.set_vol) hbox.Add((5,0), 1) + g = self.u.get_gain_range() myform['gain'] = \ form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", - weight=3, range=self.subdev.gain_range(), + weight=3, range=(g.start(), g.start(), g.step()), callback=self.set_gain) hbox.Add((5,0), 0) vbox.Add(hbox, 0, wx.EXPAND) @@ -255,14 +243,10 @@ class wxapt_rx_block (stdgui2.std_top_block): @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) - + + r = self.u.set_center_freq(target_freq) + if r: self.freq = target_freq self.myform['freq'].set_value(target_freq) # update displayed value @@ -276,7 +260,7 @@ class wxapt_rx_block (stdgui2.std_top_block): def set_gain(self, gain): self.myform['gain'].set_value(gain) # update displayed value - self.subdev.set_gain(gain) + self.u.set_gain(gain) def update_status_bar (self): msg = "Volume:%r Setting:%s" % (self.vol, self.state) diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i index b58fe9e18..f8381ae64 100644 --- a/gr-uhd/swig/uhd_swig.i +++ b/gr-uhd/swig/uhd_swig.i @@ -26,23 +26,8 @@ #define GR_UHD_API -//////////////////////////////////////////////////////////////////////// -// Language independent exception handler -//////////////////////////////////////////////////////////////////////// -%include exception.i - -%exception { - try { - $action - } - catch(std::exception &e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } - catch(...) { - SWIG_exception(SWIG_RuntimeError, "Unknown exception"); - } - -} +//suppress 319. No access specifier given for base class name (ignored). +#pragma SWIG nowarn=319 //////////////////////////////////////////////////////////////////////// // standard includes @@ -90,8 +75,6 @@ %include <uhd/types/metadata.hpp> -%ignore uhd::device::register_device; //causes compile to choke in MSVC -%include <uhd/device.hpp> %template(device_addr_vector_t) std::vector<uhd::device_addr_t>; %include <uhd/types/sensors.hpp> diff --git a/gruel/src/swig/pmt_swig.i b/gruel/src/swig/pmt_swig.i index 3b0eb45c8..34c7d4b7c 100644 --- a/gruel/src/swig/pmt_swig.i +++ b/gruel/src/swig/pmt_swig.i @@ -36,6 +36,24 @@ using namespace pmt; %} +//////////////////////////////////////////////////////////////////////// +// Language independent exception handler +//////////////////////////////////////////////////////////////////////// +%include exception.i + +%exception { + try { + $action + } + catch(std::exception &e) { + SWIG_exception(SWIG_RuntimeError, e.what()); + } + catch(...) { + SWIG_exception(SWIG_RuntimeError, "Unknown exception"); + } + +} + // Template intrusive_ptr for Swig to avoid dereferencing issues class pmt_base; //%import <intrusive_ptr.i> |