diff options
121 files changed, 4128 insertions, 4950 deletions
diff --git a/config/grc_gr_digital.m4 b/config/grc_gr_digital.m4 index a0765a3419..83c3f03a47 100644 --- a/config/grc_gr_digital.m4 +++ b/config/grc_gr_digital.m4 @@ -34,6 +34,7 @@ AC_DEFUN([GRC_GR_DIGITAL],[ gr-digital/python/utils/Makefile \ gr-digital/swig/Makefile \ gr-digital/swig/run_guile_tests \ + gr-digital/examples/Makefile \ ]) GRC_BUILD_CONDITIONAL(gr-digital,[ diff --git a/gnuradio-core/src/guile/tests/filter_ctors.test b/gnuradio-core/src/guile/tests/filter_ctors.test index 4dd0bc1870..fe1d9421d1 100644 --- a/gnuradio-core/src/guile/tests/filter_ctors.test +++ b/gnuradio-core/src/guile/tests/filter_ctors.test @@ -36,9 +36,6 @@ ;; gr_adaptive_fir_ccf(char *name, int decimation, const std::vector<float> &taps); ;; (pass-if (true? (gr:adaptive-fir-ccf "foo" 0 #(1.0 2.0 3.0 4.0)))) -;;; ./filter/gr_cma_equalizer_cc.h -(pass-if (true? (gr:cma-equalizer-cc 0 0 0))) - ;;; ./filter/gr_fft_filter_ccc.h (pass-if (true? (gr:fft-filter-ccc 0 #(1+3i 23+5i)))) diff --git a/gnuradio-core/src/guile/tests/general_ctors.test b/gnuradio-core/src/guile/tests/general_ctors.test index 244249dd80..813574bcad 100644 --- a/gnuradio-core/src/guile/tests/general_ctors.test +++ b/gnuradio-core/src/guile/tests/general_ctors.test @@ -71,9 +71,6 @@ ;;; ./general/gr_bin_statistics_f.h WONTFIX: requires gr_feval_dd & swig directors ;;;(pass-if (true? (gr:bin-statistics-f 1 (gr:msg-queue) 0 0 0))) -;;; ./general/gr_binary_slicer_fb.h -(pass-if (true? (gr:binary-slicer-fb))) - ;;; ./general/gr_bytes_to_syms.h (pass-if (true? (gr:bytes-to-syms))) @@ -86,14 +83,6 @@ ;;; ./general/gr_check_lfsr_32k_s.h (pass-if (true? (gr:check-lfsr-32k-s))) -;;; ./general/gr_clock_recovery_mm_cc.h -(pass-if (true? (gr:clock-recovery-mm-cc 1 1 1 1 1))) -(pass-if-throw "confirm throw gr:clock-recovery-mm-cc" #t (true? (gr:clock-recovery-mm-cc -1 1 1 1 1))) - -;;; ./general/gr_clock_recovery_mm_ff.h -(pass-if (true? (gr:clock-recovery-mm-ff 1 1 1 1 1))) -(pass-if-throw "confirm throw gr:clock-recovery-mm-ff" #t (true? (gr:clock-recovery-mm-ff -1 1 1 1 1))) - ;;; ./general/gr_complex_to_interleaved_short.h (pass-if (true? (gr:complex-to-interleaved-short))) @@ -108,22 +97,9 @@ ;;; ./general/gr_conjugate_cc.h (pass-if (true? (gr:conjugate-cc))) -;;; ./general/gr_constellation_decoder_cb.h -(pass-if (true? (gr:constellation-decoder-cb #(2+3i 23+5i) #(0 1)))) - ;;; ./general/gr_copy.h (pass-if (true? (gr:copy 1))) -;;; ./general/gr_correlate_access_code_bb.h -(pass-if (true? (gr:correlate-access-code-bb "foo" 0))) -(pass-if-throw "confirm throw correlate-access-code-bb" #t - (true? (gr:correlate-access-code-bb - "00000000000000000000000000000000000000000000000000000000000000000" 0))) - -;;; ./general/gr_costas_loop_cc.h -(pass-if (true? (gr:costas-loop-cc 0 0 0 0 2))) -(pass-if-throw "confirm throw gr:costas-loop-cc" #t (true? (gr:costas-loop-cc 0 0 0 0 3))) - ;;; ./general/gr_cpfsk_bc.h (pass-if (true? (gr:cpfsk-bc 1 1 1))) @@ -171,9 +147,6 @@ (pass-if (true? (gr:fft-vfc 4 #t #(1.0 2.0 3.0 4.0)))) (pass-if-throw "confirm throw gr:fft-vfc" #t (true? (gr:fft-vfc 4 #f #(1.0 2.0 3.0 4.0)))) -;;; ./general/gr_fll_band_edge_cc.h -(pass-if (true? (gr:fll-band-edge-cc 0 0 0 0 0))) - ;; ;;; ./general/gr_float_to_char.h (pass-if (true? (gr:float-to-char))) @@ -221,18 +194,9 @@ ;;; ./general/gr_lfsr_32k_source_s.h (pass-if (true? (gr:lfsr-32k-source-s))) -;;; ./general/gr_lms_dfe_cc.h -(pass-if (true? (gr:lms-dfe-ff 1 1 1 1))) - -;;; ./general/gr_lms_dfe_ff.h -(pass-if (true? (gr:lms-dfe-ff 1 1 1 1))) - ;;; ./general/gr_map_bb.h (pass-if (true? (gr:map-bb #(1 2)))) -;;; ./general/gr_mpsk_receiver_cc.h -(pass-if (true? (gr:mpsk-receiver-cc 1 1 1 1 1 1 1 1 1 1 1))) - ;;; ./general/gr_nlog10_ff.h (pass-if (true? (gr:nlog10-ff 1 1 1))) diff --git a/gnuradio-core/src/lib/filter/CMakeLists.txt b/gnuradio-core/src/lib/filter/CMakeLists.txt index d039a2a69a..2c060de802 100644 --- a/gnuradio-core/src/lib/filter/CMakeLists.txt +++ b/gnuradio-core/src/lib/filter/CMakeLists.txt @@ -313,7 +313,6 @@ ENDIF(ENABLE_PYTHON) SET(gr_core_filter_triple_threats gr_adaptive_fir_ccc gr_adaptive_fir_ccf - gr_cma_equalizer_cc gr_dc_blocker_cc gr_dc_blocker_ff gr_fft_filter_ccc diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index d8f634c382..48ec55a622 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2002,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc. +# Copyright 2001,2002,2004-2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -190,7 +190,6 @@ libfilter_la_common_SOURCES = \ $(GENERATED_CC) \ gr_adaptive_fir_ccc.cc \ gr_adaptive_fir_ccf.cc \ - gr_cma_equalizer_cc.cc \ gri_fft_filter_fff_generic.cc \ gri_fft_filter_ccc_generic.cc \ gr_fft_filter_ccc.cc \ @@ -276,7 +275,6 @@ grinclude_HEADERS = \ gr_adaptive_fir_ccc.h \ gr_adaptive_fir_ccf.h \ gr_altivec.h \ - gr_cma_equalizer_cc.h \ gr_cpu.h \ gri_fft_filter_fff_generic.h \ gri_fft_filter_ccc_generic.h \ @@ -361,7 +359,6 @@ swiginclude_HEADERS = \ filter_generated.i \ gr_adaptive_fir_ccc.i \ gr_adaptive_fir_ccf.i \ - gr_cma_equalizer_cc.i \ gr_fft_filter_ccc.i \ gr_fft_filter_fff.i \ gr_filter_delay_fc.i \ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i index 58bb4f0d5d..2af7fcc5c6 100644 --- a/gnuradio-core/src/lib/filter/filter.i +++ b/gnuradio-core/src/lib/filter/filter.i @@ -31,7 +31,6 @@ #include <gr_fractional_interpolator_ff.h> #include <gr_fractional_interpolator_cc.h> #include <gr_goertzel_fc.h> -#include <gr_cma_equalizer_cc.h> #include <gr_pfb_channelizer_ccf.h> #include <gr_pfb_synthesis_filterbank_ccf.h> #include <gr_pfb_decimator_ccf.h> @@ -53,7 +52,6 @@ %include "gr_fractional_interpolator_ff.i" %include "gr_fractional_interpolator_cc.i" %include "gr_goertzel_fc.i" -%include "gr_cma_equalizer_cc.i" %include "gr_pfb_channelizer_ccf.i" %include "gr_pfb_synthesis_filterbank_ccf.i" %include "gr_pfb_decimator_ccf.i" diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc deleted file mode 100644 index f80bfd5184..0000000000 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_cma_equalizer_cc.h> - -gr_cma_equalizer_cc_sptr -gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu) -{ - return gnuradio::get_initial_sptr(new gr_cma_equalizer_cc(num_taps, modulus, mu)); -} - -gr_cma_equalizer_cc::gr_cma_equalizer_cc(int num_taps, float modulus, float mu) - : gr_adaptive_fir_ccf("cma_equalizer_cc", 1, std::vector<float>(num_taps)), - d_modulus(modulus), d_mu(mu) -{ - if (num_taps > 0) - d_taps[0] = 1.0; -} - diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i deleted file mode 100644 index 30e2fb8bd9..0000000000 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2009 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,cma_equalizer_cc) - -// retrieve info on the base class, without generating wrappers since -// the base class has a pure virual method. -%import "gr_adaptive_fir_ccf.i" - -gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); - -class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf -{ -private: - gr_cma_equalizer_cc(int num_taps, float modulus, float mu); - -public: -}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc index a52d1d9011..b5a5aed7d3 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009,2010 Free Software Foundation, Inc. + * Copyright 2009-2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -33,14 +33,14 @@ #include <gr_io_signature.h> #include <gr_math.h> -gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size, float init_phase, float max_rate_deviation, int osps) { - return gnuradio::get_initial_sptr(new gr_pfb_clock_sync_ccf (sps, gain, taps, + return gnuradio::get_initial_sptr(new gr_pfb_clock_sync_ccf (sps, loop_bw, taps, filter_size, init_phase, max_rate_deviation, @@ -49,7 +49,7 @@ gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)}; static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); -gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float gain, +gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size, float init_phase, @@ -65,11 +65,15 @@ gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float gain, d_nfilters = filter_size; d_sps = floor(sps); + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); + // Store the last filter between calls to work // The accumulator keeps track of overflow to increment the stride correctly. // set it here to the fractional difference based on the initial phaes - set_alpha(gain); - set_beta(0.25*gain*gain); d_k = init_phase; d_rate = (sps-floor(sps))*(double)d_nfilters; d_rate_i = (int)floor(d_rate); @@ -107,6 +111,94 @@ gr_pfb_clock_sync_ccf::check_topology(int ninputs, int noutputs) return noutputs == 1 || noutputs == 4; } + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +gr_pfb_clock_sync_ccf::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +gr_pfb_clock_sync_ccf::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +gr_pfb_clock_sync_ccf::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +gr_pfb_clock_sync_ccf::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +gr_pfb_clock_sync_ccf::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +gr_pfb_clock_sync_ccf::get_damping_factor() const +{ + return d_damping; +} + +float +gr_pfb_clock_sync_ccf::get_alpha() const +{ + return d_alpha; +} + +float +gr_pfb_clock_sync_ccf::get_beta() const +{ + return d_beta; +} + +/******************************************************************* +*******************************************************************/ + +void +gr_pfb_clock_sync_ccf::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + + void gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps, std::vector< std::vector<float> > &ourtaps, @@ -131,13 +223,16 @@ gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps, // Partition the filter for(i = 0; i < d_nfilters; i++) { // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out - ourtaps[d_nfilters-1-i] = std::vector<float>(d_taps_per_filter, 0); + //ourtaps[d_nfilters-1-i] = std::vector<float>(d_taps_per_filter, 0); + ourtaps[i] = std::vector<float>(d_taps_per_filter, 0); for(j = 0; j < d_taps_per_filter; j++) { - ourtaps[d_nfilters - 1 - i][j] = tmp_taps[i + j*d_nfilters]; + //ourtaps[d_nfilters - 1 - i][j] = tmp_taps[i + j*d_nfilters]; + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; } // Build a filter for each channel and add it's taps to it - ourfilter[i]->set_taps(ourtaps[d_nfilters-1-i]); + //ourfilter[i]->set_taps(ourtaps[d_nfilters-1-i]); + ourfilter[i]->set_taps(ourtaps[i]); } // Set the history to ensure enough input items for each filter @@ -150,58 +245,84 @@ void gr_pfb_clock_sync_ccf::create_diff_taps(const std::vector<float> &newtaps, std::vector<float> &difftaps) { - float maxtap = 1e-20; - difftaps.clear(); - difftaps.push_back(0); //newtaps[0]); - for(unsigned int i = 1; i < newtaps.size()-1; i++) { - float tap = newtaps[i+1] - newtaps[i-1]; - difftaps.push_back(tap); - if(tap > maxtap) { - maxtap = tap; + std::vector<float> diff_filter(3); + diff_filter[0] = -1; + diff_filter[1] = 0; + diff_filter[2] = 1; + + float pwr = 0; + difftaps.push_back(0); + for(unsigned int i = 0; i < newtaps.size()-2; i++) { + float tap = 0; + for(int j = 0; j < 3; j++) { + tap += diff_filter[j]*newtaps[i+j]; + pwr += fabsf(tap); } + difftaps.push_back(tap); } - difftaps.push_back(0);//-newtaps[newtaps.size()-1]); + difftaps.push_back(0); - // Scale the differential taps; helps scale error term to better update state - // FIXME: should this be scaled this way or use the same gain as the taps? for(unsigned int i = 0; i < difftaps.size(); i++) { - difftaps[i] /= maxtap; + difftaps[i] *= pwr; } } -void -gr_pfb_clock_sync_ccf::print_taps() +std::string +gr_pfb_clock_sync_ccf::get_taps_as_string() { int i, j; - printf("[ "); + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; for(i = 0; i < d_nfilters; i++) { - printf("[%.4e, ", d_taps[i][0]); + str << "[" << d_taps[i][0] << ", "; for(j = 1; j < d_taps_per_filter-1; j++) { - printf("%.4e,", d_taps[i][j]); + str << d_taps[i][j] << ", "; } - printf("%.4e],", d_taps[i][j]); + str << d_taps[i][j] << "],"; } - printf(" ]\n"); + str << " ]" << std::endl; + + return str.str(); } -void -gr_pfb_clock_sync_ccf::print_diff_taps() +std::string +gr_pfb_clock_sync_ccf::get_diff_taps_as_string() { int i, j; - printf("[ "); + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; for(i = 0; i < d_nfilters; i++) { - printf("[%.4e, ", d_dtaps[i][0]); + str << "[" << d_dtaps[i][0] << ", "; for(j = 1; j < d_taps_per_filter-1; j++) { - printf("%.4e,", d_dtaps[i][j]); + str << d_dtaps[i][j] << ", "; } - printf("%.4e],", d_dtaps[i][j]); + str << d_dtaps[i][j] << "],"; } - printf(" ]\n"); + str << " ]" << std::endl; + + return str.str(); } +std::vector< std::vector<float> > +gr_pfb_clock_sync_ccf::get_taps() +{ + return d_taps; +} + +std::vector< std::vector<float> > +gr_pfb_clock_sync_ccf::get_diff_taps() +{ + return d_dtaps; +} std::vector<float> -gr_pfb_clock_sync_ccf::channel_taps(int channel) +gr_pfb_clock_sync_ccf::get_channel_taps(int channel) { std::vector<float> taps; for(int i = 0; i < d_taps_per_filter; i++) { @@ -211,7 +332,7 @@ gr_pfb_clock_sync_ccf::channel_taps(int channel) } std::vector<float> -gr_pfb_clock_sync_ccf::diff_channel_taps(int channel) +gr_pfb_clock_sync_ccf::get_diff_channel_taps(int channel) { std::vector<float> taps; for(int i = 0; i < d_taps_per_filter; i++) { @@ -230,7 +351,7 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items, gr_complex *in = (gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - float *err = 0, *outrate = 0, *outk = 0; + float *err = NULL, *outrate = NULL, *outk = NULL; if(output_items.size() == 4) { err = (float *) output_items[1]; outrate = (float*)output_items[2]; @@ -271,13 +392,13 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items, } gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]); - error_r = out[i].real() * diff.real(); - error_i = out[i].imag() * diff.imag(); + error_r = out[i].real() * diff.real(); + error_i = out[i].imag() * diff.imag(); error = (error_i + error_r) / 2.0; // average error from I&Q channel // Run the control loop to update the current phase (k) and tracking rate - d_k = d_k + d_alpha*error + d_rate_i + d_rate_f; d_rate_f = d_rate_f + d_beta*error; + d_k = d_k + d_alpha*error + d_rate_i + d_rate_f; // Keep our rate within a good range d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); @@ -285,7 +406,7 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items, if(output_items.size() == 4) { // FIXME: don't really know what to do about d_osps>1 for(int k = 0; k < d_osps; k++) { - err[i] = error; + err[i] = diff.real(); outrate[i] = d_rate_f; outk[i] = d_k; } diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h index 6ce4c1a1e4..1f96b9000c 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h @@ -29,7 +29,7 @@ class gr_pfb_clock_sync_ccf; typedef boost::shared_ptr<gr_pfb_clock_sync_ccf> gr_pfb_clock_sync_ccf_sptr; -GR_CORE_API gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, +GR_CORE_API gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size=32, float init_phase=0, @@ -118,45 +118,48 @@ class GR_CORE_API gr_pfb_clock_sync_ccf : public gr_block /*! * Build the polyphase filterbank timing synchronizer. * \param sps (double) The number of samples per symbol in the incoming signal - * \param gain (float) The alpha gain of the control loop; beta = (gain^2)/4 by default. + * \param loop_bw (float) The bandwidth of the control loop; set's alpha and beta. * \param taps (vector<int>) The filter taps. * \param filter_size (uint) The number of filters in the filterbank (default = 32). * \param init_phase (float) The initial phase to look at, or which filter to start * with (default = 0). * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). - * \parma osps (int) The number of output samples per symbol (default=1). * */ - friend GR_CORE_API gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, + friend GR_CORE_API gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size, float init_phase, float max_rate_deviation, int osps); - bool d_updated; - double d_sps; - double d_sample_num; - float d_alpha; - float d_beta; - int d_nfilters; - std::vector<gr_fir_ccf*> d_filters; - std::vector<gr_fir_ccf*> d_diff_filters; + bool d_updated; + double d_sps; + double d_sample_num; + float d_loop_bw; + float d_damping; + float d_alpha; + float d_beta; + + int d_nfilters; + int d_taps_per_filter; + std::vector<gr_fir_ccf*> d_filters; + std::vector<gr_fir_ccf*> d_diff_filters; std::vector< std::vector<float> > d_taps; std::vector< std::vector<float> > d_dtaps; - float d_k; - float d_rate; - float d_rate_i; - float d_rate_f; - float d_max_dev; - int d_filtnum; - int d_taps_per_filter; - int d_osps; + + float d_k; + float d_rate; + float d_rate_i; + float d_rate_f; + float d_max_dev; + int d_filtnum; + int d_osps; /*! * Build the polyphase filterbank timing synchronizer. */ - gr_pfb_clock_sync_ccf (double sps, float gain, + gr_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size, float init_phase, @@ -168,6 +171,15 @@ class GR_CORE_API gr_pfb_clock_sync_ccf : public gr_block public: ~gr_pfb_clock_sync_ccf (); + + /*! \brief update the system gains from omega and eta + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); /*! * Resets the filterbank's filter taps with the new prototype filter @@ -177,40 +189,97 @@ public: std::vector<gr_fir_ccf*> &ourfilter); /*! - * Returns the taps of the matched filter + * Returns all of the taps of the matched filter */ - std::vector<float> channel_taps(int channel); + std::vector< std::vector<float> > get_taps(); /*! - * Returns the taps in the derivative filter + * Returns all of the taps of the derivative filter */ - std::vector<float> diff_channel_taps(int channel); + std::vector< std::vector<float> > get_diff_taps(); /*! - * Print all of the filterbank taps to screen. + * Returns the taps of the matched filter for a particular channel */ - void print_taps(); + std::vector<float> get_channel_taps(int channel); /*! - * Print all of the filterbank taps of the derivative filter to screen. + * Returns the taps in the derivative filter for a particular channel */ - void print_diff_taps(); + std::vector<float> get_diff_channel_taps(int channel); /*! - * Set the gain value alpha for the control loop - */ - void set_alpha(float alpha) - { - d_alpha = alpha; - } + * Return the taps as a formatted string for printing + */ + std::string get_taps_as_string(); /*! - * Set the gain value beta for the control loop - */ - void set_beta(float beta) - { - d_beta = beta; - } + * Return the derivative filter taps as a formatted string for printing + */ + std::string get_diff_taps_as_string(); + + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); /*! * Set the maximum deviation from 0 d_rate can have @@ -220,6 +289,33 @@ public: d_max_dev = m; } + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /******************************************************************* + *******************************************************************/ + bool check_topology(int ninputs, int noutputs); int general_work (int noutput_items, diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i index 343ed09121..78b9a65898 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i @@ -22,7 +22,7 @@ GR_SWIG_BLOCK_MAGIC(gr,pfb_clock_sync_ccf); -gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size=32, float init_phase=0, @@ -32,7 +32,7 @@ gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, class gr_pfb_clock_sync_ccf : public gr_block { private: - gr_pfb_clock_sync_ccf (double sps, float gain, + gr_pfb_clock_sync_ccf (double sps, float loop_bw, const std::vector<float> &taps, unsigned int filter_size, float init_phase, @@ -46,11 +46,22 @@ class gr_pfb_clock_sync_ccf : public gr_block std::vector< std::vector<float> > &ourtaps, std::vector<gr_fir_ccf*> &ourfilter); - std::vector<float> channel_taps(int channel); - std::vector<float> diff_channel_taps(int channel); - void print_taps(); - void print_diff_taps(); + std::vector< std::vector<float> > get_taps(); + std::vector< std::vector<float> > get_diff_taps(); + std::vector<float> get_channel_taps(int channel); + std::vector<float> get_diff_channel_taps(int channel); + std::string get_taps_as_string(); + std::string get_diff_taps_as_string(); + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); void set_alpha(float alpha); void set_beta(float beta); void set_max_rate_deviation(float m); + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + }; diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index d9e6353471..1cd9c6bd14 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -77,6 +77,7 @@ LIST(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/gr_reverse.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_add_const_ss_generic.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_char_to_float.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_control_loop.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_debugger_hook.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_char.cc @@ -131,6 +132,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_cc.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_ff.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_char_to_float.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_control_loop.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_debugger_hook.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_char.h @@ -160,6 +162,7 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc_ff.i ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_cc.i ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_ff.i + ${CMAKE_CURRENT_SOURCE_DIR}/gri_control_loop.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "core_swig" ) @@ -177,22 +180,15 @@ SET(gr_core_general_triple_threats gr_agc2_ff gr_align_on_samplenumbers_ss gr_bin_statistics_f - gr_binary_slicer_fb gr_bytes_to_syms gr_char_to_float gr_check_counting_s gr_check_lfsr_32k_s - gr_clock_recovery_mm_cc - gr_clock_recovery_mm_ff gr_complex_to_interleaved_short gr_complex_to_xxx gr_conjugate_cc - gr_constellation_decoder_cb gr_copy - gr_correlate_access_code_bb - gr_costas_loop_cc gr_cpfsk_bc - gr_crc32 gr_ctcss_squelch_ff gr_decode_ccsds_27_fb gr_diff_decoder_bb @@ -208,7 +204,6 @@ SET(gr_core_general_triple_threats gr_fft_vcc gr_fft_vfc gr_firdes - gr_fll_band_edge_cc gr_float_to_char gr_float_to_complex gr_float_to_short @@ -226,10 +221,7 @@ SET(gr_core_general_triple_threats gr_keep_one_in_n gr_kludge_copy gr_lfsr_32k_source_s - gr_lms_dfe_cc - gr_lms_dfe_ff gr_map_bb - gr_mpsk_receiver_cc gr_nlog10_ff gr_nop gr_null_sink diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am index defbbbb0c8..f210cee393 100644 --- a/gnuradio-core/src/lib/general/Makefile.am +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -44,24 +44,17 @@ libgeneral_la_SOURCES = \ gr_agc2_ff.cc \ gr_align_on_samplenumbers_ss.cc \ gr_bin_statistics_f.cc \ - gr_binary_slicer_fb.cc \ gr_bytes_to_syms.cc \ gr_char_to_float.cc \ gr_check_counting_s.cc \ gr_check_lfsr_32k_s.cc \ gr_circular_file.cc \ - gr_clock_recovery_mm_cc.cc \ - gr_clock_recovery_mm_ff.cc \ gr_complex_to_interleaved_short.cc \ gr_complex_to_xxx.cc \ gr_conjugate_cc.cc \ gr_copy.cc \ - gr_constellation_decoder_cb.cc \ - gr_correlate_access_code_bb.cc \ - gr_costas_loop_cc.cc \ gr_count_bits.cc \ gr_cpfsk_bc.cc \ - gr_crc32.cc \ gr_ctcss_squelch_ff.cc \ gr_decode_ccsds_27_fb.cc \ gr_deinterleave.cc \ @@ -79,7 +72,6 @@ libgeneral_la_SOURCES = \ gr_fft_vcc_fftw.cc \ gr_fft_vfc.cc \ gr_firdes.cc \ - gr_fll_band_edge_cc.cc \ gr_float_to_char.cc \ gr_float_to_complex.cc \ gr_float_to_short.cc \ @@ -97,11 +89,8 @@ libgeneral_la_SOURCES = \ gr_keep_one_in_n.cc \ gr_kludge_copy.cc \ gr_lfsr_32k_source_s.cc \ - gr_lms_dfe_cc.cc \ - gr_lms_dfe_ff.cc \ gr_map_bb.cc \ gr_misc.cc \ - gr_mpsk_receiver_cc.cc \ gr_nlog10_ff.cc \ gr_nop.cc \ gr_null_sink.cc \ @@ -164,6 +153,7 @@ libgeneral_la_SOURCES = \ gr_wvps_ff.cc \ gri_add_const_ss_generic.cc \ gri_char_to_float.cc \ + gri_control_loop.cc \ gri_debugger_hook.cc \ gri_fft.cc \ gri_float_to_char.cc \ @@ -202,24 +192,17 @@ grinclude_HEADERS = \ gr_agc2_ff.h \ gr_align_on_samplenumbers_ss.h \ gr_bin_statistics_f.h \ - gr_binary_slicer_fb.h \ gr_bytes_to_syms.h \ gr_char_to_float.h \ gr_check_counting_s.h \ gr_check_lfsr_32k_s.h \ gr_circular_file.h \ - gr_clock_recovery_mm_cc.h \ - gr_clock_recovery_mm_ff.h \ gr_complex_to_interleaved_short.h \ gr_complex_to_xxx.h \ gr_conjugate_cc.h \ - gr_constellation_decoder_cb.h \ gr_copy.h \ - gr_correlate_access_code_bb.h \ - gr_costas_loop_cc.h \ gr_count_bits.h \ gr_cpfsk_bc.h \ - gr_crc32.h \ gr_ctcss_squelch_ff.h \ gr_decode_ccsds_27_fb.h \ gr_diff_decoder_bb.h \ @@ -237,7 +220,6 @@ grinclude_HEADERS = \ gr_fft_vcc_fftw.h \ gr_fft_vfc.h \ gr_firdes.h \ - gr_fll_band_edge_cc.h \ gr_float_to_char.h \ gr_float_to_complex.h \ gr_float_to_short.h \ @@ -257,14 +239,11 @@ grinclude_HEADERS = \ gr_keep_one_in_n.h \ gr_kludge_copy.h \ gr_lfsr_32k_source_s.h \ - gr_lms_dfe_cc.h \ - gr_lms_dfe_ff.h \ gr_log2_const.h \ gr_map_bb.h \ gr_math.h \ gr_misc.h \ gr_nco.h \ - gr_mpsk_receiver_cc.h \ gr_nlog10_ff.h \ gr_nop.h \ gr_null_sink.h \ @@ -334,6 +313,7 @@ grinclude_HEADERS = \ gri_agc2_cc.h \ gri_agc2_ff.h \ gri_char_to_float.h \ + gri_control_loop.h \ gri_debugger_hook.h \ gri_fft.h \ gri_float_to_char.h \ @@ -378,22 +358,15 @@ swiginclude_HEADERS = \ gr_agc2_ff.i \ gr_align_on_samplenumbers_ss.i \ gr_bin_statistics_f.i \ - gr_binary_slicer_fb.i \ gr_bytes_to_syms.i \ gr_char_to_float.i \ gr_check_counting_s.i \ gr_check_lfsr_32k_s.i \ - gr_clock_recovery_mm_cc.i \ - gr_clock_recovery_mm_ff.i \ gr_complex_to_interleaved_short.i \ gr_complex_to_xxx.i \ gr_conjugate_cc.i \ - gr_constellation_decoder_cb.i \ gr_copy.i \ - gr_correlate_access_code_bb.i \ - gr_costas_loop_cc.i \ gr_cpfsk_bc.i \ - gr_crc32.i \ gr_ctcss_squelch_ff.i \ gr_decode_ccsds_27_fb.i \ gr_diff_decoder_bb.i \ @@ -409,7 +382,6 @@ swiginclude_HEADERS = \ gr_fft_vcc.i \ gr_fft_vfc.i \ gr_firdes.i \ - gr_fll_band_edge_cc.i \ gr_float_to_char.i \ gr_float_to_complex.i \ gr_float_to_short.i \ @@ -427,10 +399,7 @@ swiginclude_HEADERS = \ gr_keep_one_in_n.i \ gr_kludge_copy.i \ gr_lfsr_32k_source_s.i \ - gr_lms_dfe_cc.i \ - gr_lms_dfe_ff.i \ gr_map_bb.i \ - gr_mpsk_receiver_cc.i \ gr_nlog10_ff.i \ gr_nop.i \ gr_null_sink.i \ @@ -493,6 +462,7 @@ swiginclude_HEADERS = \ gri_agc_ff.i \ gri_agc2_cc.i \ gri_agc2_ff.i \ + gri_control_loop.i \ gr_descrambler_bb.i \ gr_scrambler_bb.i \ gr_probe_mpsk_snr_c.i \ diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 5a55341292..f9adff3fa2 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -22,6 +22,7 @@ %{ +#include <gri_control_loop.h> #include <gr_nop.h> #include <gr_null_sink.h> #include <gr_null_source.h> @@ -69,7 +70,6 @@ #include <gr_nlog10_ff.h> #include <gr_fake_channel_coder_pp.h> #include <gr_throttle.h> -#include <gr_mpsk_receiver_cc.h> #include <gr_stream_mux.h> #include <gr_stream_to_streams.h> #include <gr_streams_to_stream.h> @@ -77,13 +77,8 @@ #include <gr_vector_to_streams.h> #include <gr_conjugate_cc.h> #include <gr_vco_f.h> -#include <gr_crc32.h> #include <gr_threshold_ff.h> -#include <gr_clock_recovery_mm_ff.h> -#include <gr_clock_recovery_mm_cc.h> #include <gr_packet_sink.h> -#include <gr_lms_dfe_cc.h> -#include <gr_lms_dfe_ff.h> #include <gr_dpll_bb.h> #include <gr_fmdet_cf.h> #include <gr_pll_freqdet_cf.h> @@ -102,7 +97,6 @@ #include <gr_ofdm_insert_preamble.h> #include <gr_ofdm_sampler.h> #include <gr_regenerate_bb.h> -#include <gr_costas_loop_cc.h> #include <gr_pa_2x2_phase_combiner.h> #include <gr_kludge_copy.h> #include <gr_prefs.h> @@ -110,10 +104,7 @@ #include <gr_test_types.h> #include <gr_test.h> #include <gr_unpack_k_bits_bb.h> -#include <gr_correlate_access_code_bb.h> #include <gr_diff_phasor_cc.h> -#include <gr_constellation_decoder_cb.h> -#include <gr_binary_slicer_fb.h> #include <gr_diff_encoder_bb.h> #include <gr_diff_decoder_bb.h> #include <gr_framer_sink_1.h> @@ -141,7 +132,6 @@ #include <gr_wavelet_ff.h> #include <gr_wvps_ff.h> #include <gr_copy.h> -#include <gr_fll_band_edge_cc.h> #include <gr_additive_scrambler_bb.h> #include <complex_vec_test.h> #include <gr_annotator_alltoall.h> @@ -149,6 +139,7 @@ #include <gr_burst_tagger.h> %} +%include "gri_control_loop.i" %include "gr_nop.i" %include "gr_null_sink.i" %include "gr_null_source.i" @@ -196,7 +187,6 @@ %include "gr_nlog10_ff.i" %include "gr_fake_channel_coder_pp.i" %include "gr_throttle.i" -%include "gr_mpsk_receiver_cc.i" %include "gr_stream_mux.i" %include "gr_stream_to_streams.i" %include "gr_streams_to_stream.i" @@ -204,13 +194,8 @@ %include "gr_vector_to_streams.i" %include "gr_conjugate_cc.i" %include "gr_vco_f.i" -%include "gr_crc32.i" %include "gr_threshold_ff.i" -%include "gr_clock_recovery_mm_ff.i" -%include "gr_clock_recovery_mm_cc.i" %include "gr_packet_sink.i" -%include "gr_lms_dfe_cc.i" -%include "gr_lms_dfe_ff.i" %include "gr_dpll_bb.i" %include "gr_fmdet_cf.i" %include "gr_pll_freqdet_cf.i" @@ -229,7 +214,6 @@ %include "gr_ofdm_insert_preamble.i" %include "gr_ofdm_sampler.i" %include "gr_regenerate_bb.i" -%include "gr_costas_loop_cc.i" %include "gr_pa_2x2_phase_combiner.i" %include "gr_kludge_copy.i" %include "gr_prefs.i" @@ -237,10 +221,7 @@ %include "gr_test_types.h" %include "gr_test.i" %include "gr_unpack_k_bits_bb.i" -%include "gr_correlate_access_code_bb.i" %include "gr_diff_phasor_cc.i" -%include "gr_constellation_decoder_cb.i" -%include "gr_binary_slicer_fb.i" %include "gr_diff_encoder_bb.i" %include "gr_diff_decoder_bb.i" %include "gr_framer_sink_1.i" @@ -268,7 +249,6 @@ %include "gr_wavelet_ff.i" %include "gr_wvps_ff.i" %include "gr_copy.i" -%include "gr_fll_band_edge_cc.i" %include "gr_additive_scrambler_bb.i" %include "complex_vec_test.i" %include "gr_annotator_alltoall.i" diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc deleted file mode 100644 index 5b87f1430f..0000000000 --- a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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_constellation_decoder_cb.h> -#include <gr_io_signature.h> -#include <stdexcept> - -#include <cstdio> -#include <iostream> -using std::cout; -using std::endl; - -static const bool compute_EVM = false; - -gr_constellation_decoder_cb_sptr -gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out) -{ - return gr_constellation_decoder_cb_sptr - (new gr_constellation_decoder_cb(sym_position, sym_value_out)); -} - -gr_constellation_decoder_cb:: -gr_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out) - : gr_sync_block ("constellation_decoder_cb", - gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 1, sizeof (unsigned char))) -{ - if (!set_constellation(sym_position,sym_value_out)) - throw std::invalid_argument("constellation_decoder_cb"); -} - - -gr_constellation_decoder_cb::~gr_constellation_decoder_cb(){} - - -bool -gr_constellation_decoder_cb::set_constellation(const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out) -{ - if (sym_position.size() != sym_value_out.size()) - return false; - - if (sym_position.size()<1) - return false; - - d_sym_position = sym_position; - d_sym_value_out = sym_value_out; - return true; -} - - -int -gr_constellation_decoder_cb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - unsigned int table_size = d_sym_value_out.size(); - unsigned int min_index = 0; - float min_euclid_dist = 0; - float euclid_dist = 0; - double total_error = 0; - - for(int i = 0; i < noutput_items; i++){ - min_euclid_dist = norm(in[i] - d_sym_position[0]); - min_index = 0; - for (unsigned int j = 1; j < table_size; j++){ - euclid_dist = norm(in[i] - d_sym_position[j]); - if (euclid_dist < min_euclid_dist){ - min_euclid_dist = euclid_dist; - min_index = j; - } - } - - out[i] = d_sym_value_out[min_index]; - - if (compute_EVM) - total_error += sqrtf(min_euclid_dist); - } - - if (compute_EVM){ - double mean = total_error / noutput_items; - double rms = sqrt(mean * mean); - fprintf(stderr, "EVM = %8.4f\n", rms); - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i deleted file mode 100644 index 8d9c9b56eb..0000000000 --- a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,constellation_decoder_cb) - -gr_constellation_decoder_cb_sptr - gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out); - -class gr_constellation_decoder_cb : public gr_sync_block -{ - private: - gr_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out); - - friend gr_constellation_decoder_cb_sptr - gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out); - - public: - int set_constellation(const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out); - ~gr_constellation_decoder_cb(); -}; diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc b/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc deleted file mode 100644 index b77b19745b..0000000000 --- a/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010,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_costas_loop_cc.h> -#include <gr_io_signature.h> -#include <gr_expj.h> -#include <gr_sincos.h> -#include <math.h> - -#define M_TWOPI (2*M_PI) - -gr_costas_loop_cc_sptr -gr_make_costas_loop_cc (float alpha, float beta, - float max_freq, float min_freq, - int order - ) throw (std::invalid_argument) -{ - return gnuradio::get_initial_sptr(new gr_costas_loop_cc (alpha, beta, - max_freq, min_freq, - order)); -} - -gr_costas_loop_cc::gr_costas_loop_cc (float alpha, float beta, - float max_freq, float min_freq, - int order - ) throw (std::invalid_argument) - : gr_sync_block ("costas_loop_cc", - gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 2, sizeof (gr_complex))), - d_alpha(alpha), d_beta(beta), - d_max_freq(max_freq), d_min_freq(min_freq), - d_phase(0), d_freq((max_freq+min_freq)/2), - d_order(order), d_phase_detector(0) -{ - switch(d_order) { - case 2: - d_phase_detector = &gr_costas_loop_cc::phase_detector_2; - break; - - case 4: - d_phase_detector = &gr_costas_loop_cc::phase_detector_4; - break; - - case 8: - d_phase_detector = &gr_costas_loop_cc::phase_detector_8; - break; - - default: - throw std::invalid_argument("order must be 2, 4, or 8"); - break; - } -} - -float -gr_costas_loop_cc::phase_detector_8(gr_complex sample) const -{ - float K = sqrt(2.0) - 1; - - if(abs(sample.real()) >= abs(sample.imag())) { - return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - - (sample.imag()>0 ? 1.0 : -1.0) * sample.real() * K); - } - else { - return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() * K - - (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); - } -} - -float -gr_costas_loop_cc::phase_detector_4(gr_complex sample) const -{ - - return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - - (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); -} - -float -gr_costas_loop_cc::phase_detector_2(gr_complex sample) const -{ - return (sample.real()*sample.imag()); -} - -void -gr_costas_loop_cc::set_alpha(float alpha) -{ - d_alpha = alpha; -} - -void -gr_costas_loop_cc::set_beta(float beta) -{ - d_beta = beta; -} - -int -gr_costas_loop_cc::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *iptr = (gr_complex *) input_items[0]; - gr_complex *optr = (gr_complex *) output_items[0]; - gr_complex *foptr = (gr_complex *) output_items[1]; - - bool write_foptr = output_items.size() >= 2; - - float error; - gr_complex nco_out; - - if (write_foptr) { - - for (int i = 0; i < noutput_items; i++){ - nco_out = gr_expj(-d_phase); - optr[i] = iptr[i] * nco_out; - - error = (*this.*d_phase_detector)(optr[i]); - if (error > 1) - error = 1; - else if (error < -1) - error = -1; - - d_freq = d_freq + d_beta * error; - d_phase = d_phase + d_freq + d_alpha * error; - - while(d_phase>M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase<-M_TWOPI) - d_phase += M_TWOPI; - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; - - foptr[i] = gr_complex(d_freq,0); - } - } else { - for (int i = 0; i < noutput_items; i++){ - nco_out = gr_expj(-d_phase); - optr[i] = iptr[i] * nco_out; - - error = (*this.*d_phase_detector)(optr[i]); - if (error > 1) - error = 1; - else if (error < -1) - error = -1; - - d_freq = d_freq + d_beta * error; - d_phase = d_phase + d_freq + d_alpha * error; - - while(d_phase>M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase<-M_TWOPI) - d_phase += M_TWOPI; - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; - - } - } - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.i b/gnuradio-core/src/lib/general/gr_costas_loop_cc.i deleted file mode 100644 index 488cab370f..0000000000 --- a/gnuradio-core/src/lib/general/gr_costas_loop_cc.i +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,costas_loop_cc); - -gr_costas_loop_cc_sptr -gr_make_costas_loop_cc (float alpha, float beta, - float max_freq, float min_freq, - int order - ) throw (std::invalid_argument); - - -class gr_costas_loop_cc : public gr_sync_block -{ - private: - gr_costas_loop_cc (float alpha, float beta, - float max_freq, float min_freq, int order); - - public: - void set_alpha(float alpha); - float alpha(); - void set_beta(float beta); - float beta(); - float freq(); -}; diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc deleted file mode 100644 index c32398e6d5..0000000000 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009,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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_fll_band_edge_cc.h> -#include <gr_fir_ccc.h> -#include <gr_fir_util.h> -#include <gri_fft.h> -#include <gr_io_signature.h> -#include <gr_expj.h> -#include <gr_math.h> -#include <cstdio> - -#define M_TWOPI (2*M_PI) - -float sinc(float x) -{ - if(x == 0) - return 1; - else - return sin(M_PI*x)/(M_PI*x); -} - - - -gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float gain_alpha, float gain_beta) -{ - return gnuradio::get_initial_sptr(new gr_fll_band_edge_cc (samps_per_sym, rolloff, - filter_size, gain_alpha, gain_beta)); -} - - -static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(gr_complex)}; -static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); -gr_fll_band_edge_cc::gr_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta) - : gr_sync_block ("fll_band_edge_cc", - gr_make_io_signature (1, 1, sizeof(gr_complex)), - gr_make_io_signaturev (1, 4, iosig)), - d_alpha(alpha), d_beta(beta), d_updated (false) -{ - // base this on the number of samples per symbol - d_max_freq = M_TWOPI * (2.0/samps_per_sym); - d_min_freq = -M_TWOPI * (2.0/samps_per_sym); - - d_freq = 0; - d_phase = 0; - - set_alpha(alpha); - - design_filter(samps_per_sym, rolloff, filter_size); -} - -gr_fll_band_edge_cc::~gr_fll_band_edge_cc () -{ - delete d_filter_lower; - delete d_filter_upper; -} - -void -gr_fll_band_edge_cc::set_alpha(float alpha) -{ - //float eta = sqrt(2.0)/2.0; - //float theta = alpha; - //d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta); - //d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta); - d_alpha = alpha; -} - -void -gr_fll_band_edge_cc::design_filter(float samps_per_sym, float rolloff, int filter_size) -{ - int M = rint(filter_size / samps_per_sym); - float power = 0; - std::vector<float> bb_taps; - for(int i = 0; i < filter_size; i++) { - float k = -M + i*2.0/samps_per_sym; - float tap = sinc(rolloff*k - 0.5) + sinc(rolloff*k + 0.5); - power += tap; - - bb_taps.push_back(tap); - } - - int N = (bb_taps.size() - 1.0)/2.0; - std::vector<gr_complex> taps_lower; - std::vector<gr_complex> taps_upper; - for(unsigned int i = 0; i < bb_taps.size(); i++) { - float tap = bb_taps[i] / power; - - float k = (-N + (int)i)/(2.0*samps_per_sym); - - gr_complex t1 = tap * gr_expj(-2*M_PI*(1+rolloff)*k); - gr_complex t2 = tap * gr_expj(2*M_PI*(1+rolloff)*k); - - taps_lower.push_back(t1); - taps_upper.push_back(t2); - } - - std::vector<gr_complex> vtaps(0, taps_lower.size()); - d_filter_upper = gr_fir_util::create_gr_fir_ccc(vtaps); - d_filter_lower = gr_fir_util::create_gr_fir_ccc(vtaps); - - d_filter_lower->set_taps(taps_lower); - d_filter_upper->set_taps(taps_upper); - - d_updated = true; - - // Set the history to ensure enough input items for each filter - set_history(filter_size+1); - -} - -void -gr_fll_band_edge_cc::print_taps() -{ - unsigned int i; - std::vector<gr_complex> taps_upper = d_filter_upper->get_taps(); - std::vector<gr_complex> taps_lower = d_filter_lower->get_taps(); - - printf("Upper Band-edge: ["); - for(i = 0; i < taps_upper.size(); i++) { - printf(" %.4e + %.4ej,", taps_upper[i].real(), taps_upper[i].imag()); - } - printf("]\n\n"); - - printf("Lower Band-edge: ["); - for(i = 0; i < taps_lower.size(); i++) { - printf(" %.4e + %.4ej,", taps_lower[i].real(), taps_lower[i].imag()); - } - printf("]\n\n"); -} - -int -gr_fll_band_edge_cc::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - - float *frq = NULL; - float *phs = NULL; - gr_complex *err = NULL; - if(output_items.size() > 2) { - frq = (float *) output_items[1]; - phs = (float *) output_items[2]; - err = (gr_complex *) output_items[3]; - } - - if (d_updated) { - d_updated = false; - return 0; // history requirements may have changed. - } - - int i; - gr_complex nco_out; - gr_complex out_upper, out_lower; - float error; - float avg_k = 0.1; - for(i = 0; i < noutput_items; i++) { - nco_out = gr_expj(d_phase); - out[i] = in[i] * nco_out; - - out_upper = (d_filter_upper->filter(&out[i])); - out_lower = (d_filter_lower->filter(&out[i])); - error = -real((out_upper + out_lower) * conj(out_upper - out_lower)); - d_error = avg_k*error + avg_k*d_error; // average error - - d_freq = d_freq + d_beta * d_error; - d_phase = d_phase + d_freq + d_alpha * d_error; - - if(d_phase > M_PI) - d_phase -= M_TWOPI; - else if(d_phase < -M_PI) - d_phase += M_TWOPI; - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; - - if(output_items.size() > 2) { - frq[i] = d_freq; - phs[i] = d_phase; - err[i] = d_error; - } - } - - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h deleted file mode 100644 index e3007b97a3..0000000000 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_GR_FLL_BAND_EDGE_CC_H -#define INCLUDED_GR_FLL_BAND_EDGE_CC_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_fll_band_edge_cc; -typedef boost::shared_ptr<gr_fll_band_edge_cc> gr_fll_band_edge_cc_sptr; -GR_CORE_API gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta); - -class gr_fir_ccc; -class gri_fft_complex; - -/*! - * \class gr_fll_band_edge_cc - * \brief Frequency Lock Loop using band-edge filters - * - * \ingroup general - * - * The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths - * of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth - * (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges - * is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth. - * The size of the filters should be fairly large so as to average over a number of symbols. - * - * The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively. - * These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining - * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the complex conjugate) - * provides an error signal at the DC term that is directly proportional to the carrier frequency. - * We then make a second-order loop using the error signal that is the running average of e(t). - * - * In theory, the band-edge filter is the derivative of the matched filter in frequency, - * (H_be(f) = \\frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point - * of the matched filter's rolloff (if it's a raised-cosine, the derivative of a cosine is a sine). - * Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent - * in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore - * derived from this sum of sincs. The band edge filters are then just the baseband signal - * modulated to the correct place in frequency. All of these calculations are done in the - * 'design_filter' function. - * - * Note: We use FIR filters here because the filters have to have a flat phase response over the - * entire frequency range to allow their comparisons to be valid. - */ - -class GR_CORE_API gr_fll_band_edge_cc : public gr_sync_block -{ - private: - /*! - * Build the FLL - * \param samps_per_sym (float) Number of samples per symbol of signal - * \param rolloff (float) Rolloff factor of signal - * \param filter_size (int) Size (in taps) of the filter - * \param alpha (float) Loop gain 1 - * \param beta (float) Loop gain 2 - */ - friend GR_CORE_API gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta); - - float d_alpha; - float d_beta; - float d_max_freq; - float d_min_freq; - - gr_fir_ccc* d_filter_upper; - gr_fir_ccc* d_filter_lower; - bool d_updated; - float d_error; - float d_freq; - float d_phase; - - /*! - * Build the FLL - * \param samps_per_sym (float) number of samples per symbol - * \param rolloff (float) Rolloff (excess bandwidth) of signal filter - * \param filter_size (int) number of filter taps to generate - * \param alpha (float) Alpha gain in the control loop - * \param beta (float) Beta gain in the control loop - */ - gr_fll_band_edge_cc(float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta); - -public: - ~gr_fll_band_edge_cc (); - - /*! - * Design the band-edge filter based on the number of samples per symbol, - * filter rolloff factor, and the filter size - * \param samps_per_sym (float) Number of samples per symbol of signal - * \param rolloff (float) Rolloff factor of signal - * \param filter_size (int) Size (in taps) of the filter - */ - void design_filter(float samps_per_sym, float rolloff, int filter_size); - - /*! - * Set the alpha gainvalue - * \param alpha (float) new gain value - */ - void set_alpha(float alpha); - - /*! - * Set the beta gain value - * \param beta (float) new gain value - */ - void set_beta(float beta) { d_beta = beta; } - - /*! - * Print the taps to screen. - */ - void print_taps(); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.i b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.i deleted file mode 100644 index c9c792c8a6..0000000000 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.i +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,fll_band_edge_cc); - -gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta); - -class gr_fll_band_edge_cc : public gr_sync_block -{ - private: - gr_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta); - - public: - ~gr_fll_band_edge_cc (); - - void set_alpha (float alpha); - void set_beta (float beta); - void design_filter(float samps_per_sym, float rolloff, int filter_size); - void print_taps(); -}; diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc deleted file mode 100644 index 8659386d50..0000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_lms_dfe_cc.h> -#include <gr_io_signature.h> -#include <gr_misc.h> -#include <iostream> - -gr_complex -gr_lms_dfe_cc::slicer_0deg (gr_complex sample) -{ - gr_complex out; - if(fabs(real(sample))>fabs(imag(sample))) { - if(real(sample) > 0) - out = gr_complex(1,0); - else - out = gr_complex(-1,0); - } - else { - if(imag(sample) > 0) - out = gr_complex(0,1); - else - out = gr_complex(0,-1); - } - return out; -} - -gr_complex -gr_lms_dfe_cc::slicer_45deg (gr_complex sample) -{ - gr_complex out; - if(real(sample) > 0) - out = gr_complex(1,0); - else - out = gr_complex(-1,0); - if(imag(sample) > 0) - out += gr_complex(0,1); - else - out += gr_complex(0,-1); - return out; -} - -gr_lms_dfe_cc_sptr -gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps) -{ - return gnuradio::get_initial_sptr(new gr_lms_dfe_cc (lambda_ff, lambda_fb, - num_fftaps, num_fbtaps)); -} - -gr_lms_dfe_cc::gr_lms_dfe_cc (float lambda_ff, float lambda_fb , - unsigned int num_fftaps, unsigned int num_fbtaps) - : gr_sync_block ("lms_dfe_cc", - gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 1, sizeof (gr_complex))), - d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), - d_ff_delayline(gr_rounduppow2(num_fftaps)), - d_fb_delayline(gr_rounduppow2(num_fbtaps)), - d_ff_taps(num_fftaps),d_fb_taps(num_fbtaps), - d_ff_index(0), d_fb_index(0) -{ - gr_zero_vector(d_ff_taps); - d_ff_taps [d_ff_taps.size()/2] = 1; - - gr_zero_vector(d_fb_taps); - gr_zero_vector(d_ff_delayline); - gr_zero_vector(d_fb_delayline); -} - -int -gr_lms_dfe_cc::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *iptr = (const gr_complex *) input_items[0]; - gr_complex *optr = (gr_complex *) output_items[0]; - - gr_complex acc, decision, error; - unsigned int i; - - unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 - unsigned int fb_mask = d_fb_delayline.size() - 1; - - int size = noutput_items; - while (size-- > 0){ - acc = 0; - d_ff_delayline[d_ff_index] = *iptr++; - - // Compute output - for (i=0; i < d_ff_taps.size(); i++) - acc += conj(d_ff_delayline[(i+d_ff_index) & ff_mask]) * d_ff_taps[i]; - - for (i=0; i < d_fb_taps.size(); i++) - acc -= conj(d_fb_delayline[(i+d_fb_index) & fb_mask]) * d_fb_taps[i]; - - decision = slicer_45deg(acc); - error = decision - acc; - - // Update taps - for (i=0; i < d_ff_taps.size(); i++) - d_ff_taps[i] += d_lambda_ff * conj(error) * d_ff_delayline[(i+d_ff_index) & ff_mask]; - - for (i=0; i < d_fb_taps.size(); i++) - d_fb_taps[i] -= d_lambda_fb * conj(error) * d_fb_delayline[(i+d_fb_index) & fb_mask]; - - d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index - d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index - - d_fb_delayline[d_fb_index] = decision; // Save decision in feedback - - *optr++ = acc; // Output decision - } - - if (0){ - std::cout << "FF Taps\t"; - for(i=0;i<d_ff_taps.size();i++) - std::cout << d_ff_taps[i] << "\t"; - std::cout << std::endl << "FB Taps\t"; - for(i=0;i<d_fb_taps.size();i++) - std::cout << d_fb_taps[i] << "\t"; - std::cout << std::endl; - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i deleted file mode 100644 index 9a9f22b6ea..0000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,lms_dfe_cc) - -gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - -class gr_lms_dfe_cc : public gr_sync_block -{ - private: - gr_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - gr_complex slicer_0deg(gr_complex baud); - gr_complex slicer_45deg(gr_complex baud); - gr_complex conjg(gr_complex val); -}; diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc deleted file mode 100644 index 8a5e22c2fe..0000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_lms_dfe_ff.h> -#include <gr_io_signature.h> -#include <gr_misc.h> -#include <iostream> - -float -slice(float val) -{ - if (val>0) - return 1; - else - return -1; -} - -gr_lms_dfe_ff_sptr -gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps) -{ - return gnuradio::get_initial_sptr(new gr_lms_dfe_ff (lambda_ff,lambda_fb,num_fftaps,num_fbtaps)); -} - -gr_lms_dfe_ff::gr_lms_dfe_ff (float lambda_ff, float lambda_fb , - unsigned int num_fftaps, unsigned int num_fbtaps) - : gr_sync_block ("lms_dfe_ff", - gr_make_io_signature (1, 1, sizeof (float)), - gr_make_io_signature (1, 1, sizeof (float))), - d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), - d_ff_delayline(gr_rounduppow2(num_fftaps)), - d_fb_delayline(gr_rounduppow2(num_fbtaps)), - d_ff_taps(num_fftaps), d_fb_taps(num_fbtaps), - d_ff_index(0), d_fb_index(0) -{ - gr_zero_vector(d_ff_taps); - d_ff_taps [d_ff_taps.size()/2] = 1; - - gr_zero_vector(d_fb_taps); - gr_zero_vector(d_ff_delayline); - gr_zero_vector(d_fb_delayline); -} - -int -gr_lms_dfe_ff::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float *iptr = (const float *) input_items[0]; - float *optr = (float *) output_items[0]; - - float acc, decision, error; - unsigned int i; - - unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 - unsigned int fb_mask = d_fb_delayline.size() - 1; - - int size = noutput_items; - while(size-- > 0) { - acc = 0; - d_ff_delayline[d_ff_index] = *iptr++; - - // Compute output - for (i=0; i < d_ff_taps.size(); i++) - acc += d_ff_delayline[(i+d_ff_index) & ff_mask] * d_ff_taps[i]; - - for (i=0; i < d_fb_taps.size(); i++) - acc -= d_fb_delayline[(i+d_fb_index) & fb_mask] * d_fb_taps[i]; - - decision = slice(acc); - error = decision - acc; - - // Update taps - for (i=0; i < d_ff_taps.size(); i++) - d_ff_taps[i] += d_lambda_ff * error * d_ff_delayline[(i+d_ff_index) & ff_mask]; - - for (i=0; i < d_fb_taps.size(); i++) - d_fb_taps[i] -= d_lambda_fb * error * d_fb_delayline[(i+d_fb_index) & fb_mask]; - - d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index - d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index - - d_fb_delayline[d_fb_index] = decision; // Save decision in feedback - - *optr++ = acc; // Output decision - } - - if (0){ - std::cout << "FF Taps\t"; - for(i=0;i<d_ff_taps.size();i++) - std::cout << d_ff_taps[i] << "\t"; - std::cout << std::endl << "FB Taps\t"; - for(i=0;i<d_fb_taps.size();i++) - std::cout << d_fb_taps[i] << "\t"; - std::cout << std::endl; - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i deleted file mode 100644 index 3ca488b524..0000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,lms_dfe_ff) - -gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - -class gr_lms_dfe_ff : public gr_sync_block -{ - private: - gr_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); -}; diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc index 8a7fbf88ba..8968cd3f18 100644 --- a/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2010 Free Software Foundation, Inc. + * Copyright 2004,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,8 +20,6 @@ * Boston, MA 02110-1301, USA. */ -// WARNING: this file is machine generated. Edits will be over written - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -35,18 +33,16 @@ #define M_TWOPI (2*M_PI) gr_pll_refout_cc_sptr -gr_make_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq) +gr_make_pll_refout_cc (float loop_bw, float max_freq, float min_freq) { - return gnuradio::get_initial_sptr(new gr_pll_refout_cc (alpha, beta, max_freq, min_freq)); + return gnuradio::get_initial_sptr(new gr_pll_refout_cc (loop_bw, max_freq, min_freq)); } -gr_pll_refout_cc::gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq) +gr_pll_refout_cc::gr_pll_refout_cc (float loop_bw, float max_freq, float min_freq) : gr_sync_block ("pll_refout_cc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature (1, 1, sizeof (gr_complex))), - d_alpha(alpha), d_beta(beta), - d_max_freq(max_freq), d_min_freq(min_freq), - d_phase(0), d_freq((max_freq+min_freq)/2) + gri_control_loop(loop_bw, max_freq, min_freq) { } @@ -84,13 +80,10 @@ gr_pll_refout_cc::work (int noutput_items, while (size-- > 0) { error = phase_detector(*iptr++,d_phase); - d_freq = d_freq + d_beta * error; - d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + advance_loop(error); + phase_wrap(); + frequency_limit(); - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; gr_sincosf(d_phase,&t_imag,&t_real); *optr++ = gr_complex(t_real,t_imag); } diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h index 833ed51cc7..11bce50464 100644 --- a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,19 +20,18 @@ * Boston, MA 02110-1301, USA. */ - - #ifndef INCLUDED_GR_PLL_REFOUT_CC_H #define INCLUDED_GR_PLL_REFOUT_CC_H #include <gr_core_api.h> #include <gr_sync_block.h> +#include <gri_control_loop.h> class gr_pll_refout_cc; typedef boost::shared_ptr<gr_pll_refout_cc> gr_pll_refout_cc_sptr; -GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, - float max_freq, float min_freq); +GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw, + float max_freq, float min_freq); /*! * \brief Implements a PLL which locks to the input frequency and outputs a carrier * \ingroup sync_blk @@ -48,20 +47,19 @@ GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta * and beta is the frequency gain (second order, units of radians per sample per radian) * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc */ -class GR_CORE_API gr_pll_refout_cc : public gr_sync_block +class GR_CORE_API gr_pll_refout_cc : public gr_sync_block, public gri_control_loop { - friend GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, - float max_freq, float min_freq); + friend GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw, + float max_freq, float min_freq); - float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq; - gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq); + gr_pll_refout_cc (float loop_bw, float max_freq, float min_freq); int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); private: float mod_2pi (float in); - float phase_detector(gr_complex sample,float ref_phase); + float phase_detector(gr_complex sample, float ref_phase); }; #endif diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.i b/gnuradio-core/src/lib/general/gr_pll_refout_cc.i index 026a684ed0..834ea1e36b 100644 --- a/gnuradio-core/src/lib/general/gr_pll_refout_cc.i +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -22,11 +22,11 @@ GR_SWIG_BLOCK_MAGIC(gr,pll_refout_cc) - gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, - float max_freq, float min_freq); +gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw, + float max_freq, float min_freq); -class gr_pll_refout_cc : public gr_sync_block +class gr_pll_refout_cc : public gr_sync_block, public gri_control_loop { private: - gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq); + gr_pll_refout_cc (float loop_bw, float max_freq, float min_freq); }; diff --git a/gnuradio-core/src/lib/general/gri_control_loop.cc b/gnuradio-core/src/lib/general/gri_control_loop.cc new file mode 100644 index 0000000000..d84b474935 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.cc @@ -0,0 +1,183 @@ +/* -*- 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. + */ + +#include <gri_control_loop.h> +#include <gr_math.h> +#include <stdexcept> + +#define M_TWOPI (2.0f*M_PI) + +gri_control_loop::gri_control_loop(float loop_bw, + float max_freq, float min_freq) + : d_phase(0), d_freq(0), d_max_freq(max_freq), d_min_freq(min_freq) +{ + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); +} + +gri_control_loop::~gri_control_loop() +{ +} + +void +gri_control_loop::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + +void +gri_control_loop::advance_loop(float error) +{ + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_freq + d_alpha * error; +} + + +void +gri_control_loop::phase_wrap() +{ + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + +void +gri_control_loop::frequency_limit() +{ + if (d_freq > d_max_freq) + d_freq = d_min_freq; + else if (d_freq < d_min_freq) + d_freq = d_max_freq; +} + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + +void +gri_control_loop::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("gri_control_loop: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +gri_control_loop::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("gri_control_loop: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +gri_control_loop::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("gri_control_loop: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +gri_control_loop::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("gri_control_loop: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +void +gri_control_loop::set_frequency(float freq) +{ + if(freq > d_max_freq) + d_freq = d_min_freq; + else if(freq < d_min_freq) + d_freq = d_max_freq; + else + d_freq = freq; +} + +void +gri_control_loop::set_phase(float phase) +{ + d_phase = phase; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +gri_control_loop::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +gri_control_loop::get_damping_factor() const +{ + return d_damping; +} + +float +gri_control_loop::get_alpha() const +{ + return d_alpha; +} + +float +gri_control_loop::get_beta() const +{ + return d_beta; +} + +float +gri_control_loop::get_frequency() const +{ + return d_freq; +} + +float +gri_control_loop::get_phase() const +{ + return d_phase; +} diff --git a/gnuradio-core/src/lib/general/gri_control_loop.h b/gnuradio-core/src/lib/general/gri_control_loop.h new file mode 100644 index 0000000000..3aeac58f78 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.h @@ -0,0 +1,203 @@ +/* -*- 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. + */ + +#ifndef GRI_CONTROL_LOOP +#define GRI_CONTROL_LOOP + +#include <gr_core_api.h> + +class GR_CORE_API gri_control_loop +{ + protected: + float d_phase, d_freq; + float d_max_freq, d_min_freq; + float d_damping, d_loop_bw; + float d_alpha, d_beta; + + public: + gri_control_loop(float loop_bw, float max_freq, float min_freq); + virtual ~gri_control_loop(); + + /*! \brief update the system gains from the loop bandwidth and damping factor + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); + + /*! \brief update the system gains from the loop bandwidth and damping factor + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void advance_loop(float error); + + /*! \brief Keep the phase between -2pi and 2pi + * + * This function keeps the phase between -2pi and 2pi. If the phase + * is greater than 2pi by d, it wraps around to be -2pi+d; similarly if + * it is less than -2pi by d, it wraps around to 2pi-d. + * + * This function should be called after advance_loop to keep the phase + * in a good operating region. It is set as a separate method in case + * another way is desired as this is fairly heavy-handed. + */ + void phase_wrap(); + + /*! \brief Keep the frequency between d_min_freq and d_max_freq + * + * This function keeps the frequency between d_min_freq and d_max_freq. + * If the frequency is greater than d_max_freq, it is set to d_max_freq. + * If the frequency is less than d_min_freq, it is set to d_min_freq. + * + * This function should be called after advance_loop to keep the frequency + * in the specified region. It is set as a separate method in case + * another way is desired as this is fairly heavy-handed. + */ + void frequency_limit(); + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); + + /*! + * \brief Set the Costas loop's frequency. + * + * Set's the Costas Loop's frequency. While this is normally updated by the + * inner loop of the algorithm, it could be useful to manually initialize, + * set, or reset this under certain circumstances. + * + * \param freq (float) new frequency + * + */ + void set_frequency(float freq); + + /*! + * \brief Set the Costas loop's phase. + * + * Set's the Costas Loop's phase. While this is normally updated by the + * inner loop of the algorithm, it could be useful to manually initialize, + * set, or reset this under certain circumstances. + * + * \param phase (float) new phase + * + */ + void set_phase(float phase); + + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Get the Costas loop's frequency estimate + */ + float get_frequency() const; + + /*! + * \brief Get the Costas loop's phase estimate + */ + float get_phase() const; +}; + +#endif /* GRI_CONTROL_LOOP */ diff --git a/gnuradio-core/src/lib/general/gri_control_loop.i b/gnuradio-core/src/lib/general/gri_control_loop.i new file mode 100644 index 0000000000..67f8838cb1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.i @@ -0,0 +1,57 @@ +/* -*- 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. + */ + + +class gri_control_loop +{ + public: + gri_control_loop(float loop_bw, float max_freq, float min_freq); + virtual ~gri_control_loop(); + + void update_gains(); + void advance_loop(float error); + void phase_wrap(); + void frequency_limit(); + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_frequency(float freq); + void set_phase(float phase); + + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_frequency() const; + float get_phase() const; +}; diff --git a/gnuradio-core/src/python/gnuradio/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/CMakeLists.txt index a65b01806a..57bc91552e 100644 --- a/gnuradio-core/src/python/gnuradio/CMakeLists.txt +++ b/gnuradio-core/src/python/gnuradio/CMakeLists.txt @@ -29,10 +29,8 @@ GR_PYTHON_INSTALL(FILES __init__.py eng_notation.py eng_option.py - modulation_utils.py modulation_utils2.py ofdm_packet_utils.py - packet_utils.py gr_unittest.py gr_xmlrunner.py optfir.py diff --git a/gnuradio-core/src/python/gnuradio/Makefile.am b/gnuradio-core/src/python/gnuradio/Makefile.am index 7d27386a44..289e37662d 100644 --- a/gnuradio-core/src/python/gnuradio/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/Makefile.am @@ -28,10 +28,8 @@ grpython_PYTHON = \ __init__.py \ eng_notation.py \ eng_option.py \ - modulation_utils.py \ modulation_utils2.py \ ofdm_packet_utils.py \ - packet_utils.py \ gr_unittest.py \ gr_xmlrunner.py \ optfir.py \ diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt index 235cf35bed..8b0baedd92 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt +++ b/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt @@ -23,17 +23,10 @@ GR_PYTHON_INSTALL(FILES __init__.py am_demod.py channel_model.py - dbpsk.py - dbpsk2.py - dqpsk.py - dqpsk2.py - d8psk.py filterbank.py fm_demod.py fm_emph.py generic_usrp.py - gmsk.py - cpm.py logpwrfft.py nbfm_rx.py nbfm_tx.py @@ -47,13 +40,8 @@ GR_PYTHON_INSTALL(FILES pfb_channelizer.py pfb_decimator.py pfb_interpolator.py - pkt.py psk.py qam.py - qam8.py - qam16.py - qam64.py - qam256.py rational_resampler.py standard_squelch.py stream_to_vector_decimator.py diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am index 7b24fb69d7..9665dde0b8 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am @@ -30,17 +30,10 @@ grblkspython_PYTHON = \ __init__.py \ am_demod.py \ channel_model.py \ - dbpsk.py \ - dbpsk2.py \ - dqpsk.py \ - dqpsk2.py \ - d8psk.py \ filterbank.py \ fm_demod.py \ fm_emph.py \ generic_usrp.py \ - gmsk.py \ - cpm.py \ logpwrfft.py \ nbfm_rx.py \ nbfm_tx.py \ @@ -54,13 +47,8 @@ grblkspython_PYTHON = \ pfb_channelizer.py \ pfb_decimator.py \ pfb_interpolator.py \ - pkt.py \ psk.py \ qam.py \ - qam8.py \ - qam16.py \ - qam64.py \ - qam256.py \ rational_resampler.py \ standard_squelch.py \ stream_to_vector_decimator.py \ diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/d8psk.py b/gnuradio-core/src/python/gnuradio/blks2impl/d8psk.py deleted file mode 100644 index 67cf9f5696..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/d8psk.py +++ /dev/null @@ -1,363 +0,0 @@ -# -# 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. -# - -# See gnuradio-examples/python/digital for examples - -""" -differential 8PSK modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import psk -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 3 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = 0.175 -_def_gain_mu = 0.175 -_def_mu = 0.5 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# D8PSK modulator -# ///////////////////////////////////////////////////////////////////////////// - -class d8psk_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "d8psk_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (sps since we're interpolating by sps) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect & Initialize base class - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 3 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gray code = %s" % self._gray_code - print "RS roll-off factor = %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - def add_options(parser): - """ - Adds 8PSK modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(d8psk_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# D8PSK demodulator -# -# Differentially coherent detection of differentially encoded 8psk -# ///////////////////////////////////////////////////////////////////////////// - -class d8psk_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered DQPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: for M&M block - @type gain_mu: float - @param mu: for M&M block - @type mu: float - @param omega_relative_limit: for M&M block - @type omega_relative_limit: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "d8psk_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._costas_alpha = costas_alpha - self._mm_gain_mu = gain_mu - self._mm_mu = mu - self._mm_omega_relative_limit = omega_relative_limit - self._gray_code = gray_code - - if samples_per_symbol < 2: - raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # Automatic gain control - scale = (1.0/16384.0) - self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1 - #self.agc = gr.agc_cc(1e-2, 1, 1, 100) - self.agc = gr.agc2_cc(1e-1, 1e-2, 1, 1, 100) - #self.agc = gr.feedforward_agc_cc(16, 1.0) - - # RRC data filter - ntaps = 11 * samples_per_symbol - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - self.rrc_filter=gr.interp_fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - self._mm_omega = self._samples_per_symbol - self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu - self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha - fmin = -0.025 - fmax = 0.025 - - self.receiver=gr.mpsk_receiver_cc(arity, 0, - self._costas_alpha, self._costas_beta, - fmin, fmax, - self._mm_mu, self._mm_gain_mu, - self._mm_omega, self._mm_gain_omega, - self._mm_omega_relative_limit) - - # Perform Differential decoding on the constellation - self.diffdec = gr.diff_phasor_cc() - - # find closest constellation point - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity]) - - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, - self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 3 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nDemodulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - print "Costas Loop alpha: %.2e" % self._costas_alpha - print "Costas Loop beta: %.2e" % self._costas_beta - print "M&M mu: %.2f" % self._mm_mu - print "M&M mu gain: %.2e" % self._mm_gain_mu - print "M&M omega: %.2f" % self._mm_omega - print "M&M omega gain: %.2e" % self._mm_gain_omega - print "M&M omega limit: %.2f" % self._mm_omega_relative_limit - - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.pre_scaler, - gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) - self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) - self.connect(self.receiver, - gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) - self.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_gray_decoder.dat")) - self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - def add_options(parser): - """ - Adds modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - parser.add_option("", "--costas-alpha", type="float", default=_def_costas_alpha, - help="set Costas loop alpha value [default=%default] (PSK)") - parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu, - help="set M&M symbol sync loop gain mu value [default=%default] (PSK)") - parser.add_option("", "--mu", type="float", default=_def_mu, - help="set M&M symbol sync loop mu value [default=%default] (PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options( - d8psk_demod.__init__, ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# -# Add these to the mod/demod registry -# -# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK -modulation_utils.add_type_1_mod('d8psk', d8psk_mod) -modulation_utils.add_type_1_demod('d8psk', d8psk_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py deleted file mode 100644 index 55e4890f30..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py +++ /dev/null @@ -1,363 +0,0 @@ -# -# Copyright 2005,2006,2007,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. -# - -# See gnuradio-examples/python/digital for examples - -""" -differential BPSK modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import psk -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = 0.1 -_def_gain_mu = None -_def_mu = 0.5 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# DBPSK modulator -# ///////////////////////////////////////////////////////////////////////////// - -class dbpsk_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered differential BPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per baud >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param log: Log modulation data to files? - @type log: bool - """ - - gr.hier_block2.__init__(self, "dbpsk_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) - - ntaps = 11 * self._samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity]) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (samples_per_symbol since we're - # interpolating by samples_per_symbol) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, - self.rrc_taps) - - # Connect - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # static method that's also callable on an instance - return 1 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def add_options(parser): - """ - Adds DBPSK modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default]") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=True, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(dbpsk_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - - def _print_verbage(self): - print "\nModulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - -# ///////////////////////////////////////////////////////////////////////////// -# DBPSK demodulator -# -# Differentially coherent detection of differentially encoded BPSK -# ///////////////////////////////////////////////////////////////////////////// - -class dbpsk_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered differential BPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: for M&M block - @type gain_mu: float - @param mu: for M&M block - @type mu: float - @param omega_relative_limit: for M&M block - @type omega_relative_limit: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "dbpsk_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._costas_alpha = costas_alpha - self._mm_gain_mu = gain_mu - self._mm_mu = mu - self._mm_omega_relative_limit = omega_relative_limit - self._gray_code = gray_code - - if samples_per_symbol < 2: - raise TypeError, "samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,) - - arity = pow(2,self.bits_per_symbol()) - - # Automatic gain control - #scale = (1.0/16384.0) - #self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1 - self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) - #self.agc = gr.feedforward_agc_cc(16, 2.0) - - # RRC data filter - ntaps = 11 * samples_per_symbol - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - self.rrc_filter=gr.interp_fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - if not self._mm_gain_mu: - self._mm_gain_mu = 0.1 - - self._mm_omega = self._samples_per_symbol - self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu - self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha - fmin = -0.25 - fmax = 0.25 - - self.receiver=gr.mpsk_receiver_cc(arity, 0, - self._costas_alpha, self._costas_beta, - fmin, fmax, - self._mm_mu, self._mm_gain_mu, - self._mm_omega, self._mm_gain_omega, - self._mm_omega_relative_limit) - - # Do differential decoding based on phase change of symbols - self.diffdec = gr.diff_phasor_cc() - - # find closest constellation point - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect and Initialize base class - self.connect(self, self.agc, self.rrc_filter, self.receiver, - self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 1 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nDemodulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - print "Costas Loop alpha: %.2e" % self._costas_alpha - print "Costas Loop beta: %.2e" % self._costas_beta - print "M&M mu: %.2f" % self._mm_mu - print "M&M mu gain: %.2e" % self._mm_gain_mu - print "M&M omega: %.2f" % self._mm_omega - print "M&M omega gain: %.2e" % self._mm_gain_omega - print "M&M omega limit: %.2f" % self._mm_omega_relative_limit - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.pre_scaler, - gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) - self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) - self.connect(self.receiver, - gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) - self.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) - self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - def add_options(parser): - """ - Adds DBPSK demodulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - parser.add_option("", "--costas-alpha", type="float", default=None, - help="set Costas loop alpha value [default=%default] (PSK)") - parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu, - help="set M&M symbol sync loop gain mu value [default=%default] (GMSK/PSK)") - parser.add_option("", "--mu", type="float", default=_def_mu, - help="set M&M symbol sync loop mu value [default=%default] (GMSK/PSK)") - parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit, - help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options( - dbpsk_demod.__init__, ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) -# -# Add these to the mod/demod registry -# -modulation_utils.add_type_1_mod('dbpsk', dbpsk_mod) -modulation_utils.add_type_1_demod('dbpsk', dbpsk_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py deleted file mode 100644 index d7bcf53907..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py +++ /dev/null @@ -1,369 +0,0 @@ -# -# Copyright 2009,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. -# - -# See gnuradio-examples/python/digital for examples - -""" -differential BPSK modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils2 -from math import pi, sqrt, ceil -import psk -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_freq_alpha = 0.010 -_def_phase_alpha = 0.1 -_def_timing_alpha = 0.100 -_def_timing_beta = 0.010 -_def_timing_max_dev = 1.5 - - -# ///////////////////////////////////////////////////////////////////////////// -# DBPSK modulator -# ///////////////////////////////////////////////////////////////////////////// - -class dbpsk2_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered differential BPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per baud >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param log: Log modulation data to files? - @type log: bool - """ - - gr.hier_block2.__init__(self, "dbpsk_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if self._samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) - - arity = pow(2,self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity]) - - # pulse shaping filter - nfilts = 32 - ntaps = nfilts * 11 * int(self._samples_per_symbol) # make nfilts filters of ntaps each - self.rrc_taps = gr.firdes.root_raised_cosine( - nfilts, # gain - nfilts, # sampling rate based on 32 filters in resampler - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - self.rrc_filter = gr.pfb_arb_resampler_ccf(self._samples_per_symbol, self.rrc_taps) - - # Connect - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # static method that's also callable on an instance - return 1 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def add_options(parser): - """ - Adds DBPSK modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default]") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=True, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils2.extract_kwargs_from_options(dbpsk2_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - - def _print_verbage(self): - print "\nModulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - -# ///////////////////////////////////////////////////////////////////////////// -# DBPSK demodulator -# -# Differentially coherent detection of differentially encoded BPSK -# ///////////////////////////////////////////////////////////////////////////// - -class dbpsk2_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - freq_alpha=_def_freq_alpha, - phase_alpha=_def_phase_alpha, - timing_alpha=_def_timing_alpha, - timing_max_dev=_def_timing_max_dev, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log, - sync_out=False): - """ - Hierarchical block for RRC-filtered differential BPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param freq_alpha: loop filter gain for frequency recovery - @type freq_alpha: float - @param phase_alpha: loop filter gain for phase/fine frequency recovery - @type phase_alpha: float - @param timing_alpha: loop alpha gain for timing recovery - @type timing_alpha: float - @param timing_max: timing loop maximum rate deviations - @type timing_max: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param log: Print modualtion data to files? - @type log: bool - @param sync_out: Output a sync signal on :1? - @type sync_out: bool - """ - if sync_out: io_sig_out = gr.io_signaturev(2, 2, (gr.sizeof_char, gr.sizeof_gr_complex)) - else: io_sig_out = gr.io_signature(1, 1, gr.sizeof_char) - - gr.hier_block2.__init__(self, "dqpsk2_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - io_sig_out) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._freq_alpha = freq_alpha - self._freq_beta = 0.10*self._freq_alpha - self._phase_alpha = phase_alpha - self._timing_alpha = timing_alpha - self._timing_beta = _def_timing_beta - self._timing_max_dev=timing_max_dev - self._gray_code = gray_code - - if samples_per_symbol < 2: - raise TypeError, "samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,) - - arity = pow(2,self.bits_per_symbol()) - - # Automatic gain control - self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) - #self.agc = gr.feedforward_agc_cc(16, 1.0) - - # Frequency correction - self.freq_recov = gr.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, - 11*int(self._samples_per_symbol), - self._freq_alpha, self._freq_beta) - - # symbol timing recovery with RRC data filter - nfilts = 32 - ntaps = 11 * int(self._samples_per_symbol*nfilts) - taps = gr.firdes.root_raised_cosine(nfilts, nfilts, - 1.0/float(self._samples_per_symbol), - self._excess_bw, ntaps) - self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, - self._timing_alpha, - taps, nfilts, nfilts/2, self._timing_max_dev) - self.time_recov.set_beta(self._timing_beta) - - # Perform phase / fine frequency correction - self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha - # Allow a frequency swing of +/- half of the sample rate - fmin = -0.5 - fmax = 0.5 - - self.phase_recov = gr.costas_loop_cc(self._phase_alpha, - self._phase_beta, - fmax, fmin, arity) - - # Do differential decoding based on phase change of symbols - self.diffdec = gr.diff_phasor_cc() - - # find closest constellation point - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.agc, - self.freq_recov, self.time_recov, self.phase_recov, - self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) - if sync_out: self.connect(self.time_recov, (self, 1)) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 1 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nDemodulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - print "FLL gain: %.2e" % self._freq_alpha - print "Timing alpha gain: %.2e" % self._timing_alpha - print "Timing beta gain: %.2e" % self._timing_beta - print "Timing max dev: %.2f" % self._timing_max_dev - print "Phase track alpha: %.2e" % self._phase_alpha - print "Phase track beta: %.2e" % self._phase_beta - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.connect(self.freq_recov, - gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat")) - self.connect(self.time_recov, - gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat")) - self.connect(self.phase_recov, - gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat")) - self.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) - self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - def add_options(parser): - """ - Adds DBPSK demodulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, - help="set frequency lock loop alpha gain value [default=%default] (PSK)") - parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, - help="set phase tracking loop alpha value [default=%default] (PSK)") - parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha, - help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)") - parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta, - help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)") - parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev, - help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils2.extract_kwargs_from_options( - dbpsk2_demod.__init__, ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) -# -# Add these to the mod/demod registry -# -modulation_utils2.add_type_1_mod('dbpsk2', dbpsk2_mod) -modulation_utils2.add_type_1_demod('dbpsk2', dbpsk2_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py deleted file mode 100644 index 42d5341685..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py +++ /dev/null @@ -1,363 +0,0 @@ -# -# Copyright 2005,2006,2007,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. -# - -# See gnuradio-examples/python/digital for examples - -""" -differential QPSK modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import psk -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = 0.15 -_def_gain_mu = None -_def_mu = 0.5 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# DQPSK modulator -# ///////////////////////////////////////////////////////////////////////////// - -class dqpsk_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "dqpsk_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = .707 + .707j - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (sps since we're interpolating by sps) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect & Initialize base class - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 2 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nModulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRS roll-off factor: %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - def add_options(parser): - """ - Adds QPSK modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(dqpsk_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# DQPSK demodulator -# -# Differentially coherent detection of differentially encoded qpsk -# ///////////////////////////////////////////////////////////////////////////// - -class dqpsk_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered DQPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: for M&M block - @type gain_mu: float - @param mu: for M&M block - @type mu: float - @param omega_relative_limit: for M&M block - @type omega_relative_limit: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "dqpsk_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._costas_alpha = costas_alpha - self._mm_gain_mu = gain_mu - self._mm_mu = mu - self._mm_omega_relative_limit = omega_relative_limit - self._gray_code = gray_code - - if samples_per_symbol < 2: - raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # Automatic gain control - scale = (1.0/16384.0) - self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1 - #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) - self.agc = gr.feedforward_agc_cc(16, 2.0) - - # RRC data filter - ntaps = 11 * samples_per_symbol - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - self.rrc_filter=gr.interp_fir_filter_ccf(1, self.rrc_taps) - - if not self._mm_gain_mu: - sbs_to_mm = {2: 0.050, 3: 0.075, 4: 0.11, 5: 0.125, 6: 0.15, 7: 0.15} - self._mm_gain_mu = sbs_to_mm[samples_per_symbol] - - self._mm_omega = self._samples_per_symbol - self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu - self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha - fmin = -0.25 - fmax = 0.25 - - self.receiver=gr.mpsk_receiver_cc(arity, pi/4.0, - self._costas_alpha, self._costas_beta, - fmin, fmax, - self._mm_mu, self._mm_gain_mu, - self._mm_omega, self._mm_gain_omega, - self._mm_omega_relative_limit) - - # Perform Differential decoding on the constellation - self.diffdec = gr.diff_phasor_cc() - - # find closest constellation point - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect & Initialize base class - self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, - self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 2 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nDemodulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - print "Costas Loop alpha: %.2e" % self._costas_alpha - print "Costas Loop beta: %.2e" % self._costas_beta - print "M&M mu: %.2f" % self._mm_mu - print "M&M mu gain: %.2e" % self._mm_gain_mu - print "M&M omega: %.2f" % self._mm_omega - print "M&M omega gain: %.2e" % self._mm_gain_omega - print "M&M omega limit: %.2f" % self._mm_omega_relative_limit - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.pre_scaler, - gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) - self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) - self.connect(self.receiver, - gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) - self.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_gray_decoder.dat")) - self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - def add_options(parser): - """ - Adds modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - parser.add_option("", "--costas-alpha", type="float", default=_def_costas_alpha, - help="set Costas loop alpha value [default=%default] (PSK)") - parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu, - help="set M&M symbol sync loop gain mu value [default=%default] (PSK)") - parser.add_option("", "--mu", type="float", default=_def_mu, - help="set M&M symbol sync loop mu value [default=%default] (PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options( - dqpsk_demod.__init__, ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# -# Add these to the mod/demod registry -# -modulation_utils.add_type_1_mod('dqpsk', dqpsk_mod) -modulation_utils.add_type_1_demod('dqpsk', dqpsk_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py deleted file mode 100644 index e1e627707b..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py +++ /dev/null @@ -1,377 +0,0 @@ -# -# Copyright 2009,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. -# - -# See gnuradio-examples/python/digital for examples - -""" -differential QPSK modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils2 -from math import pi, sqrt -import psk -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_freq_alpha = 0.010 -_def_phase_alpha = 0.01 -_def_timing_alpha = 0.100 -_def_timing_beta = 0.010 -_def_timing_max_dev = 1.5 - - -# ///////////////////////////////////////////////////////////////////////////// -# DQPSK modulator -# ///////////////////////////////////////////////////////////////////////////// - -class dqpsk2_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "dqpsk2_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if samples_per_symbol < 2: - raise TypeError, ("sbp must be >= 2, is %f" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = .707 + .707j - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - nfilts = 32 - ntaps = 11 * int(nfilts * self._samples_per_symbol) # make nfilts filters of ntaps each - self.rrc_taps = gr.firdes.root_raised_cosine( - nfilts, # gain - nfilts, # sampling rate based on 32 filters in resampler - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - self.rrc_filter = gr.pfb_arb_resampler_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect & Initialize base class - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 2 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nModulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRS roll-off factor: %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - def add_options(parser): - """ - Adds QPSK modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils2.extract_kwargs_from_options(dqpsk2_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# DQPSK demodulator -# -# Differentially coherent detection of differentially encoded qpsk -# ///////////////////////////////////////////////////////////////////////////// - -class dqpsk2_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - freq_alpha=_def_freq_alpha, - phase_alpha=_def_phase_alpha, - timing_alpha=_def_timing_alpha, - timing_max_dev=_def_timing_max_dev, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log, - sync_out=False): - """ - Hierarchical block for RRC-filtered DQPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param freq_alpha: loop filter gain for frequency recovery - @type freq_alpha: float - @param phase_alpha: loop filter gain - @type phase_alphas: float - @param timing_alpha: timing loop alpha gain - @type timing_alpha: float - @param timing_max: timing loop maximum rate deviations - @type timing_max: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param log: Print modualtion data to files? - @type log: bool - @param sync_out: Output a sync signal on :1? - @type sync_out: bool - """ - if sync_out: io_sig_out = gr.io_signaturev(2, 2, (gr.sizeof_char, gr.sizeof_gr_complex)) - else: io_sig_out = gr.io_signature(1, 1, gr.sizeof_char) - - gr.hier_block2.__init__(self, "dqpsk2_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - io_sig_out) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._freq_alpha = freq_alpha - self._freq_beta = 0.25*self._freq_alpha**2 - self._phase_alpha = phase_alpha - self._timing_alpha = timing_alpha - self._timing_beta = _def_timing_beta - self._timing_max_dev=timing_max_dev - self._gray_code = gray_code - - if samples_per_symbol < 2: - raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol - - arity = pow(2,self.bits_per_symbol()) - - # Automatic gain control - self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) - #self.agc = gr.feedforward_agc_cc(16, 2.0) - - # Frequency correction - self.freq_recov = gr.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, - 11*int(self._samples_per_symbol), - self._freq_alpha, self._freq_beta) - - - # symbol timing recovery with RRC data filter - nfilts = 32 - ntaps = 11 * int(samples_per_symbol*nfilts) - taps = gr.firdes.root_raised_cosine(nfilts, nfilts, - 1.0/float(self._samples_per_symbol), - self._excess_bw, ntaps) - self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, - self._timing_alpha, - taps, nfilts, nfilts/2, self._timing_max_dev) - self.time_recov.set_beta(self._timing_beta) - - - # Perform phase / fine frequency correction - self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha - # Allow a frequency swing of +/- half of the sample rate - fmin = -0.5 - fmax = 0.5 - - self.phase_recov = gr.costas_loop_cc(self._phase_alpha, - self._phase_beta, - fmax, fmin, arity) - - - # Perform Differential decoding on the constellation - self.diffdec = gr.diff_phasor_cc() - - # find closest constellation point - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity]) - else: - self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.agc, - self.freq_recov, self.time_recov, self.phase_recov, - self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) - if sync_out: self.connect(self.time_recov, (self, 1)) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 2 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "\nDemodulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "Gray code: %s" % self._gray_code - print "RRC roll-off factor: %.2f" % self._excess_bw - print "FLL gain: %.2f" % self._freq_alpha - print "Timing alpha gain: %.2f" % self._timing_alpha - print "Timing beta gain: %.2f" % self._timing_beta - print "Timing max dev: %.2f" % self._timing_max_dev - print "Phase track alpha: %.2e" % self._phase_alpha - print "Phase track beta: %.2e" % self._phase_beta - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.connect(self.freq_recov, - gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat")) - self.connect(self.time_recov, - gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat")) - self.connect(self.phase_recov, - gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat")) - self.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_gray_decoder.dat")) - self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - def add_options(parser): - """ - Adds DQPSK demodulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, - help="set frequency lock loop alpha gain value [default=%default] (PSK)") - parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, - help="set phase tracking loop alpha value [default=%default] (PSK)") - parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha, - help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)") - parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta, - help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)") - parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev, - help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)") - add_options=staticmethod(add_options) - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils2.extract_kwargs_from_options( - dqpsk2_demod.__init__, ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# -# Add these to the mod/demod registry -# -modulation_utils2.add_type_1_mod('dqpsk2', dqpsk2_mod) -modulation_utils2.add_type_1_demod('dqpsk2', dqpsk2_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pkt.py b/gnuradio-core/src/python/gnuradio/blks2impl/pkt.py deleted file mode 100644 index 908437ef2b..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/pkt.py +++ /dev/null @@ -1,164 +0,0 @@ -# -# 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 math import pi -from gnuradio import gr, packet_utils -import gnuradio.gr.gr_threading as _threading - - -# ///////////////////////////////////////////////////////////////////////////// -# mod/demod with packets as i/o -# ///////////////////////////////////////////////////////////////////////////// - -class mod_pkts(gr.hier_block2): - """ - Wrap an arbitrary digital modulator in our packet handling framework. - - Send packets by calling send_pkt - """ - def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False): - """ - Hierarchical block for sending packets - - Packets to be sent are enqueued by calling send_pkt. - The output is the complex modulated signal at baseband. - - @param modulator: instance of modulator class (gr_block or hier_block2) - @type modulator: complex baseband out - @param access_code: AKA sync vector - @type access_code: string of 1's and 0's between 1 and 64 long - @param msgq_limit: maximum number of messages in message queue - @type msgq_limit: int - @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples - @param use_whitener_offset: If true, start of whitener XOR string is incremented each packet - - See gmsk_mod for remaining parameters - """ - - gr.hier_block2.__init__(self, "mod_pkts", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._modulator = modulator - self._pad_for_usrp = pad_for_usrp - self._use_whitener_offset = use_whitener_offset - self._whitener_offset = 0 - - if access_code is None: - access_code = packet_utils.default_access_code - if not packet_utils.is_1_0_string(access_code): - raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) - self._access_code = access_code - - # accepts messages from the outside world - self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) - self.connect(self._pkt_input, self._modulator, self) - - def send_pkt(self, payload='', eof=False): - """ - Send the payload. - - @param payload: data to send - @type payload: string - """ - if eof: - msg = gr.message(1) # tell self._pkt_input we're not sending any more packets - else: - # print "original_payload =", string_to_hex_list(payload) - pkt = packet_utils.make_packet(payload, - self._modulator.samples_per_symbol(), - self._modulator.bits_per_symbol(), - self._access_code, - self._pad_for_usrp, - self._whitener_offset) - #print "pkt =", string_to_hex_list(pkt) - msg = gr.message_from_string(pkt) - if self._use_whitener_offset is True: - self._whitener_offset = (self._whitener_offset + 1) % 16 - - self._pkt_input.msgq().insert_tail(msg) - - - -class demod_pkts(gr.hier_block2): - """ - Wrap an arbitrary digital demodulator in our packet handling framework. - - The input is complex baseband. When packets are demodulated, they are passed to the - app via the callback. - """ - - def __init__(self, demodulator, access_code=None, callback=None, threshold=-1): - """ - Hierarchical block for demodulating and deframing packets. - - The input is the complex modulated signal at baseband. - Demodulated packets are sent to the handler. - - @param demodulator: instance of demodulator class (gr_block or hier_block2) - @type demodulator: complex baseband in - @param access_code: AKA sync vector - @type access_code: string of 1's and 0's - @param callback: function of two args: ok, payload - @type callback: ok: bool; payload: string - @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default) - @type threshold: int - """ - - gr.hier_block2.__init__(self, "demod_pkts", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(0, 0, 0)) # Output signature - - self._demodulator = demodulator - if access_code is None: - access_code = packet_utils.default_access_code - if not packet_utils.is_1_0_string(access_code): - raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) - self._access_code = access_code - - if threshold == -1: - threshold = 12 # FIXME raise exception - - self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY - self.correlator = gr.correlate_access_code_bb(access_code, threshold) - - self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) - self.connect(self, self._demodulator, self.correlator, self.framer_sink) - - self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) - - -class _queue_watcher_thread(_threading.Thread): - def __init__(self, rcvd_pktq, callback): - _threading.Thread.__init__(self) - self.setDaemon(1) - self.rcvd_pktq = rcvd_pktq - self.callback = callback - self.keep_running = True - self.start() - - - def run(self): - while self.keep_running: - msg = self.rcvd_pktq.delete_head() - ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1())) - if self.callback: - self.callback(ok, payload) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/qam16.py b/gnuradio-core/src/python/gnuradio/blks2impl/qam16.py deleted file mode 100644 index 0bdb9c6fb8..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/qam16.py +++ /dev/null @@ -1,208 +0,0 @@ -# -# 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. -# - -# See gnuradio-examples/python/digital for examples - -""" -QAM16 modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import qam -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = None -_def_gain_mu = 0.03 -_def_mu = 0.05 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM16 modulator -# ///////////////////////////////////////////////////////////////////////////// - -class qam16_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "qam16_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2, self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(qam.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = 1.0 - print "constellation with %d arity" % arity - rotated_const = map(lambda pt: pt * rot, qam.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (sps since we're interpolating by sps) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 4 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gray code = %s" % self._gray_code - print "RRS roll-off factor = %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat")) - - def add_options(parser): - """ - Adds QAM modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(qam16_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM16 demodulator -# -# ///////////////////////////////////////////////////////////////////////////// - -class qam16_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - gr.hier_block2.__init__(self, "qam16_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - # do this - pass - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 4 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - -# -# Add these to the mod/demod registry -# -# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK -#modulation_utils.add_type_1_mod('qam16', qam16_mod) -#modulation_utils.add_type_1_demod('qam16', qam16_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/qam256.py b/gnuradio-core/src/python/gnuradio/blks2impl/qam256.py deleted file mode 100644 index fc455f17c1..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/qam256.py +++ /dev/null @@ -1,209 +0,0 @@ -# -# 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. -# - -# See gnuradio-examples/python/digital for examples - -""" -QAM256 modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import qam -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = None -_def_gain_mu = 0.03 -_def_mu = 0.05 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM256 modulator -# ///////////////////////////////////////////////////////////////////////////// - -class qam256_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "qam256_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2, self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(qam.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = 1.0 - print "constellation with %d arity" % arity - rotated_const = map(lambda pt: pt * rot, qam.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (sps since we're interpolating by sps) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 8 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gray code = %s" % self._gray_code - print "RRS roll-off factor = %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat")) - - def add_options(parser): - """ - Adds QAM modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(qam256_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM256 demodulator -# -# ///////////////////////////////////////////////////////////////////////////// - -class qam256_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - gr.hier_block2.__init__(self, "qam256_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - - # do this - pass - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 8 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - -# -# Add these to the mod/demod registry -# -# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK -#modulation_utils.add_type_1_mod('qam256', qam256_mod) -#modulation_utils.add_type_1_demod('qam256', qam256_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/qam64.py b/gnuradio-core/src/python/gnuradio/blks2impl/qam64.py deleted file mode 100644 index 5509f37458..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/qam64.py +++ /dev/null @@ -1,208 +0,0 @@ -# -# 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. -# - -# See gnuradio-examples/python/digital for examples - -""" -differential QPSK modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import qam -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = None -_def_gain_mu = 0.03 -_def_mu = 0.05 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM64 modulator -# ///////////////////////////////////////////////////////////////////////////// - -class qam64_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "qam64_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2, self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(qam.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = 1.0 - print "constellation with %d arity" % arity - rotated_const = map(lambda pt: pt * rot, qam.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (sps since we're interpolating by sps) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 6 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gray code = %s" % self._gray_code - print "RRS roll-off factor = %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat")) - - def add_options(parser): - """ - Adds QAM modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(qam64_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM16 demodulator -# -# ///////////////////////////////////////////////////////////////////////////// - -class qam64_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - gr.hier_block2.__init__(self, "qam64_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - - # do this - pass - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 6 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - -# -# Add these to the mod/demod registry -# -# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK -#modulation_utils.add_type_1_mod('qam64', qam64_mod) -#modulation_utils.add_type_1_demod('qam16', qam16_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/qam8.py b/gnuradio-core/src/python/gnuradio/blks2impl/qam8.py deleted file mode 100644 index 6a7b355978..0000000000 --- a/gnuradio-core/src/python/gnuradio/blks2impl/qam8.py +++ /dev/null @@ -1,209 +0,0 @@ -# -# 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. -# - -# See gnuradio-examples/python/digital for examples - -""" -QAM8 modulation and demodulation. -""" - -from gnuradio import gr, gru, modulation_utils -from math import pi, sqrt -import qam -import cmath -from pprint import pprint - -# default values (used in __init__ and add_options) -_def_samples_per_symbol = 2 -_def_excess_bw = 0.35 -_def_gray_code = True -_def_verbose = False -_def_log = False - -_def_costas_alpha = None -_def_gain_mu = 0.03 -_def_mu = 0.05 -_def_omega_relative_limit = 0.005 - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM8 modulator -# ///////////////////////////////////////////////////////////////////////////// - -class qam8_mod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param samples_per_symbol: samples per symbol >= 2 - @type samples_per_symbol: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param gray_code: Tell modulator to Gray code the bits - @type gray_code: bool - @param verbose: Print information about modulator? - @type verbose: bool - @param debug: Print modualtion data to files? - @type debug: bool - """ - - gr.hier_block2.__init__(self, "qam8_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature - - self._samples_per_symbol = samples_per_symbol - self._excess_bw = excess_bw - self._gray_code = gray_code - - if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol) - - ntaps = 11 * samples_per_symbol - - arity = pow(2, self.bits_per_symbol()) - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - - if self._gray_code: - self.symbol_mapper = gr.map_bb(qam.binary_to_gray[arity]) - else: - self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity]) - - self.diffenc = gr.diff_encoder_bb(arity) - - rot = 1.0 - print "constellation with %d arity" % arity - rotated_const = map(lambda pt: pt * rot, qam.constellation[arity]) - self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (sps since we're interpolating by sps) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - - if verbose: - self._print_verbage() - - if log: - self._setup_logging() - - # Connect - self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, - self.chunks2symbols, self.rrc_filter, self) - - def samples_per_symbol(self): - return self._samples_per_symbol - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 3 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - - def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gray code = %s" % self._gray_code - print "RRS roll-off factor = %f" % self._excess_bw - - def _setup_logging(self): - print "Modulation logging turned on." - self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "bytes2chunks.dat")) - self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat")) - self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat")) - - def add_options(parser): - """ - Adds QAM modulation-specific options to the standard parser - """ - parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, - help="set RRC excess bandwith factor [default=%default] (PSK)") - parser.add_option("", "--no-gray-code", dest="gray_code", - action="store_false", default=_def_gray_code, - help="disable gray coding on modulated bits (PSK)") - add_options=staticmethod(add_options) - - - def extract_kwargs_from_options(options): - """ - Given command line options, create dictionary suitable for passing to __init__ - """ - return modulation_utils.extract_kwargs_from_options(qam8_mod.__init__, - ('self',), options) - extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) - - -# ///////////////////////////////////////////////////////////////////////////// -# QAM8 demodulator -# -# ///////////////////////////////////////////////////////////////////////////// - -class qam8_demod(gr.hier_block2): - - def __init__(self, - samples_per_symbol=_def_samples_per_symbol, - excess_bw=_def_excess_bw, - costas_alpha=_def_costas_alpha, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - gray_code=_def_gray_code, - verbose=_def_verbose, - log=_def_log): - - gr.hier_block2.__init__(self, "qam8_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature - - # do this - pass - - def bits_per_symbol(self=None): # staticmethod that's also callable on an instance - return 3 - bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM - -# -# Add these to the mod/demod registry -# -# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK -modulation_utils.add_type_1_mod('qam8', qam8_mod) -#modulation_utils.add_type_1_demod('qam8', qam8_demod) diff --git a/gnuradio-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am index 45c970227f..7bf1c0827e 100644 --- a/gnuradio-core/src/python/gnuradio/gr/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am @@ -49,11 +49,8 @@ noinst_PYTHON = \ qa_argmax.py \ qa_bin_statistics.py \ qa_classify.py \ - qa_cma_equalizer.py \ qa_complex_to_xxx.py \ - qa_constellation_decoder_cb.py \ qa_copy.py \ - qa_correlate_access_code.py \ qa_delay.py \ qa_dc_blocker.py \ qa_diff_encoder.py \ diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt index 1863e96fd5..aa93387640 100644 --- a/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt +++ b/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt @@ -21,7 +21,6 @@ INCLUDE(GrPython) GR_PYTHON_INSTALL(FILES __init__.py - crc.py freqz.py gnuplot_freqz.py hexint.py diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am index ffae4b8094..903bc26955 100644 --- a/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am @@ -25,7 +25,6 @@ grupythondir = $(grpythondir)/gruimpl grupython_PYTHON = \ __init__.py \ - crc.py \ freqz.py \ gnuplot_freqz.py \ hexint.py \ diff --git a/gr-digital/Makefile.am b/gr-digital/Makefile.am index 62c40f2dfd..f1409793ff 100644 --- a/gr-digital/Makefile.am +++ b/gr-digital/Makefile.am @@ -24,7 +24,7 @@ include $(top_srcdir)/Makefile.common SUBDIRS = lib if PYTHON -SUBDIRS += swig python apps grc +SUBDIRS += swig python apps grc examples endif pkgconfigdir = $(libdir)/pkgconfig diff --git a/gr-digital/examples/.gitignore b/gr-digital/examples/.gitignore new file mode 100644 index 0000000000..b336cc7cec --- /dev/null +++ b/gr-digital/examples/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gr-digital/examples/Makefile.am b/gr-digital/examples/Makefile.am new file mode 100644 index 0000000000..ca36716fae --- /dev/null +++ b/gr-digital/examples/Makefile.am @@ -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. +# + +include $(top_srcdir)/Makefile.common + +ourdatadir = $(exampledir)/digital + +noinst_PYTHON = \ + example_fll.py + +dist_ourdata_SCRIPTS = \ + transmit_path.py \ + receive_path.py + + diff --git a/gr-digital/examples/benchmark_rx.py b/gr-digital/examples/benchmark_rx.py new file mode 100755 index 0000000000..9390540dd4 --- /dev/null +++ b/gr-digital/examples/benchmark_rx.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# +# Copyright 2010,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 usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +# From gr-digital +from gnuradio import digital + +# from current dir +from receive_path import receive_path + +import random +import struct +import sys + +#import os +#print os.getpid() +#raw_input('Attach and press enter: ') + +class my_top_block(gr.top_block): + def __init__(self, demodulator, rx_callback, options): + gr.top_block.__init__(self) + + # Set up receive path + self.rxpath = receive_path(demodulator, rx_callback, options) + + if(options.from_file is not None): + self.thr = gr.throttle(gr.sizeof_gr_complex, 1e6) + self.source = gr.file_source(gr.sizeof_gr_complex, options.from_file) + self.connect(self.source, self.thr, self.rxpath) + else: + self.thr = gr.throttle(gr.sizeof_gr_complex, 1e6) + self.source = gr.null_source(gr.sizeof_gr_complex) + self.connect(self.source, self.thr, self.rxpath) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %5s pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + demods = digital.modulation_utils2.type_1_demods() + + # Create Options Parser: + parser = OptionParser (option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + default='psk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(demods.keys()),)) + parser.add_option("","--from-file", default=None, + help="input file of samples to demod") + + receive_path.add_options(parser, expert_grp) + + for mod in demods.values(): + mod.add_options(expert_grp) + + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help(sys.stderr) + sys.exit(1) + + if options.from_file is None: + if options.rx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) + + + # build the graph + tb = my_top_block(demods[options.modulation], rx_callback, options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." + + tb.start() # start flow graph + tb.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gr-digital/examples/benchmark_tx.py b/gr-digital/examples/benchmark_tx.py new file mode 100755 index 0000000000..e5d24915af --- /dev/null +++ b/gr-digital/examples/benchmark_tx.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# +# Copyright 2010,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 usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +# From gr-digital +from gnuradio import digital + +# from current dir +from transmit_path import transmit_path + +import random, time, struct, sys + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + +class my_top_block(gr.top_block): + def __init__(self, modulator, options): + gr.top_block.__init__(self) + + self.txpath = transmit_path(modulator, options) + + if(options.to_file is not None): + self.sink = gr.file_sink(gr.sizeof_gr_complex, options.to_file) + else: + self.sink = gr.null_sink(gr.sizeof_gr_complex) + + self.connect(self.txpath, self.sink) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return tb.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + mods = digital.modulation_utils2.type_1_mods() + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + default='psk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(mods.keys()),)) + + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + parser.add_option("","--from-file", default=None, + help="use intput file for packet contents") + parser.add_option("","--to-file", default=None, + help="Output file for modulated samples") + + transmit_path.add_options(parser, expert_grp) + + for mod in mods.values(): + mod.add_options(expert_grp) + + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.to_file is None: + if options.tx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) + + if options.from_file is not None: + source_file = open(options.from_file, 'r') + + # build the graph + tb = my_top_block(mods[options.modulation], options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + tb.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + pkt_size = int(options.size) + + while n < nbytes: + if options.from_file is None: + data = (pkt_size - 2) * chr(pktno & 0xff) + else: + data = source_file.read(pkt_size - 2) + if data == '': + break; + + payload = struct.pack('!H', pktno & 0xffff) + data + send_pkt(payload) + n += len(payload) + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + + tb.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gr-digital/examples/example_costas.py b/gr-digital/examples/example_costas.py new file mode 100755 index 0000000000..aef0196cc0 --- /dev/null +++ b/gr-digital/examples/example_costas.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python + +from gnuradio import gr, digital +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +try: + import scipy +except ImportError: + print "Error: could not import scipy (http://www.scipy.org/)" + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + sys.exit(1) + +class example_costas(gr.top_block): + def __init__(self, N, sps, rolloff, ntaps, bw, noise, foffset, toffset, poffset): + gr.top_block.__init__(self) + + rrc_taps = gr.firdes.root_raised_cosine( + sps, sps, 1.0, rolloff, ntaps) + + data = 2.0*scipy.random.randint(0, 2, N) - 1.0 + data = scipy.exp(1j*poffset) * data + + self.src = gr.vector_source_c(data.tolist(), False) + self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps) + self.chn = gr.channel_model(noise, foffset, toffset) + self.cst = digital.costas_loop_cc(bw, 2) + + self.vsnk_src = gr.vector_sink_c() + self.vsnk_cst = gr.vector_sink_c() + self.vsnk_frq = gr.vector_sink_f() + + self.connect(self.src, self.rrc, self.chn, self.cst, self.vsnk_cst) + self.connect(self.rrc, self.vsnk_src) + self.connect((self.cst,1), self.vsnk_frq) + +def main(): + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=2000, + help="Set the number of samples to process [default=%default]") + parser.add_option("-S", "--sps", type="int", default=4, + help="Set the samples per symbol [default=%default]") + parser.add_option("-r", "--rolloff", type="eng_float", default=0.35, + help="Set the rolloff factor [default=%default]") + parser.add_option("-W", "--bandwidth", type="eng_float", default=2*scipy.pi/100.0, + help="Set the loop bandwidth [default=%default]") + parser.add_option("-n", "--ntaps", type="int", default=45, + help="Set the number of taps in the filters [default=%default]") + parser.add_option("", "--noise", type="eng_float", default=0.0, + help="Set the simulation noise voltage [default=%default]") + parser.add_option("-f", "--foffset", type="eng_float", default=0.0, + help="Set the simulation's normalized frequency offset (in Hz) [default=%default]") + parser.add_option("-t", "--toffset", type="eng_float", default=1.0, + help="Set the simulation's timing offset [default=%default]") + parser.add_option("-p", "--poffset", type="eng_float", default=0.707, + help="Set the simulation's phase offset [default=%default]") + (options, args) = parser.parse_args () + + # Adjust N for the interpolation by sps + options.nsamples = options.nsamples // options.sps + + # Set up the program-under-test + put = example_costas(options.nsamples, options.sps, options.rolloff, + options.ntaps, options.bandwidth, options.noise, + options.foffset, options.toffset, options.poffset) + put.run() + + data_src = scipy.array(put.vsnk_src.data()) + + # Convert the FLL's LO frequency from rads/sec to Hz + data_frq = scipy.array(put.vsnk_frq.data()) / (2.0*scipy.pi) + + # adjust this to align with the data. + data_cst = scipy.array(3*[0,]+list(put.vsnk_cst.data())) + + # Plot the Costas loop's LO frequency + f1 = pylab.figure(1, figsize=(12,10), facecolor='w') + s1 = f1.add_subplot(2,2,1) + s1.plot(data_frq) + s1.set_title("Costas LO") + s1.set_xlabel("Samples") + s1.set_ylabel("Frequency (normalized Hz)") + + # Plot the IQ symbols + s3 = f1.add_subplot(2,2,2) + s3.plot(data_src.real, data_src.imag, "o") + s3.plot(data_cst.real, data_cst.imag, "rx") + s3.set_title("IQ") + s3.set_xlabel("Real part") + s3.set_ylabel("Imag part") + s3.set_xlim([-2, 2]) + s3.set_ylim([-2, 2]) + + # Plot the symbols in time + s4 = f1.add_subplot(2,2,3) + s4.set_position([0.125, 0.05, 0.775, 0.4]) + s4.plot(data_src.real, "o-") + s4.plot(data_cst.real, "rx-") + s4.set_title("Symbols") + s4.set_xlabel("Samples") + s4.set_ylabel("Real Part of Signals") + + pylab.show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-digital/examples/example_fll.py b/gr-digital/examples/example_fll.py new file mode 100755 index 0000000000..3b75b5a758 --- /dev/null +++ b/gr-digital/examples/example_fll.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python + +from gnuradio import gr, digital +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +try: + import scipy +except ImportError: + print "Error: could not import scipy (http://www.scipy.org/)" + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + sys.exit(1) + +class example_fll(gr.top_block): + def __init__(self, N, sps, rolloff, ntaps, bw, noise, foffset, toffset, poffset): + gr.top_block.__init__(self) + + rrc_taps = gr.firdes.root_raised_cosine( + sps, sps, 1.0, rolloff, ntaps) + + data = 2.0*scipy.random.randint(0, 2, N) - 1.0 + data = scipy.exp(1j*poffset) * data + + self.src = gr.vector_source_c(data.tolist(), False) + self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps) + self.chn = gr.channel_model(noise, foffset, toffset) + self.fll = digital.fll_band_edge_cc(sps, rolloff, ntaps, bw) + + self.vsnk_src = gr.vector_sink_c() + self.vsnk_fll = gr.vector_sink_c() + self.vsnk_frq = gr.vector_sink_f() + self.vsnk_phs = gr.vector_sink_f() + self.vsnk_err = gr.vector_sink_f() + + self.connect(self.src, self.rrc, self.chn, self.fll, self.vsnk_fll) + self.connect(self.rrc, self.vsnk_src) + self.connect((self.fll,1), self.vsnk_frq) + self.connect((self.fll,2), self.vsnk_phs) + self.connect((self.fll,3), self.vsnk_err) + +def main(): + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=2000, + help="Set the number of samples to process [default=%default]") + parser.add_option("-S", "--sps", type="int", default=4, + help="Set the samples per symbol [default=%default]") + parser.add_option("-r", "--rolloff", type="eng_float", default=0.35, + help="Set the rolloff factor [default=%default]") + parser.add_option("-W", "--bandwidth", type="eng_float", default=2*scipy.pi/100.0, + help="Set the loop bandwidth [default=%default]") + parser.add_option("-n", "--ntaps", type="int", default=45, + help="Set the number of taps in the filters [default=%default]") + parser.add_option("", "--noise", type="eng_float", default=0.0, + help="Set the simulation noise voltage [default=%default]") + parser.add_option("-f", "--foffset", type="eng_float", default=0.2, + help="Set the simulation's normalized frequency offset (in Hz) [default=%default]") + parser.add_option("-t", "--toffset", type="eng_float", default=1.0, + help="Set the simulation's timing offset [default=%default]") + parser.add_option("-p", "--poffset", type="eng_float", default=0.0, + help="Set the simulation's phase offset [default=%default]") + (options, args) = parser.parse_args () + + # Adjust N for the interpolation by sps + options.nsamples = options.nsamples // options.sps + + # Set up the program-under-test + put = example_fll(options.nsamples, options.sps, options.rolloff, + options.ntaps, options.bandwidth, options.noise, + options.foffset, options.toffset, options.poffset) + put.run() + + data_src = scipy.array(put.vsnk_src.data()) + data_err = scipy.array(put.vsnk_err.data()) + + # Convert the FLL's LO frequency from rads/sec to Hz + data_frq = scipy.array(put.vsnk_frq.data()) / (2.0*scipy.pi) + + # adjust this to align with the data. There are 2 filters of + # ntaps long and the channel introduces another 4 sample delay. + data_fll = scipy.array(put.vsnk_fll.data()[2*options.ntaps-4:]) + + # Plot the FLL's LO frequency + f1 = pylab.figure(1, figsize=(12,10)) + s1 = f1.add_subplot(2,2,1) + s1.plot(data_frq) + s1.set_title("FLL LO") + s1.set_xlabel("Samples") + s1.set_ylabel("Frequency (normalized Hz)") + + # Plot the FLL's error + s2 = f1.add_subplot(2,2,2) + s2.plot(data_err) + s2.set_title("FLL Error") + s2.set_xlabel("Samples") + s2.set_ylabel("FLL Loop error") + + # Plot the IQ symbols + s3 = f1.add_subplot(2,2,3) + s3.plot(data_src.real, data_src.imag, "o") + s3.plot(data_fll.real, data_fll.imag, "rx") + s3.set_title("IQ") + s3.set_xlabel("Real part") + s3.set_ylabel("Imag part") + + # Plot the symbols in time + s4 = f1.add_subplot(2,2,4) + s4.plot(data_src.real, "o-") + s4.plot(data_fll.real, "rx-") + s4.set_title("Symbols") + s4.set_xlabel("Samples") + s4.set_ylabel("Real Part of Signals") + + pylab.show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-digital/examples/example_timing.py b/gr-digital/examples/example_timing.py new file mode 100755 index 0000000000..fd86acfb16 --- /dev/null +++ b/gr-digital/examples/example_timing.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python + +from gnuradio import gr, digital +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +try: + import scipy +except ImportError: + print "Error: could not import scipy (http://www.scipy.org/)" + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + sys.exit(1) + +from scipy import fftpack + +class example_timing(gr.top_block): + def __init__(self, N, sps, rolloff, ntaps, bw, noise, + foffset, toffset, poffset, mode=0): + gr.top_block.__init__(self) + + rrc_taps = gr.firdes.root_raised_cosine( + sps, sps, 1.0, rolloff, ntaps) + + gain = 2*scipy.pi/100.0 + nfilts = 32 + rrc_taps_rx = gr.firdes.root_raised_cosine( + nfilts, sps*nfilts, 1.0, rolloff, ntaps*nfilts) + + data = 2.0*scipy.random.randint(0, 2, N) - 1.0 + data = scipy.exp(1j*poffset) * data + + self.src = gr.vector_source_c(data.tolist(), False) + self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps) + self.chn = gr.channel_model(noise, foffset, toffset) + self.off = gr.fractional_interpolator_cc(0.20, 1.0) + + if mode == 0: + self.clk = gr.pfb_clock_sync_ccf(sps, gain, rrc_taps_rx, + nfilts, nfilts//2, 3.5) + self.taps = self.clk.get_taps() + self.dtaps = self.clk.get_diff_taps() + + self.vsnk_err = gr.vector_sink_f() + self.vsnk_rat = gr.vector_sink_f() + self.vsnk_phs = gr.vector_sink_f() + + self.connect((self.clk,1), self.vsnk_err) + self.connect((self.clk,2), self.vsnk_rat) + self.connect((self.clk,3), self.vsnk_phs) + + else: # mode == 1 + mu = 0.5 + gain_mu = 0.1 + gain_omega = 0.25*gain_mu*gain_mu + omega_rel_lim = 0.02 + self.clk = digital.clock_recovery_mm_cc(sps, gain_omega, + mu, gain_mu, + omega_rel_lim) + + self.vsnk_err = gr.vector_sink_f() + + self.connect((self.clk,1), self.vsnk_err) + + self.vsnk_src = gr.vector_sink_c() + self.vsnk_clk = gr.vector_sink_c() + + self.connect(self.src, self.rrc, self.chn, self.off, self.clk, self.vsnk_clk) + self.connect(self.off, self.vsnk_src) + + +def main(): + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=2000, + help="Set the number of samples to process [default=%default]") + parser.add_option("-S", "--sps", type="int", default=4, + help="Set the samples per symbol [default=%default]") + parser.add_option("-r", "--rolloff", type="eng_float", default=0.35, + help="Set the rolloff factor [default=%default]") + parser.add_option("-W", "--bandwidth", type="eng_float", default=2*scipy.pi/100.0, + help="Set the loop bandwidth [default=%default]") + parser.add_option("-n", "--ntaps", type="int", default=45, + help="Set the number of taps in the filters [default=%default]") + parser.add_option("", "--noise", type="eng_float", default=0.0, + help="Set the simulation noise voltage [default=%default]") + parser.add_option("-f", "--foffset", type="eng_float", default=0.0, + help="Set the simulation's normalized frequency offset (in Hz) [default=%default]") + parser.add_option("-t", "--toffset", type="eng_float", default=1.0, + help="Set the simulation's timing offset [default=%default]") + parser.add_option("-p", "--poffset", type="eng_float", default=0.0, + help="Set the simulation's phase offset [default=%default]") + parser.add_option("-M", "--mode", type="int", default=0, + help="Set the recovery mode (0: polyphase, 1: M&M) [default=%default]") + (options, args) = parser.parse_args () + + # Adjust N for the interpolation by sps + options.nsamples = options.nsamples // options.sps + + # Set up the program-under-test + put = example_timing(options.nsamples, options.sps, options.rolloff, + options.ntaps, options.bandwidth, options.noise, + options.foffset, options.toffset, options.poffset, + options.mode) + put.run() + + if options.mode == 0: + data_src = scipy.array(put.vsnk_src.data()[20:]) + data_clk = scipy.array(put.vsnk_clk.data()[20:]) + + data_err = scipy.array(put.vsnk_err.data()[20:]) + data_rat = scipy.array(put.vsnk_rat.data()[20:]) + data_phs = scipy.array(put.vsnk_phs.data()[20:]) + + f1 = pylab.figure(1, figsize=(12,10), facecolor='w') + + # Plot the IQ symbols + s1 = f1.add_subplot(2,2,1) + s1.plot(data_src.real, data_src.imag, "bo") + s1.plot(data_clk.real, data_clk.imag, "ro") + s1.set_title("IQ") + s1.set_xlabel("Real part") + s1.set_ylabel("Imag part") + s1.set_xlim([-2, 2]) + s1.set_ylim([-2, 2]) + + # Plot the symbols in time + s2 = f1.add_subplot(2,2,2) + s2.plot(data_src.real, "bo-") + s2.plot(data_clk.real, "ro") + s2.set_title("Symbols") + s2.set_xlabel("Samples") + s2.set_ylabel("Real Part of Signals") + + # Plot the clock recovery loop's error + s3 = f1.add_subplot(2,2,3) + s3.plot(data_err) + s3.set_title("Clock Recovery Loop Error") + s3.set_xlabel("Samples") + s3.set_ylabel("Error") + + # Plot the clock recovery loop's error + s4 = f1.add_subplot(2,2,4) + s4.plot(data_phs) + s4.set_title("Clock Recovery Loop Filter Phase") + s4.set_xlabel("Samples") + s4.set_ylabel("Filter Phase") + + + diff_taps = put.dtaps + ntaps = len(diff_taps[0]) + nfilts = len(diff_taps) + t = scipy.arange(0, ntaps*nfilts) + + f3 = pylab.figure(3, figsize=(12,10), facecolor='w') + s31 = f3.add_subplot(2,1,1) + s32 = f3.add_subplot(2,1,2) + s31.set_title("Differential Filters") + s32.set_title("FFT of Differential Filters") + + for i,d in enumerate(diff_taps): + D = 20.0*scipy.log10(abs(fftpack.fftshift(fftpack.fft(d, 10000)))) + s31.plot(t[i::nfilts].real, d, "-o") + s32.plot(D) + + # If testing the M&M clock recovery loop + else: + data_src = scipy.array(put.vsnk_src.data()[20:]) + data_clk = scipy.array(put.vsnk_clk.data()[20:]) + + data_err = scipy.array(put.vsnk_err.data()[20:]) + + f1 = pylab.figure(1, figsize=(12,10), facecolor='w') + + # Plot the IQ symbols + s1 = f1.add_subplot(2,2,1) + s1.plot(data_src.real, data_src.imag, "o") + s1.plot(data_clk.real, data_clk.imag, "ro") + s1.set_title("IQ") + s1.set_xlabel("Real part") + s1.set_ylabel("Imag part") + s1.set_xlim([-2, 2]) + s1.set_ylim([-2, 2]) + + # Plot the symbols in time + s2 = f1.add_subplot(2,2,2) + s2.plot(data_src.real, "o-") + s2.plot(data_clk.real, "ro") + s2.set_title("Symbols") + s2.set_xlabel("Samples") + s2.set_ylabel("Real Part of Signals") + + # Plot the clock recovery loop's error + s3 = f1.add_subplot(2,2,3) + s3.plot(data_err) + s3.set_title("Clock Recovery Loop Error") + s3.set_xlabel("Samples") + s3.set_ylabel("Error") + + pylab.show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-digital/examples/receive_path.py b/gr-digital/examples/receive_path.py new file mode 100644 index 0000000000..dd8eb1a0dd --- /dev/null +++ b/gr-digital/examples/receive_path.py @@ -0,0 +1,146 @@ +#!/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, gru +from gnuradio import eng_notation +from gnuradio import digital + +import copy +import sys + +# ///////////////////////////////////////////////////////////////////////////// +# receive path +# ///////////////////////////////////////////////////////////////////////////// + +class receive_path(gr.hier_block2): + def __init__(self, demod_class, rx_callback, options): + gr.hier_block2.__init__(self, "receive_path", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(0, 0, 0)) # Output signature + + + options = copy.copy(options) # make a copy so we can destructively modify + + self._verbose = options.verbose + self._bitrate = options.bitrate # desired bit rate + + self._rx_callback = rx_callback # this callback is fired when there's a packet available + self._demod_class = demod_class # the demodulator_class we're using + + # Get demod_kwargs + demod_kwargs = self._demod_class.extract_kwargs_from_options(options) + + # Build the demodulator + self.demodulator = self._demod_class(**demod_kwargs) + + # Design filter to get actual channel we want + sw_decim = 1 + chan_coeffs = gr.firdes.low_pass (1.0, # gain + sw_decim * self.samples_per_symbol(), # sampling rate + 1.0, # midpoint of trans. band + 0.5, # width of trans. band + gr.firdes.WIN_HANN) # filter type + self.channel_filter = gr.fft_filter_ccc(sw_decim, chan_coeffs) + + # receiver + self.packet_receiver = \ + digital.demod_pkts(self.demodulator, + access_code=None, + callback=self._rx_callback, + threshold=-1) + + # Carrier Sensing Blocks + alpha = 0.001 + thresh = 30 # in dB, will have to adjust + self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) + + # Display some information about the setup + if self._verbose: + self._print_verbage() + + # connect block input to channel filter + self.connect(self, self.channel_filter) + + # connect the channel input filter to the carrier power detector + self.connect(self.channel_filter, self.probe) + + # connect channel filter to the packet receiver + self.connect(self.channel_filter, self.packet_receiver) + + def bitrate(self): + return self._bitrate + + def samples_per_symbol(self): + return self.demodulator._samples_per_symbol + + def differential(self): + return self.demodulator._differential + + def carrier_sensed(self): + """ + Return True if we think carrier is present. + """ + #return self.probe.level() > X + return self.probe.unmuted() + + def carrier_threshold(self): + """ + Return current setting in dB. + """ + return self.probe.threshold() + + def set_carrier_threshold(self, threshold_in_db): + """ + Set carrier threshold. + + @param threshold_in_db: set detection threshold + @type threshold_in_db: float (dB) + """ + self.probe.set_threshold(threshold_in_db) + + + def add_options(normal, expert): + """ + Adds receiver-specific options to the Options Parser + """ + if not normal.has_option("--bitrate"): + normal.add_option("-r", "--bitrate", type="eng_float", default=100e3, + help="specify bitrate [default=%default].") + normal.add_option("-v", "--verbose", action="store_true", default=False) + expert.add_option("-S", "--samples-per-symbol", type="float", default=None, + help="set samples/symbol [default=%default]") + expert.add_option("", "--log", action="store_true", default=False, + help="Log all parts of flow graph to files (CAUTION: lots of data)") + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + + def _print_verbage(self): + """ + Prints information about the receive path + """ + print "\nReceive Path:" + print "modulation: %s" % (self._demod_class.__name__) + print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) + print "samples/symbol: %.4f" % (self.samples_per_symbol()) + print "Differential: %s" % (self.differential()) diff --git a/gr-digital/examples/transmit_path.py b/gr-digital/examples/transmit_path.py new file mode 100644 index 0000000000..f22ffb3278 --- /dev/null +++ b/gr-digital/examples/transmit_path.py @@ -0,0 +1,122 @@ +# +# 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, gru +from gnuradio import eng_notation +from gnuradio import digital + +import copy +import sys + +# ///////////////////////////////////////////////////////////////////////////// +# transmit path +# ///////////////////////////////////////////////////////////////////////////// + +class transmit_path(gr.hier_block2): + def __init__(self, modulator_class, options): + ''' + See below for what options should hold + ''' + gr.hier_block2.__init__(self, "transmit_path", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + options = copy.copy(options) # make a copy so we can destructively modify + + self._verbose = options.verbose + self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP + self._bitrate = options.bitrate # desired bit rate + + self._modulator_class = modulator_class # the modulator_class we are using + + # Get mod_kwargs + mod_kwargs = self._modulator_class.extract_kwargs_from_options(options) + + # transmitter + self.modulator = self._modulator_class(**mod_kwargs) + + self.packet_transmitter = \ + digital.mod_pkts(self.modulator, + access_code=None, + msgq_limit=4, + pad_for_usrp=True) + + self.amp = gr.multiply_const_cc(1) + self.set_tx_amplitude(self._tx_amplitude) + + # Display some information about the setup + if self._verbose: + self._print_verbage() + + # Connect components in the flowgraph + self.connect(self.packet_transmitter, self.amp, self) + + def set_tx_amplitude(self, ampl): + """ + Sets the transmit amplitude sent to the USRP in volts + @param: ampl 0 <= ampl < 1. + """ + self._tx_amplitude = max(0.0, min(ampl, 1)) + self.amp.set_k(self._tx_amplitude) + + def send_pkt(self, payload='', eof=False): + """ + Calls the transmitter method to send a packet + """ + return self.packet_transmitter.send_pkt(payload, eof) + + def bitrate(self): + return self._bitrate + + def samples_per_symbol(self): + return self.modulator._samples_per_symbol + + def differential(self): + return self.modulator._differential + + def add_options(normal, expert): + """ + Adds transmitter-specific options to the Options Parser + """ + if not normal.has_option('--bitrate'): + normal.add_option("-r", "--bitrate", type="eng_float", default=100e3, + help="specify bitrate [default=%default].") + normal.add_option("", "--tx-amplitude", type="eng_float", default=0.250, metavar="AMPL", + help="set transmitter digital amplitude: 0 <= AMPL < 1 [default=%default]") + normal.add_option("-v", "--verbose", action="store_true", default=False) + + expert.add_option("-S", "--samples-per-symbol", type="float", default=None, + help="set samples/symbol [default=%default]") + expert.add_option("", "--log", action="store_true", default=False, + help="Log all parts of flow graph to file (CAUTION: lots of data)") + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the transmit path + """ + print "Tx amplitude %s" % (self._tx_amplitude) + print "modulation: %s" % (self._modulator_class.__name__) + print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) + print "samples/symbol: %.4f" % (self.samples_per_symbol()) + print "Differential: %s" % (self.differential()) diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index 86e082b31d..30e1e3a400 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/CMakeLists.txt @@ -32,13 +32,20 @@ LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) # Setup library ######################################################################## LIST(APPEND gr_digital_sources + digital_binary_slicer_fb.cc + digital_clock_recovery_mm_cc.cc + digital_clock_recovery_mm_ff.cc digital_constellation.cc digital_constellation_receiver_cb.cc digital_constellation_decoder_cb.cc + digital_correlate_access_code_bb.cc digital_costas_loop_cc.cc digital_cma_equalizer_cc.cc + digital_crc32.cc + digital_fll_band_edge_cc.cc digital_lms_dd_equalizer_cc.cc digital_kurtotic_equalizer_cc.cc + digital_mpsk_receiver_cc.cc ) LIST(APPEND digital_libs @@ -62,14 +69,21 @@ INSTALL(TARGETS gnuradio-digital ######################################################################## INSTALL(FILES digital_api.h + digital_binary_slicer_fb.h + digital_clock_recovery_mm_cc.h + digital_clock_recovery_mm_ff.h digital_constellation.h digital_constellation_receiver_cb.h digital_constellation_decoder_cb.h + digital_correlate_access_code_bb.h digital_costas_loop_cc.h digital_cma_equalizer_cc.h + digital_crc32.h + digital_fll_band_edge_cc.h digital_lms_dd_equalizer_cc.h digital_kurtotic_equalizer_cc.h digital_metric_type.h + digital_mpsk_receiver_cc.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "digital_devel" ) diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am index 1cdb27a389..4a9359fce2 100644 --- a/gr-digital/lib/Makefile.am +++ b/gr-digital/lib/Makefile.am @@ -26,25 +26,39 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) # These headers get installed in ${prefix}/include/gnuradio grinclude_HEADERS = \ digital_api.h \ + digital_binary_slicer_fb.h \ + digital_clock_recovery_mm_cc.h \ + digital_clock_recovery_mm_ff.h \ digital_constellation.h \ digital_constellation_receiver_cb.h \ digital_constellation_decoder_cb.h \ + digital_correlate_access_code_bb.h \ digital_costas_loop_cc.h \ digital_cma_equalizer_cc.h \ + digital_crc32.h \ + digital_fll_band_edge_cc.h \ digital_lms_dd_equalizer_cc.h \ digital_kurtotic_equalizer_cc.h \ - digital_metric_type.h + digital_metric_type.h \ + digital_mpsk_receiver_cc.h lib_LTLIBRARIES = libgnuradio-digital.la libgnuradio_digital_la_SOURCES = \ + digital_binary_slicer_fb.cc \ + digital_clock_recovery_mm_cc.cc \ + digital_clock_recovery_mm_ff.cc \ digital_constellation.cc \ digital_constellation_receiver_cb.cc \ digital_constellation_decoder_cb.cc \ + digital_correlate_access_code_bb.cc \ digital_costas_loop_cc.cc \ digital_cma_equalizer_cc.cc \ + digital_crc32.cc \ + digital_fll_band_edge_cc.cc \ digital_lms_dd_equalizer_cc.cc \ - digital_kurtotic_equalizer_cc.cc + digital_kurtotic_equalizer_cc.cc \ + digital_mpsk_receiver_cc.cc libgnuradio_digital_la_LIBADD = \ $(GNURADIO_CORE_LA) diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc b/gr-digital/lib/digital_binary_slicer_fb.cc index ae8903abbd..fcdb4291fb 100644 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc +++ b/gr-digital/lib/digital_binary_slicer_fb.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2010 Free Software Foundation, Inc. + * Copyright 2006,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,40 +24,35 @@ #include "config.h" #endif -#include <gr_binary_slicer_fb.h> +#include <digital_binary_slicer_fb.h> #include <gr_io_signature.h> +#include <gr_math.h> #include <stdexcept> -gr_binary_slicer_fb_sptr -gr_make_binary_slicer_fb () +digital_binary_slicer_fb_sptr +digital_make_binary_slicer_fb () { - return gnuradio::get_initial_sptr(new gr_binary_slicer_fb ()); + return gnuradio::get_initial_sptr(new digital_binary_slicer_fb ()); } -gr_binary_slicer_fb::gr_binary_slicer_fb () +digital_binary_slicer_fb::digital_binary_slicer_fb () : gr_sync_block ("binary_slicer_fb", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (1, 1, sizeof (unsigned char))) { } -static inline int -slice(float x) -{ - return x < 0 ? 0 : 1; -} - int -gr_binary_slicer_fb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +digital_binary_slicer_fb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const float *in = (const float *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; for (int i = 0; i < noutput_items; i++){ - out[i] = slice(in[i]); + out[i] = gr_binary_slicer(in[i]); } return noutput_items; diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h b/gr-digital/lib/digital_binary_slicer_fb.h index 45d8e6213e..9da7760120 100644 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h +++ b/gr-digital/lib/digital_binary_slicer_fb.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,16 +20,16 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_BINARY_SLICER_FB_H -#define INCLUDED_GR_BINARY_SLICER_FB_H +#ifndef INCLUDED_DIGITAL_BINARY_SLICER_FB_H +#define INCLUDED_DIGITAL_BINARY_SLICER_FB_H -#include <gr_core_api.h> +#include <digital_api.h> #include <gr_sync_block.h> -class gr_binary_slicer_fb; -typedef boost::shared_ptr<gr_binary_slicer_fb> gr_binary_slicer_fb_sptr; +class digital_binary_slicer_fb; +typedef boost::shared_ptr<digital_binary_slicer_fb> digital_binary_slicer_fb_sptr; -GR_CORE_API gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); +DIGITAL_API digital_binary_slicer_fb_sptr digital_make_binary_slicer_fb (); /*! * \brief slice float binary symbol outputting 1 bit output @@ -38,10 +38,10 @@ GR_CORE_API gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); * x < 0 --> 0 * x >= 0 --> 1 */ -class GR_CORE_API gr_binary_slicer_fb : public gr_sync_block +class DIGITAL_API digital_binary_slicer_fb : public gr_sync_block { - friend GR_CORE_API gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); - gr_binary_slicer_fb (); + friend DIGITAL_API digital_binary_slicer_fb_sptr digital_make_binary_slicer_fb (); + digital_binary_slicer_fb (); public: int work (int noutput_items, diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc b/gr-digital/lib/digital_clock_recovery_mm_cc.cc index 7c20f7fd94..198eb4b890 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc +++ b/gr-digital/lib/digital_clock_recovery_mm_cc.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2006,2010 Free Software Foundation, Inc. + * Copyright 2005,2006,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,7 +26,7 @@ #include <gr_io_signature.h> #include <gr_prefs.h> -#include <gr_clock_recovery_mm_cc.h> +#include <digital_clock_recovery_mm_cc.h> #include <gri_mmse_fir_interpolator_cc.h> #include <stdexcept> #include <cstdio> @@ -35,22 +35,24 @@ // Public constructor static const int FUDGE = 16; -gr_clock_recovery_mm_cc_sptr -gr_make_clock_recovery_mm_cc(float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit) +digital_clock_recovery_mm_cc_sptr +digital_make_clock_recovery_mm_cc(float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit) { - return gnuradio::get_initial_sptr(new gr_clock_recovery_mm_cc (omega, - gain_omega, - mu, - gain_mu, - omega_relative_limit)); + return gnuradio::get_initial_sptr(new digital_clock_recovery_mm_cc (omega, + gain_omega, + mu, + gain_mu, + omega_relative_limit)); } -gr_clock_recovery_mm_cc::gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, - float gain_mu, float omega_relative_limit) +digital_clock_recovery_mm_cc::digital_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit) : gr_block ("clock_recovery_mm_cc", gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 2, sizeof (gr_complex))), + gr_make_io_signature2 (1, 2, sizeof (gr_complex), sizeof(float))), d_mu (mu), d_omega(omega), d_gain_omega(gain_omega), d_omega_relative_limit(omega_relative_limit), d_gain_mu(gain_mu), d_last_sample(0), d_interp(new gri_mmse_fir_interpolator_cc()), @@ -67,13 +69,13 @@ gr_clock_recovery_mm_cc::gr_clock_recovery_mm_cc (float omega, float gain_omega, set_history(3); // ensure 2 extra input sample is available } -gr_clock_recovery_mm_cc::~gr_clock_recovery_mm_cc () +digital_clock_recovery_mm_cc::~digital_clock_recovery_mm_cc () { delete d_interp; } void -gr_clock_recovery_mm_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) +digital_clock_recovery_mm_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) { unsigned ninputs = ninput_items_required.size(); for (unsigned i=0; i < ninputs; i++) @@ -82,7 +84,7 @@ gr_clock_recovery_mm_cc::forecast(int noutput_items, gr_vector_int &ninput_items } gr_complex -gr_clock_recovery_mm_cc::slicer_0deg (gr_complex sample) +digital_clock_recovery_mm_cc::slicer_0deg (gr_complex sample) { float real=0, imag=0; @@ -94,7 +96,7 @@ gr_clock_recovery_mm_cc::slicer_0deg (gr_complex sample) } gr_complex -gr_clock_recovery_mm_cc::slicer_45deg (gr_complex sample) +digital_clock_recovery_mm_cc::slicer_45deg (gr_complex sample) { float real= -1, imag = -1; if(sample.real() > 0) @@ -112,14 +114,14 @@ gr_clock_recovery_mm_cc::slicer_45deg (gr_complex sample) */ int -gr_clock_recovery_mm_cc::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +digital_clock_recovery_mm_cc::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - gr_complex *foptr = (gr_complex *) output_items[1]; + float *foptr = (float *) output_items[1]; bool write_foptr = output_items.size() >= 2; @@ -151,7 +153,7 @@ gr_clock_recovery_mm_cc::general_work (int noutput_items, out[oo++] = d_p_0T; // limit mm_val - mm_val = gr_branchless_clip(mm_val,1.0); + mm_val = gr_branchless_clip(mm_val,4.0); d_omega = d_omega + d_gain_omega * mm_val; d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_relative_limit); // make sure we don't walk away @@ -160,7 +162,7 @@ gr_clock_recovery_mm_cc::general_work (int noutput_items, d_mu -= floor(d_mu); // write the error signal to the second output - foptr[oo-1] = gr_complex(d_mu,0); + foptr[oo-1] = mm_val; if (ii < 0) // clamp it. This should only happen with bogus input ii = 0; diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h b/gr-digital/lib/digital_clock_recovery_mm_cc.h index 292b066dc3..e45b79229d 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h +++ b/gr-digital/lib/digital_clock_recovery_mm_cc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,23 +20,24 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_CLOCK_RECOVERY_MM_CC_H -#define INCLUDED_GR_CLOCK_RECOVERY_MM_CC_H +#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H +#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_CC_H -#include <gr_core_api.h> +#include <digital_api.h> #include <gr_block.h> #include <gr_complex.h> #include <gr_math.h> class gri_mmse_fir_interpolator_cc; -class gr_clock_recovery_mm_cc; -typedef boost::shared_ptr<gr_clock_recovery_mm_cc> gr_clock_recovery_mm_cc_sptr; +class digital_clock_recovery_mm_cc; +typedef boost::shared_ptr<digital_clock_recovery_mm_cc> digital_clock_recovery_mm_cc_sptr; // public constructor -GR_CORE_API gr_clock_recovery_mm_cc_sptr -gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit=0.001); +DIGITAL_API digital_clock_recovery_mm_cc_sptr +digital_make_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit=0.001); /*! * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output. @@ -49,10 +50,10 @@ gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gai * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller * algorithm," Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033. */ -class GR_CORE_API gr_clock_recovery_mm_cc : public gr_block +class DIGITAL_API digital_clock_recovery_mm_cc : public gr_block { public: - ~gr_clock_recovery_mm_cc (); + ~digital_clock_recovery_mm_cc (); void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work (int noutput_items, gr_vector_int &ninput_items, @@ -75,8 +76,9 @@ class GR_CORE_API gr_clock_recovery_mm_cc : public gr_block } protected: - gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limi); + digital_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limi); private: float d_mu; @@ -102,9 +104,10 @@ protected: gr_complex slicer_0deg (gr_complex sample); gr_complex slicer_45deg (gr_complex sample); - friend GR_CORE_API gr_clock_recovery_mm_cc_sptr - gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit); + friend DIGITAL_API digital_clock_recovery_mm_cc_sptr + digital_make_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit); }; #endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc b/gr-digital/lib/digital_clock_recovery_mm_ff.cc index bb5a27071d..04057f0e94 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc +++ b/gr-digital/lib/digital_clock_recovery_mm_ff.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2010 Free Software Foundation, Inc. + * Copyright 2004,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,7 +25,7 @@ #endif #include <gr_io_signature.h> -#include <gr_clock_recovery_mm_ff.h> +#include <digital_clock_recovery_mm_ff.h> #include <gri_mmse_fir_interpolator.h> #include <stdexcept> @@ -33,19 +33,21 @@ // Public constructor -gr_clock_recovery_mm_ff_sptr -gr_make_clock_recovery_mm_ff(float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit) +digital_clock_recovery_mm_ff_sptr +digital_make_clock_recovery_mm_ff(float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit) { - return gnuradio::get_initial_sptr(new gr_clock_recovery_mm_ff (omega, - gain_omega, - mu, - gain_mu, - omega_relative_limit)); + return gnuradio::get_initial_sptr(new digital_clock_recovery_mm_ff (omega, + gain_omega, + mu, + gain_mu, + omega_relative_limit)); } -gr_clock_recovery_mm_ff::gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit) +digital_clock_recovery_mm_ff::digital_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit) : gr_block ("clock_recovery_mm_ff", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (1, 1, sizeof (float))), @@ -65,7 +67,7 @@ gr_clock_recovery_mm_ff::gr_clock_recovery_mm_ff (float omega, float gain_omega, d_logfile = fopen("cr_mm_ff.dat", "wb"); } -gr_clock_recovery_mm_ff::~gr_clock_recovery_mm_ff () +digital_clock_recovery_mm_ff::~digital_clock_recovery_mm_ff () { delete d_interp; @@ -76,7 +78,7 @@ gr_clock_recovery_mm_ff::~gr_clock_recovery_mm_ff () } void -gr_clock_recovery_mm_ff::forecast(int noutput_items, gr_vector_int &ninput_items_required) +digital_clock_recovery_mm_ff::forecast(int noutput_items, gr_vector_int &ninput_items_required) { unsigned ninputs = ninput_items_required.size(); for (unsigned i=0; i < ninputs; i++) @@ -98,10 +100,10 @@ slice(float x) * ISBN 0-471-50275-8. */ int -gr_clock_recovery_mm_ff::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +digital_clock_recovery_mm_ff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const float *in = (const float *) input_items[0]; float *out = (float *) output_items[0]; diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h b/gr-digital/lib/digital_clock_recovery_mm_ff.h index 2b33463380..6f88a4dcd0 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h +++ b/gr-digital/lib/digital_clock_recovery_mm_ff.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,23 +20,24 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_CLOCK_RECOVERY_MM_FF_H -#define INCLUDED_GR_CLOCK_RECOVERY_MM_FF_H +#ifndef INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H +#define INCLUDED_DIGITAL_CLOCK_RECOVERY_MM_FF_H -#include <gr_core_api.h> +#include <digital_api.h> #include <gr_block.h> #include <gr_math.h> #include <stdio.h> class gri_mmse_fir_interpolator; -class gr_clock_recovery_mm_ff; -typedef boost::shared_ptr<gr_clock_recovery_mm_ff> gr_clock_recovery_mm_ff_sptr; +class digital_clock_recovery_mm_ff; +typedef boost::shared_ptr<digital_clock_recovery_mm_ff> digital_clock_recovery_mm_ff_sptr; // public constructor -GR_CORE_API gr_clock_recovery_mm_ff_sptr -gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit=0.001); +DIGITAL_API digital_clock_recovery_mm_ff_sptr +digital_make_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit=0.001); /*! * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output. @@ -48,10 +49,10 @@ gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gai * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. * ISBN 0-471-50275-8. */ -class GR_CORE_API gr_clock_recovery_mm_ff : public gr_block +class DIGITAL_API digital_clock_recovery_mm_ff : public gr_block { public: - ~gr_clock_recovery_mm_ff (); + ~digital_clock_recovery_mm_ff (); void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work (int noutput_items, gr_vector_int &ninput_items, @@ -73,7 +74,7 @@ class GR_CORE_API gr_clock_recovery_mm_ff : public gr_block } protected: - gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + digital_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, float omega_relative_limit); private: @@ -89,9 +90,10 @@ protected: FILE *d_logfile; float d_omega_relative_limit; // used to compute min and max omega - friend GR_CORE_API gr_clock_recovery_mm_ff_sptr - gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit); + friend DIGITAL_API digital_clock_recovery_mm_ff_sptr + digital_make_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit); }; #endif diff --git a/gr-digital/lib/digital_constellation_receiver_cb.cc b/gr-digital/lib/digital_constellation_receiver_cb.cc index 573c4e855e..e2b6bf1d80 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.cc +++ b/gr-digital/lib/digital_constellation_receiver_cb.cc @@ -40,28 +40,151 @@ digital_constellation_receiver_cb_sptr digital_make_constellation_receiver_cb(digital_constellation_sptr constell, - float alpha, float beta, - float fmin, float fmax) + float loop_bw, float fmin, float fmax) { return gnuradio::get_initial_sptr(new digital_constellation_receiver_cb (constell, - alpha, beta, + loop_bw, fmin, fmax)); } static int ios[] = {sizeof(char), sizeof(float), sizeof(float), sizeof(float)}; static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); digital_constellation_receiver_cb::digital_constellation_receiver_cb (digital_constellation_sptr constellation, - float alpha, float beta, - float fmin, float fmax) + float loop_bw, float fmin, float fmax) : gr_block ("constellation_receiver_cb", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signaturev (1, 4, iosig)), - d_alpha(alpha), d_beta(beta), d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0), + d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0), d_constellation(constellation), d_current_const_point(0) { if (d_constellation->dimensionality() != 1) throw std::runtime_error ("This receiver only works with constellations of dimension 1."); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); +} + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + +void +digital_constellation_receiver_cb::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("digital_constellation_receiver_cb: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +digital_constellation_receiver_cb::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("digital_constellation_receiver_cb: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +digital_constellation_receiver_cb::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("digital_constellation_receiver_cb: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +digital_constellation_receiver_cb::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("digital_constellation_receiver_cb: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +void +digital_constellation_receiver_cb::set_frequency(float freq) +{ + if(freq > d_max_freq) + d_freq = d_min_freq; + else if(freq < d_min_freq) + d_freq = d_max_freq; + else + d_freq = freq; +} + +void +digital_constellation_receiver_cb::set_phase(float phase) +{ + d_phase = phase; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +digital_constellation_receiver_cb::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +digital_constellation_receiver_cb::get_damping_factor() const +{ + return d_damping; +} + +float +digital_constellation_receiver_cb::get_alpha() const +{ + return d_alpha; +} + +float +digital_constellation_receiver_cb::get_beta() const +{ + return d_beta; +} + +float +digital_constellation_receiver_cb::get_frequency() const +{ + return d_freq; +} + +float +digital_constellation_receiver_cb::get_phase() const +{ + return d_phase; +} + +/******************************************************************* +*******************************************************************/ + +void +digital_constellation_receiver_cb::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; } void diff --git a/gr-digital/lib/digital_constellation_receiver_cb.h b/gr-digital/lib/digital_constellation_receiver_cb.h index 36169d76b5..11eb96cda9 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.h +++ b/gr-digital/lib/digital_constellation_receiver_cb.h @@ -24,7 +24,6 @@ #define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H #include <digital_api.h> -#include <gruel/attributes.h> #include <gr_block.h> #include <digital_constellation.h> #include <gr_complex.h> @@ -37,8 +36,7 @@ typedef boost::shared_ptr<digital_constellation_receiver_cb> digital_constellati // public constructor DIGITAL_API digital_constellation_receiver_cb_sptr digital_make_constellation_receiver_cb (digital_constellation_sptr constellation, - float alpha, float beta, - float fmin, float fmax); + float loop_bw, float fmin, float fmax); /*! * \brief This block takes care of receiving generic modulated signals through phase, frequency, and symbol @@ -75,31 +73,124 @@ class DIGITAL_API digital_constellation_receiver_cb : public gr_block gr_vector_void_star &output_items); - // Member function related to the phase/frequency tracking portion of the receiver - //! (CL) Returns the value for alpha (the phase gain term) - float alpha() const { return d_alpha; } - - //! (CL) Returns the value of beta (the frequency gain term) - float beta() const { return d_beta; } + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ - //! (CL) Returns the current value of the frequency of the NCO in the Costas loop - float freq() const { return d_freq; } + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); - //! (CL) Returns the current value of the phase of the NCO in the Costal loop - float phase() const { return d_phase; } + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); - //! (CL) Sets the value for alpha (the phase gain term) - void set_alpha(float alpha) { d_alpha = alpha; } - - //! (CL) Setss the value of beta (the frequency gain term) - void set_beta(float beta) { d_beta = beta; } + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); - //! (CL) Sets the current value of the frequency of the NCO in the Costas loop - void set_freq(float freq) { d_freq = freq; } + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); - //! (CL) Setss the current value of the phase of the NCO in the Costal loop - void set_phase(float phase) { d_phase = phase; } + /*! + * \brief Set the phase/freq recovery loop's frequency. + * + * Set's the phase/freq recovery loop's frequency. While this is normally + * updated by the inner loop of the algorithm, it could be useful to + * manually initialize, set, or reset this under certain circumstances. + * + * \param freq (float) new frequency + * + */ + void set_frequency(float freq); + /*! + * \brief Set the phase/freq recovery loop's phase. + * + * Set's the phase/freq recovery loop's phase. While this is normally + * updated by the inner loop of the algorithm, it could be useful to + * manually initialize, set, or reset this under certain circumstances. + * + * \param phase (float) new phase + * + */ + void set_phase(float phase); + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Get the phase/freq recovery loop's frequency estimate + */ + float get_frequency() const; + + /*! + * \brief Get the phase/freq loop's phase estimate + */ + float get_phase() const; protected: @@ -116,8 +207,7 @@ protected: * work loop based on the value of M. */ digital_constellation_receiver_cb (digital_constellation_sptr constellation, - float alpha, float beta, - float fmin, float fmax); + float loop_bw, float fmin, float fmax); void phase_error_tracking(float phase_error); @@ -125,11 +215,14 @@ protected: unsigned int d_M; // Members related to carrier and phase tracking - float d_alpha; - float d_beta; float d_freq, d_max_freq, d_min_freq; float d_phase; + float d_loop_bw; + float d_damping; + float d_alpha; + float d_beta; + digital_constellation_sptr d_constellation; unsigned int d_current_const_point; @@ -137,15 +230,23 @@ protected: static const unsigned int DLLEN = 8; //! delay line plus some length for overflow protection - __GR_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN]; + gr_complex d_dl[2*DLLEN] __attribute__ ((aligned(8))); //! index to delay line unsigned int d_dl_idx; + /*! \brief update the system gains from the loop bandwidth and damping factor + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); + friend DIGITAL_API digital_constellation_receiver_cb_sptr digital_make_constellation_receiver_cb (digital_constellation_sptr constell, - float alpha, float beta, - float fmin, float fmax); + float loop_bw, float fmin, float fmax); }; #endif diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc b/gr-digital/lib/digital_correlate_access_code_bb.cc index 15f6734111..f21b57d92c 100644 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc +++ b/gr-digital/lib/digital_correlate_access_code_bb.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2006,2010 Free Software Foundation, Inc. + * Copyright 2004,2006,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,7 +24,7 @@ #include "config.h" #endif -#include <gr_correlate_access_code_bb.h> +#include <digital_correlate_access_code_bb.h> #include <gr_io_signature.h> #include <stdexcept> #include <gr_count_bits.h> @@ -34,14 +34,15 @@ #define VERBOSE 0 -gr_correlate_access_code_bb_sptr -gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) +digital_correlate_access_code_bb_sptr +digital_make_correlate_access_code_bb (const std::string &access_code, int threshold) { - return gnuradio::get_initial_sptr(new gr_correlate_access_code_bb (access_code, threshold)); + return gnuradio::get_initial_sptr(new digital_correlate_access_code_bb + (access_code, threshold)); } -gr_correlate_access_code_bb::gr_correlate_access_code_bb ( +digital_correlate_access_code_bb::digital_correlate_access_code_bb ( const std::string &access_code, int threshold) : gr_sync_block ("correlate_access_code_bb", gr_make_io_signature (1, 1, sizeof(char)), @@ -51,17 +52,17 @@ gr_correlate_access_code_bb::gr_correlate_access_code_bb ( { if (!set_access_code(access_code)){ - fprintf(stderr, "gr_correlate_access_code_bb: access_code is > 64 bits\n"); + fprintf(stderr, "digital_correlate_access_code_bb: access_code is > 64 bits\n"); throw std::out_of_range ("access_code is > 64 bits"); } } -gr_correlate_access_code_bb::~gr_correlate_access_code_bb () +digital_correlate_access_code_bb::~digital_correlate_access_code_bb () { } bool -gr_correlate_access_code_bb::set_access_code( +digital_correlate_access_code_bb::set_access_code( const std::string &access_code) { unsigned len = access_code.length(); // # of bytes in string @@ -84,9 +85,9 @@ gr_correlate_access_code_bb::set_access_code( } int -gr_correlate_access_code_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +digital_correlate_access_code_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h b/gr-digital/lib/digital_correlate_access_code_bb.h index 8b5429e393..c4cb604288 100644 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h +++ b/gr-digital/lib/digital_correlate_access_code_bb.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2006 Free Software Foundation, Inc. + * Copyright 2005,2006,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,22 +20,22 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H -#define INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H +#ifndef INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_H +#define INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_H -#include <gr_core_api.h> +#include <digital_api.h> #include <gr_sync_block.h> #include <string> -class gr_correlate_access_code_bb; -typedef boost::shared_ptr<gr_correlate_access_code_bb> gr_correlate_access_code_bb_sptr; +class digital_correlate_access_code_bb; +typedef boost::shared_ptr<digital_correlate_access_code_bb> digital_correlate_access_code_bb_sptr; /*! * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" * \param threshold maximum number of bits that may be wrong */ -GR_CORE_API gr_correlate_access_code_bb_sptr -gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); +DIGITAL_API digital_correlate_access_code_bb_sptr +digital_make_correlate_access_code_bb (const std::string &access_code, int threshold); /*! * \brief Examine input for specified access code, one bit at a time. @@ -50,10 +50,10 @@ gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) * flag bit and is 1 if the corresponding data bit is the first data * bit following the access code. Otherwise the flag bit is 0. */ -class GR_CORE_API gr_correlate_access_code_bb : public gr_sync_block +class DIGITAL_API digital_correlate_access_code_bb : public gr_sync_block { - friend GR_CORE_API gr_correlate_access_code_bb_sptr - gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + friend DIGITAL_API digital_correlate_access_code_bb_sptr + digital_make_correlate_access_code_bb (const std::string &access_code, int threshold); private: unsigned long long d_access_code; // access code to locate start of packet // access code is left justified in the word @@ -65,10 +65,10 @@ class GR_CORE_API gr_correlate_access_code_bb : public gr_sync_block unsigned int d_threshold; // how many bits may be wrong in sync vector protected: - gr_correlate_access_code_bb(const std::string &access_code, int threshold); + digital_correlate_access_code_bb(const std::string &access_code, int threshold); public: - ~gr_correlate_access_code_bb(); + ~digital_correlate_access_code_bb(); int work(int noutput_items, gr_vector_const_void_star &input_items, @@ -81,4 +81,4 @@ class GR_CORE_API gr_correlate_access_code_bb : public gr_sync_block bool set_access_code (const std::string &access_code); }; -#endif /* INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H */ +#endif /* INCLUDED_DIGITAL_CORRELATE_ACCESS_CODE_BB_H */ diff --git a/gr-digital/lib/digital_costas_loop_cc.cc b/gr-digital/lib/digital_costas_loop_cc.cc index 5d98bde4c4..370dc7e5c1 100644 --- a/gr-digital/lib/digital_costas_loop_cc.cc +++ b/gr-digital/lib/digital_costas_loop_cc.cc @@ -30,31 +30,23 @@ #include <gr_sincos.h> #include <gr_math.h> -#define M_TWOPI (2*M_PI) - digital_costas_loop_cc_sptr -digital_make_costas_loop_cc (float damping, float nat_freq, - int order +digital_make_costas_loop_cc (float loop_bw, int order ) throw (std::invalid_argument) { - return gnuradio::get_initial_sptr(new digital_costas_loop_cc (damping, - nat_freq, - order)); + return gnuradio::get_initial_sptr(new digital_costas_loop_cc + (loop_bw, order)); } -digital_costas_loop_cc::digital_costas_loop_cc (float damping, float nat_freq, - int order +digital_costas_loop_cc::digital_costas_loop_cc (float loop_bw, int order ) throw (std::invalid_argument) : gr_sync_block ("costas_loop_cc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature2 (1, 2, sizeof (gr_complex), sizeof(float))), - d_max_freq(1.0), d_min_freq(-1.0), d_phase(0), d_freq(0.0), - d_nat_freq(nat_freq), d_damping(damping), + gri_control_loop(loop_bw, 1.0, -1.0), d_order(order), d_phase_detector(NULL) { - // initialize gains from the natural freq and damping factors - update_gains(); - + // Set up the phase detector to use based on the constellation order switch(d_order) { case 2: d_phase_detector = &digital_costas_loop_cc::phase_detector_2; @@ -115,27 +107,6 @@ digital_costas_loop_cc::phase_detector_2(gr_complex sample) const return (sample.real()*sample.imag()); } -void -digital_costas_loop_cc::set_natural_freq(float w) -{ - d_nat_freq = w; - update_gains(); -} - -void -digital_costas_loop_cc::set_damping_factor(float eta) -{ - d_damping = eta; - update_gains(); -} - -void -digital_costas_loop_cc::update_gains() -{ - d_beta = d_nat_freq*d_nat_freq; - d_alpha = 2*d_damping*d_nat_freq; -} - int digital_costas_loop_cc::work (int noutput_items, gr_vector_const_void_star &input_items, @@ -159,18 +130,9 @@ digital_costas_loop_cc::work (int noutput_items, error = (*this.*d_phase_detector)(optr[i]); error = gr_branchless_clip(error, 1.0); - d_freq = d_freq + d_beta * error; - d_phase = d_phase + d_freq + d_alpha * error; - - while(d_phase>M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase<-M_TWOPI) - d_phase += M_TWOPI; - - if (d_freq > d_max_freq) - d_freq = d_min_freq; - else if (d_freq < d_min_freq) - d_freq = d_max_freq; + advance_loop(error); + phase_wrap(); + frequency_limit(); foptr[i] = d_freq; } @@ -181,20 +143,10 @@ digital_costas_loop_cc::work (int noutput_items, error = (*this.*d_phase_detector)(optr[i]); error = gr_branchless_clip(error, 1.0); - - d_freq = d_freq + d_beta * error; - d_phase = d_phase + d_freq + d_alpha * error; - - while(d_phase>M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase<-M_TWOPI) - d_phase += M_TWOPI; - - if (d_freq > d_max_freq) - d_freq = d_min_freq; - else if (d_freq < d_min_freq) - d_freq = d_max_freq; - + + advance_loop(error); + phase_wrap(); + frequency_limit(); } } return noutput_items; diff --git a/gr-digital/lib/digital_costas_loop_cc.h b/gr-digital/lib/digital_costas_loop_cc.h index 099fca3be2..c787263410 100644 --- a/gr-digital/lib/digital_costas_loop_cc.h +++ b/gr-digital/lib/digital_costas_loop_cc.h @@ -24,8 +24,8 @@ #ifndef INCLUDED_DIGITAL_COSTAS_LOOP_CC_H #define INCLUDED_DIGITAL_COSTAS_LOOP_CC_H -#include <digital_api.h> #include <gr_sync_block.h> +#include <gri_control_loop.h> #include <stdexcept> #include <fstream> @@ -54,13 +54,15 @@ * \param min_freq the minimum frequency deviation (radians/sample) the loop can handle * \param order the loop order, either 2 or 4 */ + +#include <digital_api.h> + class digital_costas_loop_cc; typedef boost::shared_ptr<digital_costas_loop_cc> digital_costas_loop_cc_sptr; DIGITAL_API digital_costas_loop_cc_sptr -digital_make_costas_loop_cc (float damping, float nat_freq, - int order +digital_make_costas_loop_cc (float loop_bw, int order ) throw (std::invalid_argument); @@ -74,34 +76,17 @@ digital_make_costas_loop_cc (float damping, float nat_freq, * * \p order must be 2 or 4. */ -class DIGITAL_API digital_costas_loop_cc : public gr_sync_block +class DIGITAL_API digital_costas_loop_cc : public gr_sync_block, public gri_control_loop { friend DIGITAL_API digital_costas_loop_cc_sptr - digital_make_costas_loop_cc (float damping, float nat_freq, - int order + digital_make_costas_loop_cc (float loop_bw, int order ) throw (std::invalid_argument); - float d_alpha, d_beta, d_max_freq, d_min_freq, d_phase, d_freq; - float d_nat_freq, d_damping; int d_order; - digital_costas_loop_cc (float damping, float nat_freq, - int order + digital_costas_loop_cc (float loop_bw, int order ) throw (std::invalid_argument); - - /*! \brief update the system gains from omega and eta - * - * This function updates the system gains based on the natural - * frequency (omega) and damping factor (eta) of the system. - * These two factors can be set separately through their own - * set functions. - * - * These equations are summarized nicely in this paper from Berkeley: - * http://www.complextoreal.com/chapters/pll.pdf - */ - void update_gains(); - /*! \brief the phase detector circuit for 8th-order PSK loops * \param sample complex sample * \return the phase error @@ -125,27 +110,9 @@ class DIGITAL_API digital_costas_loop_cc : public gr_sync_block public: - void set_natural_freq(float w); - void set_damping_factor(float eta); - - /*! \brief get the first order gain - * - */ - float alpha() const { return d_alpha; } - - /*! \brief get the second order gain - * - */ - float beta() const { return d_beta; } - int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - - /*! \brief returns the current NCO frequency in radians/sample - * - */ - float freq() const { return d_freq; } }; #endif diff --git a/gnuradio-core/src/lib/general/gr_crc32.cc b/gr-digital/lib/digital_crc32.cc index d4e8435286..8806d6e9c7 100644 --- a/gnuradio-core/src/lib/general/gr_crc32.cc +++ b/gr-digital/lib/digital_crc32.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,13 +27,13 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <gr_crc32.h> +#include <digital_crc32.h> // Automatically generated CRC function // polynomial: 0x104C11DB7 unsigned int -gr_update_crc32(unsigned int crc, const unsigned char *data, size_t len) +digital_update_crc32(unsigned int crc, const unsigned char *data, size_t len) { static const unsigned int table[256] = { 0x00000000U,0x04C11DB7U,0x09823B6EU,0x0D4326D9U, @@ -112,19 +112,19 @@ gr_update_crc32(unsigned int crc, const unsigned char *data, size_t len) } unsigned int -gr_update_crc32(unsigned int crc, const std::string s) +digital_update_crc32(unsigned int crc, const std::string s) { - return gr_update_crc32(crc, (const unsigned char *) s.data(), s.size()); + return digital_update_crc32(crc, (const unsigned char *) s.data(), s.size()); } unsigned int -gr_crc32(const unsigned char *buf, size_t len) +digital_crc32(const unsigned char *buf, size_t len) { - return gr_update_crc32(0xffffffff, buf, len) ^ 0xffffffff; + return digital_update_crc32(0xffffffff, buf, len) ^ 0xffffffff; } unsigned int -gr_crc32(const std::string s) +digital_crc32(const std::string s) { - return gr_crc32((const unsigned char *) s.data(), s.size()); + return digital_crc32((const unsigned char *) s.data(), s.size()); } diff --git a/gnuradio-core/src/lib/general/gr_crc32.h b/gr-digital/lib/digital_crc32.h index b59bf9cdcf..852d06f49f 100644 --- a/gnuradio-core/src/lib/general/gr_crc32.h +++ b/gr-digital/lib/digital_crc32.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,10 +20,10 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_CRC32_H -#define INCLUDED_GR_CRC32_H +#ifndef INCLUDED_DIGITAL_CRC32_H +#define INCLUDED_DIGITAL_CRC32_H -#include <gr_core_api.h> +#include <digital_api.h> #include <string> #include <gr_types.h> @@ -36,16 +36,16 @@ * complement of the final running CRC. The resulting CRC should be * transmitted in big endian order. */ -GR_CORE_API unsigned int -gr_update_crc32(unsigned int crc, const unsigned char *buf, size_t len); +DIGITAL_API unsigned int +digital_update_crc32(unsigned int crc, const unsigned char *buf, size_t len); -GR_CORE_API unsigned int -gr_update_crc32(unsigned int crc, const std::string buf); +DIGITAL_API unsigned int +digital_update_crc32(unsigned int crc, const std::string buf); -GR_CORE_API unsigned int -gr_crc32(const unsigned char *buf, size_t len); +DIGITAL_API unsigned int +digital_crc32(const unsigned char *buf, size_t len); -GR_CORE_API unsigned int -gr_crc32(const std::string buf); +DIGITAL_API unsigned int +digital_crc32(const std::string buf); #endif /* INCLUDED_CRC32_H */ diff --git a/gr-digital/lib/digital_fll_band_edge_cc.cc b/gr-digital/lib/digital_fll_band_edge_cc.cc new file mode 100644 index 0000000000..70cb543519 --- /dev/null +++ b/gr-digital/lib/digital_fll_band_edge_cc.cc @@ -0,0 +1,390 @@ +/* -*- 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 <digital_fll_band_edge_cc.h> +#include <gr_io_signature.h> +#include <gr_expj.h> +#include <cstdio> + +#define M_TWOPI (2*M_PI) + +float sinc(float x) +{ + if(x == 0) + return 1; + else + return sin(M_PI*x)/(M_PI*x); +} + +digital_fll_band_edge_cc_sptr +digital_make_fll_band_edge_cc (float samps_per_sym, float rolloff, + int filter_size, float bandwidth) +{ + return gnuradio::get_initial_sptr(new digital_fll_band_edge_cc (samps_per_sym, rolloff, + filter_size, bandwidth)); +} + + +static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +digital_fll_band_edge_cc::digital_fll_band_edge_cc (float samps_per_sym, float rolloff, + int filter_size, float bandwidth) + : gr_sync_block ("fll_band_edge_cc", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false) +{ + // Initialize samples per symbol + if(samps_per_sym <= 0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid number of sps. Must be > 0."); + } + d_sps = samps_per_sym; + + // Initialize rolloff factor + if(rolloff < 0 || rolloff > 1.0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1]."); + } + d_rolloff = rolloff; + + // Initialize filter length + if(filter_size <= 0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid filter size. Must be > 0."); + } + d_filter_size = filter_size; + + // base this on the number of samples per symbol + d_max_freq = M_TWOPI * (2.0/samps_per_sym); + d_min_freq = -M_TWOPI * (2.0/samps_per_sym); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(bandwidth); + + // Build the band edge filters + design_filter(d_sps, d_rolloff, d_filter_size); + + // Initialize loop values + d_freq = 0; + d_phase = 0; +} + +digital_fll_band_edge_cc::~digital_fll_band_edge_cc () +{ +} + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +digital_fll_band_edge_cc::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +digital_fll_band_edge_cc::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +digital_fll_band_edge_cc::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +digital_fll_band_edge_cc::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +void +digital_fll_band_edge_cc::set_samples_per_symbol(float sps) +{ + if(sps <= 0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid number of sps. Must be > 0."); + } + d_sps = sps; + design_filter(d_sps, d_rolloff, d_filter_size); +} + +void +digital_fll_band_edge_cc::set_rolloff(float rolloff) +{ + if(rolloff < 0 || rolloff > 1.0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1]."); + } + d_rolloff = rolloff; + design_filter(d_sps, d_rolloff, d_filter_size); +} + +void +digital_fll_band_edge_cc::set_filter_size(int filter_size) +{ + if(filter_size <= 0) { + throw std::out_of_range ("digital_fll_band_edge_cc: invalid filter size. Must be > 0."); + } + d_filter_size = filter_size; + design_filter(d_sps, d_rolloff, d_filter_size); +} + +void +digital_fll_band_edge_cc::set_frequency(float freq) +{ + if(freq > d_max_freq) + d_freq = d_min_freq; + else if(freq < d_min_freq) + d_freq = d_max_freq; + else + d_freq = freq; +} + +void +digital_fll_band_edge_cc::set_phase(float phase) +{ + d_phase = phase; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +digital_fll_band_edge_cc::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +digital_fll_band_edge_cc::get_damping_factor() const +{ + return d_damping; +} + +float +digital_fll_band_edge_cc::get_alpha() const +{ + return d_alpha; +} + +float +digital_fll_band_edge_cc::get_beta() const +{ + return d_beta; +} + +float +digital_fll_band_edge_cc::get_samples_per_symbol() const +{ + return d_sps; +} + +float +digital_fll_band_edge_cc::get_rolloff() const +{ + return d_rolloff; +} + +int +digital_fll_band_edge_cc:: get_filter_size() const +{ + return d_filter_size; +} + +float +digital_fll_band_edge_cc::get_frequency() const +{ + return d_freq; +} + +float +digital_fll_band_edge_cc::get_phase() const +{ + return d_phase; +} + + +/******************************************************************* +*******************************************************************/ + + +void +digital_fll_band_edge_cc::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + +void +digital_fll_band_edge_cc::design_filter(float samps_per_sym, + float rolloff, int filter_size) +{ + int M = rint(filter_size / samps_per_sym); + float power = 0; + + // Create the baseband filter by adding two sincs together + std::vector<float> bb_taps; + for(int i = 0; i < filter_size; i++) { + float k = -M + i*2.0/samps_per_sym; + float tap = sinc(rolloff*k - 0.5) + sinc(rolloff*k + 0.5); + power += tap; + + bb_taps.push_back(tap); + } + + d_taps_lower.resize(filter_size); + d_taps_upper.resize(filter_size); + + // Create the band edge filters by spinning the baseband + // filter up and down to the right places in frequency. + // Also, normalize the power in the filters + int N = (bb_taps.size() - 1.0)/2.0; + for(int i = 0; i < filter_size; i++) { + float tap = bb_taps[i] / power; + + float k = (-N + (int)i)/(2.0*samps_per_sym); + + gr_complex t1 = tap * gr_expj(-M_TWOPI*(1+rolloff)*k); + gr_complex t2 = tap * gr_expj(M_TWOPI*(1+rolloff)*k); + + d_taps_lower[filter_size-i-1] = t1; + d_taps_upper[filter_size-i-1] = t2; + } + + d_updated = true; + + // Set the history to ensure enough input items for each filter + set_history(filter_size+1); +} + +void +digital_fll_band_edge_cc::print_taps() +{ + unsigned int i; + + printf("Upper Band-edge: ["); + for(i = 0; i < d_taps_upper.size(); i++) { + printf(" %.4e + %.4ej,", d_taps_upper[i].real(), d_taps_upper[i].imag()); + } + printf("]\n\n"); + + printf("Lower Band-edge: ["); + for(i = 0; i < d_taps_lower.size(); i++) { + printf(" %.4e + %.4ej,", d_taps_lower[i].real(), d_taps_lower[i].imag()); + } + printf("]\n\n"); +} + +int +digital_fll_band_edge_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + float *frq = NULL; + float *phs = NULL; + float *err = NULL; + if(output_items.size() == 4) { + frq = (float *) output_items[1]; + phs = (float *) output_items[2]; + err = (float *) output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i; + float error; + gr_complex nco_out; + gr_complex out_upper, out_lower; + for(i = 0; i < noutput_items; i++) { + nco_out = gr_expj(d_phase); + out[i+d_filter_size-1] = in[i] * nco_out; + + // Perform the dot product of the output with the filters + out_upper = 0; + out_lower = 0; + for(int k = 0; k < d_filter_size; k++) { + out_upper += d_taps_upper[k] * out[i+k]; + out_lower += d_taps_lower[k] * out[i+k]; + } + error = norm(out_lower) - norm(out_upper); + + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_freq + d_alpha * error; + + if(d_phase > M_PI) + d_phase -= M_TWOPI; + else if(d_phase < -M_PI) + d_phase += M_TWOPI; + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + + if(output_items.size() == 4) { + frq[i] = d_freq; + phs[i] = d_phase; + err[i] = error; + } + } + + return noutput_items; +} diff --git a/gr-digital/lib/digital_fll_band_edge_cc.h b/gr-digital/lib/digital_fll_band_edge_cc.h new file mode 100644 index 0000000000..c7a56a7c9c --- /dev/null +++ b/gr-digital/lib/digital_fll_band_edge_cc.h @@ -0,0 +1,323 @@ +/* -*- 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_DIGITAL_FLL_BAND_EDGE_CC_H +#define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +class digital_fll_band_edge_cc; +typedef boost::shared_ptr<digital_fll_band_edge_cc> digital_fll_band_edge_cc_sptr; +DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym, + float rolloff, + int filter_size, + float bandwidth); + +/*! + * \class digital_fll_band_edge_cc + * \brief Frequency Lock Loop using band-edge filters + * + * \ingroup general + * + * The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths + * of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth + * (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges + * is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth. + * The size of the filters should be fairly large so as to average over a number of symbols. + * + * The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively. + * These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining + * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the complex conjugate) + * provides an error signal at the DC term that is directly proportional to the carrier frequency. + * We then make a second-order loop using the error signal that is the running average of e(t). + * + * In practice, the above equation can be simplified by just comparing the absolute value squared + * of the output of both filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)). + * + * In theory, the band-edge filter is the derivative of the matched filter in frequency, + * (H_be(f) = \\frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point + * of the matched filter's rolloff (if it's a raised-cosine, the derivative of a cosine is a sine). + * Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent + * in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore + * derived from this sum of sincs. The band edge filters are then just the baseband signal + * modulated to the correct place in frequency. All of these calculations are done in the + * 'design_filter' function. + * + * Note: We use FIR filters here because the filters have to have a flat phase response over the + * entire frequency range to allow their comparisons to be valid. + * + * It is very important that the band edge filters be the derivatives of the pulse shaping filter, + * and that they be linear phase. Otherwise, the variance of the error will be very large. + * + */ + +class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block +{ + private: + /*! + * Build the FLL + * \param samps_per_sym (float) Number of samples per symbol of signal + * \param rolloff (float) Rolloff factor of signal + * \param filter_size (int) Size (in taps) of the filter + * \param bandwidth (float) Loop bandwidth + */ + friend DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym, + float rolloff, + int filter_size, + float bandwidth); + + float d_sps; + float d_rolloff; + int d_filter_size; + float d_max_freq; + float d_min_freq; + + float d_loop_bw; + float d_damping; + float d_alpha; + float d_beta; + + std::vector<gr_complex> d_taps_lower; + std::vector<gr_complex> d_taps_upper; + bool d_updated; + + float d_freq; + float d_phase; + + /*! + * Build the FLL + * \param samps_per_sym (float) number of samples per symbol + * \param rolloff (float) Rolloff (excess bandwidth) of signal filter + * \param filter_size (int) number of filter taps to generate + * \param bandwidth (float) Loop bandwidth + */ + digital_fll_band_edge_cc(float samps_per_sym, float rolloff, + int filter_size, float bandwidth); + + /*! + * \brief Update the gains, alpha and beta, of the loop filter. + */ + void update_gains(); + + /*! + * Design the band-edge filter based on the number of samples per symbol, + * filter rolloff factor, and the filter size + * + * \param samps_per_sym (float) Number of samples per symbol of signal + * \param rolloff (float) Rolloff factor of signal + * \param filter_size (int) Size (in taps) of the filter + */ + void design_filter(float samps_per_sym, float rolloff, int filter_size); + +public: + ~digital_fll_band_edge_cc (); + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); + + /*! + * \brief Set the number of samples per symbol + * + * Set's the number of samples per symbol the system should use. This value + * is uesd to calculate the filter taps and will force a recalculation. + * + * \param sps (float) new samples per symbol + * + */ + void set_samples_per_symbol(float sps); + + /*! + * \brief Set the rolloff factor of the shaping filter + * + * This sets the rolloff factor that is used in the pulse shaping filter + * and is used to calculate the filter taps. Changing this will force a + * recalculation of the filter taps. + * + * This should be the same value that is used in the transmitter's pulse + * shaping filter. It must be between 0 and 1 and is usually between + * 0.2 and 0.5 (where 0.22 and 0.35 are commonly used values). + * + * \param rolloff (float) new shaping filter rolloff factor [0,1] + * + */ + void set_rolloff(float rolloff); + + /*! + * \brief Set the number of taps in the filter + * + * This sets the number of taps in the band-edge filters. Setting this will + * force a recalculation of the filter taps. + * + * This should be about the same number of taps used in the transmitter's + * shaping filter and also not very large. A large number of taps will + * result in a large delay between input and frequency estimation, and + * so will not be as accurate. Between 30 and 70 taps is usual. + * + * \param filter_size (float) number of taps in the filters + * + */ + void set_filter_size(int filter_size); + + /*! + * \brief Set the FLL's frequency. + * + * Set's the FLL's frequency. While this is normally updated by the + * inner loop of the algorithm, it could be useful to manually initialize, + * set, or reset this under certain circumstances. + * + * \param freq (float) new frequency + * + */ + void set_frequency(float freq); + + /*! + * \brief Set the FLL's phase. + * + * Set's the FLL's phase. While this is normally updated by the + * inner loop of the algorithm, it could be useful to manually initialize, + * set, or reset this under certain circumstances. + * + * \param phase (float) new phase + * + */ + void set_phase(float phase); + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Returns the number of sampler per symbol used for the filter + */ + float get_samples_per_symbol() const; + + /*! + * \brief Returns the rolloff factor used for the filter + */ + float get_rolloff() const; + + /*! + * \brief Returns the number of taps of the filter + */ + int get_filter_size() const; + + /*! + * \brief Get the FLL's frequency estimate + */ + float get_frequency() const; + + /*! + * \brief Get the FLL's phase estimate + */ + float get_phase() const; + + /*! + * Print the taps to screen. + */ + void print_taps(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc b/gr-digital/lib/digital_mpsk_receiver_cc.cc index bc51c67693..3b2ea98404 100644 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc +++ b/gr-digital/lib/digital_mpsk_receiver_cc.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2006,2007,2010 Free Software Foundation, Inc. + * Copyright 2005,2006,2007,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,7 +26,7 @@ #include <gr_io_signature.h> #include <gr_prefs.h> -#include <gr_mpsk_receiver_cc.h> +#include <digital_mpsk_receiver_cc.h> #include <stdexcept> #include <gr_math.h> #include <gr_expj.h> @@ -39,21 +39,21 @@ // Public constructor -gr_mpsk_receiver_cc_sptr -gr_make_mpsk_receiver_cc(unsigned int M, float theta, +digital_mpsk_receiver_cc_sptr +digital_make_mpsk_receiver_cc(unsigned int M, float theta, float alpha, float beta, float fmin, float fmax, float mu, float gain_mu, float omega, float gain_omega, float omega_rel) { - return gnuradio::get_initial_sptr(new gr_mpsk_receiver_cc (M, theta, + return gnuradio::get_initial_sptr(new digital_mpsk_receiver_cc (M, theta, alpha, beta, fmin, fmax, mu, gain_mu, omega, gain_omega, omega_rel)); } -gr_mpsk_receiver_cc::gr_mpsk_receiver_cc (unsigned int M, float theta, +digital_mpsk_receiver_cc::digital_mpsk_receiver_cc (unsigned int M, float theta, float alpha, float beta, float fmin, float fmax, float mu, float gain_mu, @@ -90,29 +90,29 @@ gr_mpsk_receiver_cc::gr_mpsk_receiver_cc (unsigned int M, float theta, // Select a phase detector and a decision maker for the modulation order switch(d_M) { case 2: // optimized algorithms for BPSK - d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_bpsk; //bpsk; - d_decision = &gr_mpsk_receiver_cc::decision_bpsk; + d_phase_error_detector = &digital_mpsk_receiver_cc::phase_error_detector_bpsk; //bpsk; + d_decision = &digital_mpsk_receiver_cc::decision_bpsk; break; case 4: // optimized algorithms for QPSK - d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_qpsk; //qpsk; - d_decision = &gr_mpsk_receiver_cc::decision_qpsk; + d_phase_error_detector = &digital_mpsk_receiver_cc::phase_error_detector_qpsk; //qpsk; + d_decision = &digital_mpsk_receiver_cc::decision_qpsk; break; default: // generic algorithms for any M (power of 2?) but not pretty - d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_generic; - d_decision = &gr_mpsk_receiver_cc::decision_generic; + d_phase_error_detector = &digital_mpsk_receiver_cc::phase_error_detector_generic; + d_decision = &digital_mpsk_receiver_cc::decision_generic; break; } } -gr_mpsk_receiver_cc::~gr_mpsk_receiver_cc () +digital_mpsk_receiver_cc::~digital_mpsk_receiver_cc () { delete d_interp; } void -gr_mpsk_receiver_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) +digital_mpsk_receiver_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) { unsigned ninputs = ninput_items_required.size(); for (unsigned i=0; i < ninputs; i++) @@ -121,7 +121,7 @@ gr_mpsk_receiver_cc::forecast(int noutput_items, gr_vector_int &ninput_items_req // FIXME add these back in an test difference in performance float -gr_mpsk_receiver_cc::phase_error_detector_qpsk(gr_complex sample) const +digital_mpsk_receiver_cc::phase_error_detector_qpsk(gr_complex sample) const { float phase_error = 0; if(fabsf(sample.real()) > fabsf(sample.imag())) { @@ -141,26 +141,26 @@ gr_mpsk_receiver_cc::phase_error_detector_qpsk(gr_complex sample) const } float -gr_mpsk_receiver_cc::phase_error_detector_bpsk(gr_complex sample) const +digital_mpsk_receiver_cc::phase_error_detector_bpsk(gr_complex sample) const { return -(sample.real()*sample.imag()); } -float gr_mpsk_receiver_cc::phase_error_detector_generic(gr_complex sample) const +float digital_mpsk_receiver_cc::phase_error_detector_generic(gr_complex sample) const { //return gr_fast_atan2f(sample*conj(d_constellation[d_current_const_point])); return -arg(sample*conj(d_constellation[d_current_const_point])); } unsigned int -gr_mpsk_receiver_cc::decision_bpsk(gr_complex sample) const +digital_mpsk_receiver_cc::decision_bpsk(gr_complex sample) const { return (gr_branchless_binary_slicer(sample.real()) ^ 1); //return gr_binary_slicer(sample.real()) ^ 1; } unsigned int -gr_mpsk_receiver_cc::decision_qpsk(gr_complex sample) const +digital_mpsk_receiver_cc::decision_qpsk(gr_complex sample) const { unsigned int index; @@ -170,7 +170,7 @@ gr_mpsk_receiver_cc::decision_qpsk(gr_complex sample) const } unsigned int -gr_mpsk_receiver_cc::decision_generic(gr_complex sample) const +digital_mpsk_receiver_cc::decision_generic(gr_complex sample) const { unsigned int min_m = 0; float min_s = 65535; @@ -191,7 +191,7 @@ gr_mpsk_receiver_cc::decision_generic(gr_complex sample) const void -gr_mpsk_receiver_cc::make_constellation() +digital_mpsk_receiver_cc::make_constellation() { for(unsigned int m=0; m < d_M; m++) { d_constellation.push_back(gr_expj((M_TWOPI/d_M)*m)); @@ -199,7 +199,7 @@ gr_mpsk_receiver_cc::make_constellation() } void -gr_mpsk_receiver_cc::mm_sampler(const gr_complex symbol) +digital_mpsk_receiver_cc::mm_sampler(const gr_complex symbol) { gr_complex sample, nco; @@ -222,7 +222,7 @@ gr_mpsk_receiver_cc::mm_sampler(const gr_complex symbol) } void -gr_mpsk_receiver_cc::mm_error_tracking(gr_complex sample) +digital_mpsk_receiver_cc::mm_error_tracking(gr_complex sample) { gr_complex u, x, y; float mm_error = 0; @@ -259,7 +259,7 @@ gr_mpsk_receiver_cc::mm_error_tracking(gr_complex sample) void -gr_mpsk_receiver_cc::phase_error_tracking(gr_complex sample) +digital_mpsk_receiver_cc::phase_error_tracking(gr_complex sample) { float phase_error = 0; @@ -286,10 +286,10 @@ gr_mpsk_receiver_cc::phase_error_tracking(gr_complex sample) } int -gr_mpsk_receiver_cc::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +digital_mpsk_receiver_cc::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h b/gr-digital/lib/digital_mpsk_receiver_cc.h index 1a3f0792a4..8a6352ec7b 100644 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h +++ b/gr-digital/lib/digital_mpsk_receiver_cc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2007 Free Software Foundation, Inc. + * Copyright 2004,2007,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,27 +20,27 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_MPSK_RECEIVER_CC_H -#define INCLUDED_GR_MPSK_RECEIVER_CC_H +#ifndef INCLUDED_DIGITAL_MPSK_RECEIVER_CC_H +#define INCLUDED_DIGITAL_MPSK_RECEIVER_CC_H +#include <digital_api.h> #include <gruel/attributes.h> -#include <gr_core_api.h> #include <gr_block.h> #include <gr_complex.h> #include <fstream> class gri_mmse_fir_interpolator_cc; -class gr_mpsk_receiver_cc; -typedef boost::shared_ptr<gr_mpsk_receiver_cc> gr_mpsk_receiver_cc_sptr; +class digital_mpsk_receiver_cc; +typedef boost::shared_ptr<digital_mpsk_receiver_cc> digital_mpsk_receiver_cc_sptr; // public constructor -GR_CORE_API gr_mpsk_receiver_cc_sptr -gr_make_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, - float fmin, float fmax, - float mu, float gain_mu, - float omega, float gain_omega, float omega_rel); +DIGITAL_API digital_mpsk_receiver_cc_sptr +digital_make_mpsk_receiver_cc (unsigned int M, float theta, + float alpha, float beta, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, float omega_rel); /*! * \brief This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol @@ -71,10 +71,10 @@ gr_make_mpsk_receiver_cc (unsigned int M, float theta, * */ -class GR_CORE_API gr_mpsk_receiver_cc : public gr_block +class DIGITAL_API digital_mpsk_receiver_cc : public gr_block { public: - ~gr_mpsk_receiver_cc (); + ~digital_mpsk_receiver_cc (); void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work (int noutput_items, gr_vector_int &ninput_items, @@ -160,11 +160,11 @@ protected: * The constructor also chooses which phase detector and decision maker to use in the work loop based on the * value of M. */ - gr_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, - float fmin, float fmax, - float mu, float gain_mu, - float omega, float gain_omega, float omega_rel); + digital_mpsk_receiver_cc (unsigned int M, float theta, + float alpha, float beta, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, float omega_rel); void make_constellation(); void mm_sampler(const gr_complex symbol); @@ -271,7 +271,7 @@ protected: * * \return index into d_constellation point that is the closest to the recieved sample */ - unsigned int (gr_mpsk_receiver_cc::*d_decision)(gr_complex sample) const; // pointer to decision function + unsigned int (digital_mpsk_receiver_cc::*d_decision)(gr_complex sample) const; // pointer to decision function std::vector<gr_complex> d_constellation; @@ -291,7 +291,7 @@ protected: * This is a function pointer that is set in the constructor to point to the proper phase error detector * function for the specified constellation order. */ - float (gr_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const; + float (digital_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const; //! get interpolated value @@ -306,12 +306,12 @@ protected: //! index to delay line unsigned int d_dl_idx; - friend GR_CORE_API gr_mpsk_receiver_cc_sptr - gr_make_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, - float fmin, float fmax, - float mu, float gain_mu, - float omega, float gain_omega, float omega_rel); + friend DIGITAL_API digital_mpsk_receiver_cc_sptr + digital_make_mpsk_receiver_cc (unsigned int M, float theta, + float alpha, float beta, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, float omega_rel); }; #endif diff --git a/gr-digital/python/CMakeLists.txt b/gr-digital/python/CMakeLists.txt index 194894c73e..2d09a4945a 100644 --- a/gr-digital/python/CMakeLists.txt +++ b/gr-digital/python/CMakeLists.txt @@ -25,18 +25,19 @@ INCLUDE(GrPython) GR_PYTHON_INSTALL( FILES __init__.py + bpsk.py + cpm.py + crc.py + generic_mod_demod.py + gmsk.py + modulation_utils.py + modulation_utils2.py + packet_utils.py + pkt.py psk.py - dbpsk.py - dqpsk.py - d8psk.py psk2.py - generic_mod_demod.py qam.py - bpsk.py qpsk.py - ofdm.py - pkt.py - modulation_utils2.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital COMPONENT "digital_python" ) diff --git a/gr-digital/python/Makefile.am b/gr-digital/python/Makefile.am index 392ce45c16..6c61002f16 100644 --- a/gr-digital/python/Makefile.am +++ b/gr-digital/python/Makefile.am @@ -32,23 +32,32 @@ digitaldir = $(grpythondir)/digital noinst_PYTHON = \ qa_digital.py \ + qa_binary_slicer_fb.py \ + qa_clock_recovery_mm.py \ + qa_cma_equalizer.py \ qa_constellation.py \ qa_constellation_receiver.py \ - qa_costas_loop_cc.py + qa_constellation_decoder_cb.py \ + qa_correlate_access_code.py \ + qa_costas_loop_cc.py \ + qa_crc32.py \ + qa_fll_band_edge.py \ + qa_lms_equalizer.py \ + qa_mpsk_receiver.py digital_PYTHON = \ - __init__.py \ - psk.py \ - dbpsk.py \ - dqpsk.py \ - d8psk.py \ - psk2.py \ + __init__.py \ + bpsk.py \ + cpm.py \ + crc.py \ generic_mod_demod.py \ - qam.py \ - bpsk.py \ - qpsk.py \ - ofdm.py \ - pkt.py \ - modulation_utils2.py - + gmsk.py \ + modulation_utils.py \ + modulation_utils2.py \ + packet_utils.py \ + pkt.py \ + psk.py \ + psk2.py \ + qam.py \ + qpsk.py endif diff --git a/gr-digital/python/__init__.py b/gr-digital/python/__init__.py index 3d0be3865b..4046f7fafe 100644 --- a/gr-digital/python/__init__.py +++ b/gr-digital/python/__init__.py @@ -22,11 +22,10 @@ # The presence of this file turns this directory into a Python package from digital_swig import * -from dbpsk import * -from dqpsk import * -from d8psk import * from psk2 import * +from bpsk import * +from qpsk import * from qam import * -from ofdm import * from pkt import * -from modulation_utils2 import * +from packet_utils import * +from crc import * diff --git a/gr-digital/python/bpsk.py b/gr-digital/python/bpsk.py index 6d2eb5d6d5..58a8289a56 100644 --- a/gr-digital/python/bpsk.py +++ b/gr-digital/python/bpsk.py @@ -26,13 +26,15 @@ BPSK modulation and demodulation. from math import pi, log from cmath import exp -from gnuradio import gr, modulation_utils2 +from gnuradio import gr from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod +import digital_swig +import modulation_utils2 # Default number of points in constellation. _def_constellation_points = 2 # Whether differential coding is used. -_def_differential = True +_def_differential = False # ///////////////////////////////////////////////////////////////////////////// # BPSK constellation @@ -41,7 +43,7 @@ _def_differential = True def bpsk_constellation(m=_def_constellation_points): if m != _def_constellation_points: raise ValueError("BPSK can only have 2 constellation points.") - return gr.constellation_bpsk() + return digital_swig.constellation_bpsk() # ///////////////////////////////////////////////////////////////////////////// # BPSK modulator @@ -50,7 +52,7 @@ def bpsk_constellation(m=_def_constellation_points): class bpsk_mod(generic_mod): def __init__(self, constellation_points=_def_constellation_points, - *args, **kwargs): + differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered BPSK modulation. @@ -61,11 +63,13 @@ class bpsk_mod(generic_mod): See generic_mod block for list of parameters. """ - constellation = gr.constellation_bpsk() + constellation_points = _def_constellation_points + constellation = digital_swig.constellation_bpsk() if constellation_points != 2: raise ValueError('Number of constellation points must be 2 for BPSK.') - super(bpsk_mod, self).__init__(constellation, *args, **kwargs) - + super(bpsk_mod, self).__init__(constellation=constellation, + differential=differential, *args, **kwargs) + # ///////////////////////////////////////////////////////////////////////////// # BPSK demodulator # @@ -74,7 +78,7 @@ class bpsk_mod(generic_mod): class bpsk_demod(generic_demod): def __init__(self, constellation_points=_def_constellation_points, - *args, **kwargs): + differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered BPSK modulation. @@ -85,10 +89,76 @@ class bpsk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation = gr.constellation_bpsk() + constellation_points = _def_constellation_points + constellation = digital_swig.constellation_bpsk() if constellation_points != 2: raise ValueError('Number of constellation points must be 2 for BPSK.') - super(bpsk_demod, self).__init__(constellation, *args, **kwargs) + super(bpsk_demod, self).__init__(constellation=constellation, + differential=differential, *args, **kwargs) + + + +# ///////////////////////////////////////////////////////////////////////////// +# DBPSK constellation +# ///////////////////////////////////////////////////////////////////////////// + +def dbpsk_constellation(m=_def_constellation_points): + if m != _def_constellation_points: + raise ValueError("DBPSK can only have 2 constellation points.") + return digital_swig.constellation_dbpsk() + +# ///////////////////////////////////////////////////////////////////////////// +# DBPSK modulator +# ///////////////////////////////////////////////////////////////////////////// + +class dbpsk_mod(generic_mod): + + def __init__(self, constellation_points=_def_constellation_points, + differential=True, *args, **kwargs): + + """ + Hierarchical block for RRC-filtered DBPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + See generic_mod block for list of parameters. + """ + + constellation_points = _def_constellation_points + constellation = digital_swig.constellation_bpsk() + if constellation_points != 2: + raise ValueError('Number of constellation points must be 2 for DBPSK.') + super(dbpsk_mod, self).__init__(constellation=constellation, + differential=True, + *args, **kwargs) + +# ///////////////////////////////////////////////////////////////////////////// +# DBPSK demodulator +# +# ///////////////////////////////////////////////////////////////////////////// + +class dbpsk_demod(generic_demod): + + def __init__(self, constellation_points=_def_constellation_points, + differential=True, *args, **kwargs): + + """ + Hierarchical block for RRC-filtered DBPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + See generic_demod block for list of parameters. + """ + + constellation_points = _def_constellation_points + constellation = digital_swig.constellation_bpsk() + if constellation_points != 2: + raise ValueError('Number of constellation points must be 2 for DBPSK.') + super(dbpsk_demod, self).__init__(constellation=constellation, + differential=True, + *args, **kwargs) # # Add these to the mod/demod registry @@ -96,3 +166,6 @@ class bpsk_demod(generic_demod): modulation_utils2.add_type_1_mod('bpsk', bpsk_mod) modulation_utils2.add_type_1_demod('bpsk', bpsk_demod) modulation_utils2.add_type_1_constellation('bpsk', bpsk_constellation) +modulation_utils2.add_type_1_mod('dbpsk', dbpsk_mod) +modulation_utils2.add_type_1_demod('dbpsk', dbpsk_demod) +modulation_utils2.add_type_1_constellation('dbpsk', dbpsk_constellation) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/cpm.py b/gr-digital/python/cpm.py index 8f593cd51e..8f593cd51e 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/cpm.py +++ b/gr-digital/python/cpm.py diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/crc.py b/gr-digital/python/crc.py index d31aca0ea7..198ab059f5 100644 --- a/gnuradio-core/src/python/gnuradio/gruimpl/crc.py +++ b/gr-digital/python/crc.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2007 Free Software Foundation, Inc. +# Copyright 2005,2007,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -19,20 +19,20 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr -from hexint import * +from gnuradio import gru +import digital_swig import struct def gen_and_append_crc32(s): - crc = gr.crc32(s) - return s + struct.pack(">I", hexint(crc) & 0xFFFFFFFF) + crc = digital_swig.crc32(s) + return s + struct.pack(">I", gru.hexint(crc) & 0xFFFFFFFF) def check_crc32(s): if len(s) < 4: return (False, '') msg = s[:-4] #print "msg = '%s'" % (msg,) - actual = gr.crc32(msg) + actual = digital_swig.crc32(msg) (expected,) = struct.unpack(">I", s[-4:]) # print "actual =", hex(actual), "expected =", hex(expected) return (actual == expected, msg) diff --git a/gr-digital/python/d8psk.py b/gr-digital/python/d8psk.py index 8bed395a7f..46290faeda 100644 --- a/gr-digital/python/d8psk.py +++ b/gr-digital/python/d8psk.py @@ -310,8 +310,9 @@ class d8psk_demod(gr.hier_block2): print "Timing alpha gain: %.2f" % self._timing_alpha print "Timing beta gain: %.2f" % self._timing_beta print "Timing max dev: %.2f" % self._timing_max_dev - print "Phase track alpha: %.2e" % self._phase_alpha - print "Phase track beta: %.2e" % self._phase_beta + print "Phase damping fact: %.2e" % self._phase_damping + print "Phase natural freq: %.2e" % self._phase_natfreq + def _setup_logging(self): print "Modulation logging turned on." @@ -343,8 +344,10 @@ class d8psk_demod(gr.hier_block2): help="disable gray coding on modulated bits (PSK)") parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, help="set frequency lock loop alpha gain value [default=%default] (PSK)") - parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, - help="set phase tracking loop alpha value [default=%default] (PSK)") + parser.add_option("", "--phase-natfreq", type="float", default=_def_phase_natfreq, + help="set natural frequency of phase tracking loop [default=%default] (PSK)") + parser.add_option("", "--phase-damping", type="float", default=_def_phase_damping, + help="set damping factor of phase tracking loop [default=%default] (PSK)") parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha, help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)") parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta, diff --git a/gr-digital/python/dbpsk.py b/gr-digital/python/dbpsk.py index 2e9b756e64..9e065263f6 100644 --- a/gr-digital/python/dbpsk.py +++ b/gr-digital/python/dbpsk.py @@ -100,6 +100,7 @@ class dbpsk_mod(gr.hier_block2): self.diffenc = gr.diff_encoder_bb(arity) + self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity]) # pulse shaping filter @@ -272,9 +273,8 @@ class dbpsk_demod(gr.hier_block2): self.diffdec = gr.diff_phasor_cc() # find closest constellation point - rot = 1 - rotated_const = map(lambda pt: pt * rot, psk.constellation[arity]) - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + const = digital_swig.constellation_bpsk() + self.slicer = digital_swig.constellation_decoder_cb(const.base()) if self._gray_code: self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity]) @@ -312,8 +312,8 @@ class dbpsk_demod(gr.hier_block2): print "Timing alpha gain: %.2e" % self._timing_alpha print "Timing beta gain: %.2e" % self._timing_beta print "Timing max dev: %.2f" % self._timing_max_dev - print "Phase track alpha: %.2e" % self._phase_alpha - print "Phase track beta: %.2e" % self._phase_beta + print "Phase damping fact: %.2e" % self._phase_damping + print "Phase natural freq: %.2e" % self._phase_natfreq def _setup_logging(self): print "Modulation logging turned on." @@ -345,8 +345,10 @@ class dbpsk_demod(gr.hier_block2): help="disable gray coding on modulated bits (PSK)") parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, help="set frequency lock loop alpha gain value [default=%default] (PSK)") - parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, - help="set phase tracking loop alpha value [default=%default] (PSK)") + parser.add_option("", "--phase-natfreq", type="float", default=_def_phase_natfreq, + help="set natural frequency of phase tracking loop [default=%default] (PSK)") + parser.add_option("", "--phase-damping", type="float", default=_def_phase_damping, + help="set damping factor of phase tracking loop [default=%default] (PSK)") parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha, help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)") parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta, @@ -366,5 +368,5 @@ class dbpsk_demod(gr.hier_block2): # # Add these to the mod/demod registry # -modulation_utils2.add_type_1_mod('dbpsk3', dbpsk_mod) -modulation_utils2.add_type_1_demod('dbpsk3', dbpsk_demod) +modulation_utils2.add_type_1_mod('dbpsk', dbpsk_mod) +modulation_utils2.add_type_1_demod('dbpsk', dbpsk_demod) diff --git a/gr-digital/python/dqpsk.py b/gr-digital/python/dqpsk.py index 29afd55306..5e17d24bcc 100644 --- a/gr-digital/python/dqpsk.py +++ b/gr-digital/python/dqpsk.py @@ -315,8 +315,8 @@ class dqpsk_demod(gr.hier_block2): print "Timing alpha gain: %.2f" % self._timing_alpha print "Timing beta gain: %.2f" % self._timing_beta print "Timing max dev: %.2f" % self._timing_max_dev - print "Phase track alpha: %.2e" % self._phase_alpha - print "Phase track beta: %.2e" % self._phase_beta + print "Phase damping fact: %.2e" % self._phase_damping + print "Phase natural freq: %.2e" % self._phase_natfreq def _setup_logging(self): print "Modulation logging turned on." @@ -348,8 +348,10 @@ class dqpsk_demod(gr.hier_block2): help="disable gray coding on modulated bits (PSK)") parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, help="set frequency lock loop alpha gain value [default=%default] (PSK)") - parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, - help="set phase tracking loop alpha value [default=%default] (PSK)") + parser.add_option("", "--phase-natfreq", type="float", default=_def_phase_natfreq, + help="set natural frequency of phase tracking loop [default=%default] (PSK)") + parser.add_option("", "--phase-damping", type="float", default=_def_phase_damping, + help="set damping factor of phase tracking loop [default=%default] (PSK)") parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha, help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)") parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta, diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index f8051db0a8..da8e2cfd99 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -27,9 +27,9 @@ Generic modulation and demodulation. from gnuradio import gr from modulation_utils2 import extract_kwargs_from_options_for_class -#from gnuradio.digital.utils import mod_codes from utils import mod_codes import digital_swig +import math # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -38,17 +38,16 @@ _def_verbose = False _def_log = False # Frequency correction -_def_freq_alpha = 0.010 +_def_freq_bw = 2*math.pi/100.0 # Symbol timing recovery -_def_timing_alpha = 0.100 -_def_timing_beta = 0.010 +_def_timing_bw = 2*math.pi/100.0 _def_timing_max_dev = 1.5 # Fine frequency / Phase correction -_def_phase_alpha = 0.1 +_def_phase_bw = 2*math.pi/100.0 # Number of points in constellation _def_constellation_points = 16 # Whether differential coding is used. -_def_differential = True +_def_differential = False def add_common_options(parser): """ @@ -56,10 +55,12 @@ def add_common_options(parser): """ parser.add_option("-p", "--constellation-points", type="int", default=_def_constellation_points, help="set the number of constellation points (must be a power of 2 (power of 4 for QAM) [default=%default]") - parser.add_option("", "--differential", action="store_true", dest="differential", default=True, - help="use differential encoding [default=%default]") - parser.add_option("", "--not-differential", action="store_false", dest="differential", + parser.add_option("", "--non-differential", action="store_true", + dest="differential", default=False, help="do not use differential encoding [default=%default]") + parser.add_option("", "--differential", action="store_false", + dest="differential", + help="use differential encoding [default=False]") parser.add_option("", "--mod-code", type="choice", choices=mod_codes.codes, default=mod_codes.NO_CODE, help="Select modulation code from: %s [default=%%default]" @@ -78,6 +79,7 @@ class generic_mod(gr.hier_block2): differential=_def_differential, samples_per_symbol=_def_samples_per_symbol, excess_bw=_def_excess_bw, + gray_coded=True, verbose=_def_verbose, log=_def_log): """ @@ -89,9 +91,11 @@ class generic_mod(gr.hier_block2): @param constellation: determines the modulation type @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per baud >= 2 - @type samples_per_symbol: integer + @type samples_per_symbol: float @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float + @param gray_coded: turn gray coding on/off + @type gray_coded: bool @param verbose: Print information about modulator? @type verbose: bool @param log: Log modulation data to files? @@ -106,12 +110,10 @@ class generic_mod(gr.hier_block2): self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._differential = differential - - if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) - - ntaps = 11 * self._samples_per_symbol + if self._samples_per_symbol < 2: + raise TypeError, ("sbp must be >= 2, is %d" % self._samples_per_symbol) + arity = pow(2,self.bits_per_symbol()) # turn bytes into k-bit vectors @@ -127,14 +129,15 @@ class generic_mod(gr.hier_block2): self.chunks2symbols = gr.chunks_to_symbols_bc(self._constellation.points()) # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - self._samples_per_symbol, # gain (samples_per_symbol since we're - # interpolating by samples_per_symbol) - self._samples_per_symbol, # sampling rate - 1.0, # symbol rate - self._excess_bw, # excess bandwidth (roll-off factor) + nfilts = 32 + ntaps = nfilts * 11 * int(self._samples_per_symbol) # make nfilts filters of ntaps each + self.rrc_taps = gr.firdes.root_raised_cosine( + nfilts, # gain + nfilts, # sampling rate based on 32 filters in resampler + 1.0, # symbol rate + self._excess_bw, # excess bandwidth (roll-off factor) ntaps) - self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, + self.rrc_filter = gr.pfb_arb_resampler_ccf(self._samples_per_symbol, self.rrc_taps) # Connect @@ -182,17 +185,17 @@ class generic_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) + gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.8b")) if self._constellation.apply_pre_diff_code(): self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) + gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.8b")) if self._differential: self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) + gr.file_sink(gr.sizeof_char, "tx_diffenc.8b")) self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) + gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.32fc")) self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) + gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.32fc")) # ///////////////////////////////////////////////////////////////////////////// @@ -208,10 +211,9 @@ class generic_demod(gr.hier_block2): samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, excess_bw=_def_excess_bw, - freq_alpha=_def_freq_alpha, - timing_alpha=_def_timing_alpha, - timing_max_dev=_def_timing_max_dev, - phase_alpha=_def_phase_alpha, + freq_bw=_def_freq_bw, + timing_bw=_def_timing_bw, + phase_bw=_def_phase_bw, verbose=_def_verbose, log=_def_log): """ @@ -226,14 +228,12 @@ class generic_demod(gr.hier_block2): @type samples_per_symbol: float @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float - @param freq_alpha: loop filter gain for frequency recovery - @type freq_alpha: float - @param timing_alpha: loop alpha gain for timing recovery - @type timing_alpha: float - @param timing_max_dev: timing loop maximum rate deviations - @type timing_max_dev: float - @param phase_alpha: loop filter gain in phase loop - @type phase_alphas: float + @param freq_bw: loop filter lock-in bandwidth + @type freq_bw: float + @param timing_bw: timing recoery loop lock-in bandwidth + @type timing_bw: float + @param phase_bw: phase recovery loop bandwidth + @type phase_bw: float @param verbose: Print information about modulator? @type verbose: bool @param debug: Print modualtion data to files? @@ -247,46 +247,38 @@ class generic_demod(gr.hier_block2): self._constellation = constellation.base() self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw - self._phase_alpha = phase_alpha - self._freq_alpha = freq_alpha - self._freq_beta = 0.10*self._freq_alpha - self._timing_alpha = timing_alpha - self._timing_beta = _def_timing_beta - self._timing_max_dev=timing_max_dev + self._phase_bw = phase_bw + self._freq_bw = freq_bw + self._timing_bw = timing_bw + self._timing_max_dev= _def_timing_max_dev self._differential = differential - if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2: - raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) + if self._samples_per_symbol < 2: + raise TypeError, ("sbp must be >= 2, is %d" % self._samples_per_symbol) arity = pow(2,self.bits_per_symbol()) + nfilts = 32 + ntaps = 11 * int(self._samples_per_symbol*nfilts) + # Automatic gain control self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) # Frequency correction - self.freq_recov = gr.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, - 11*int(self._samples_per_symbol), - self._freq_alpha, self._freq_beta) + self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, + ntaps, self._freq_bw) # symbol timing recovery with RRC data filter - nfilts = 32 - ntaps = 11 * int(self._samples_per_symbol*nfilts) - taps = gr.firdes.root_raised_cosine(nfilts, nfilts, - 1.0/float(self._samples_per_symbol), - self._excess_bw, ntaps) + taps = gr.firdes.root_raised_cosine(nfilts, nfilts*self._samples_per_symbol, + 1.0, self._excess_bw, ntaps) self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, - self._timing_alpha, - taps, nfilts, nfilts/2, self._timing_max_dev) - self.time_recov.set_beta(self._timing_beta) + self._timing_bw, taps, + nfilts, nfilts//2, self._timing_max_dev) - #self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha - self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha fmin = -0.25 fmax = 0.25 - self.receiver = digital_swig.constellation_receiver_cb( - self._constellation, - self._phase_alpha, self._phase_beta, + self._constellation, self._phase_bw, fmin, fmax) # Do differential decoding based on phase change of symbols @@ -325,49 +317,46 @@ class generic_demod(gr.hier_block2): print "\nDemodulator:" print "bits per symbol: %d" % self.bits_per_symbol() print "RRC roll-off factor: %.2f" % self._excess_bw - print "FLL gain: %.2e" % self._freq_alpha - print "Timing alpha gain: %.2e" % self._timing_alpha - print "Timing beta gain: %.2e" % self._timing_beta - print "Timing max dev: %.2f" % self._timing_max_dev - print "Phase track alpha: %.2e" % self._phase_alpha - print "Phase track beta: %.2e" % self._phase_beta + print "FLL bandwidth: %.2e" % self._freq_bw + print "Timing bandwidth: %.2e" % self._timing_bw + print "Phase bandwidth: %.2e" % self._phase_bw def _setup_logging(self): print "Modulation logging turned on." self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) + gr.file_sink(gr.sizeof_gr_complex, "rx_agc.32fc")) self.connect((self.freq_recov, 0), - gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat")) + gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.32fc")) self.connect((self.freq_recov, 1), - gr.file_sink(gr.sizeof_float, "rx_freq_recov_freq.dat")) + gr.file_sink(gr.sizeof_float, "rx_freq_recov_freq.32f")) self.connect((self.freq_recov, 2), - gr.file_sink(gr.sizeof_float, "rx_freq_recov_phase.dat")) + gr.file_sink(gr.sizeof_float, "rx_freq_recov_phase.32f")) self.connect((self.freq_recov, 3), - gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov_error.dat")) + gr.file_sink(gr.sizeof_float, "rx_freq_recov_error.32f")) self.connect((self.time_recov, 0), - gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat")) + gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.32fc")) self.connect((self.time_recov, 1), - gr.file_sink(gr.sizeof_float, "rx_time_recov_error.dat")) + gr.file_sink(gr.sizeof_float, "rx_time_recov_error.32f")) self.connect((self.time_recov, 2), - gr.file_sink(gr.sizeof_float, "rx_time_recov_rate.dat")) + gr.file_sink(gr.sizeof_float, "rx_time_recov_rate.32f")) self.connect((self.time_recov, 3), - gr.file_sink(gr.sizeof_float, "rx_time_recov_phase.dat")) + gr.file_sink(gr.sizeof_float, "rx_time_recov_phase.32f")) self.connect((self.receiver, 0), - gr.file_sink(gr.sizeof_char, "rx_receiver.dat")) + gr.file_sink(gr.sizeof_char, "rx_receiver.8b")) self.connect((self.receiver, 1), - gr.file_sink(gr.sizeof_float, "rx_receiver_error.dat")) + gr.file_sink(gr.sizeof_float, "rx_receiver_error.32f")) self.connect((self.receiver, 2), - gr.file_sink(gr.sizeof_float, "rx_receiver_phase.dat")) + gr.file_sink(gr.sizeof_float, "rx_receiver_phase.32f")) self.connect((self.receiver, 3), - gr.file_sink(gr.sizeof_float, "rx_receiver_freq.dat")) + gr.file_sink(gr.sizeof_float, "rx_receiver_freq.32f")) if self._differential: self.connect(self.diffdec, - gr.file_sink(gr.sizeof_char, "rx_diffdec.dat")) + gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) if self._constellation.apply_pre_diff_code(): self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) + gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) + gr.file_sink(gr.sizeof_char, "rx_unpack.8b")) def add_options(parser): """ @@ -376,16 +365,12 @@ class generic_demod(gr.hier_block2): # Add options shared with modulator. add_common_options(parser) # Add options specific to demodulator. - parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, - help="set frequency lock loop alpha gain value [default=%default]") - parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, - help="set phase tracking loop alpha value [default=%default]") - parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha, - help="set timing symbol sync loop gain alpha value [default=%default]") - parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta, - help="set timing symbol sync loop gain beta value [default=%default]") - parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev, - help="set timing symbol sync loop maximum deviation [default=%default]") + parser.add_option("", "--freq-bw", type="float", default=_def_freq_bw, + help="set frequency lock loop lock-in bandwidth [default=%default]") + parser.add_option("", "--phase-bw", type="float", default=_def_phase_bw, + help="set phase tracking loop lock-in bandwidth [default=%default]") + parser.add_option("", "--timing-bw", type="float", default=_def_timing_bw, + help="set timing symbol sync loop gain lock-in bandwidth [default=%default]") add_options=staticmethod(add_options) def extract_kwargs_from_options(cls, options): diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/gmsk.py b/gr-digital/python/gmsk.py index 3b6c016a0b..3b6c016a0b 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/gmsk.py +++ b/gr-digital/python/gmsk.py diff --git a/gnuradio-core/src/python/gnuradio/modulation_utils.py b/gr-digital/python/modulation_utils.py index 71ba773895..71ba773895 100644 --- a/gnuradio-core/src/python/gnuradio/modulation_utils.py +++ b/gr-digital/python/modulation_utils.py diff --git a/gr-digital/python/modulation_utils2.py b/gr-digital/python/modulation_utils2.py index f30055f4ac..cb3a9812d4 100644 --- a/gr-digital/python/modulation_utils2.py +++ b/gr-digital/python/modulation_utils2.py @@ -80,6 +80,7 @@ def extract_kwargs_from_options(function, excluded_args, options): @param options: result of command argument parsing @type options: optparse.Values """ + # Try this in C++ ;) args, varargs, varkw, defaults = inspect.getargspec(function) d = {} diff --git a/gnuradio-core/src/python/gnuradio/packet_utils.py b/gr-digital/python/packet_utils.py index e36b05413e..2e216ff50e 100644 --- a/gnuradio-core/src/python/gnuradio/packet_utils.py +++ b/gr-digital/python/packet_utils.py @@ -22,7 +22,7 @@ import struct import numpy from gnuradio import gru - +import crc def conv_packed_binary_string_to_1_0_string(s): """ @@ -127,7 +127,7 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, (packed_access_code, padded) = conv_1_0_string_to_packed_binary_string(access_code) (packed_preamble, ignore) = conv_1_0_string_to_packed_binary_string(preamble) - payload_with_crc = gru.gen_and_append_crc32(payload) + payload_with_crc = crc.gen_and_append_crc32(payload) #print "outbound crc =", string_to_hex_list(payload_with_crc[-4:]) L = len(payload_with_crc) @@ -184,7 +184,7 @@ def unmake_packet(whitened_payload_with_crc, whitener_offset=0, dewhitening=True else: payload_with_crc = (whitened_payload_with_crc) - ok, payload = gru.check_crc32(payload_with_crc) + ok, payload = crc.check_crc32(payload_with_crc) if 0: print "payload_with_crc =", string_to_hex_list(payload_with_crc) diff --git a/gr-digital/python/pkt.py b/gr-digital/python/pkt.py index aa720d1a52..c9b29bd51a 100644 --- a/gr-digital/python/pkt.py +++ b/gr-digital/python/pkt.py @@ -20,8 +20,10 @@ # from math import pi -from gnuradio import gr, packet_utils +from gnuradio import gr import gnuradio.gr.gr_threading as _threading +import packet_utils +import digital_swig # ///////////////////////////////////////////////////////////////////////////// @@ -34,8 +36,8 @@ class mod_pkts(gr.hier_block2): Send packets by calling send_pkt """ - def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False, - modulate=True): + def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, + use_whitener_offset=False, modulate=True): """ Hierarchical block for sending packets @@ -154,7 +156,7 @@ class demod_pkts(gr.hier_block2): threshold = 12 # FIXME raise exception self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY - self.correlator = gr.correlate_access_code_bb(access_code, threshold) + self.correlator = digital_swig.correlate_access_code_bb(access_code, threshold) self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) if self._demodulator is not None: diff --git a/gr-digital/python/psk2.py b/gr-digital/python/psk2.py index 778c1e5e56..82781e63b0 100644 --- a/gr-digital/python/psk2.py +++ b/gr-digital/python/psk2.py @@ -26,7 +26,6 @@ PSK modulation and demodulation. from math import pi, log from cmath import exp -from gnuradio import gr import digital_swig import modulation_utils2 from utils import mod_codes, gray_code diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py b/gr-digital/python/qa_binary_slicer_fb.py index 27e1802e08..944dc1b5aa 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py +++ b/gr-digital/python/qa_binary_slicer_fb.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010 Free Software Foundation, Inc. +# Copyright 2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,7 +21,8 @@ # from gnuradio import gr, gr_unittest -import math +import digital_swig +import math, random class test_constellation_decoder (gr_unittest.TestCase): @@ -31,17 +32,18 @@ class test_constellation_decoder (gr_unittest.TestCase): def tearDown (self): self.tb = None - def test_constellation_decoder_cb (self): - symbol_positions = [1 + 0j, 0 + 1j , -1 + 0j, 0 - 1j] - symbol_values_out = [0, 1, 2, 3] - expected_result = ( 0, 3, 2, 1, 0, 0, 3) - src_data = (0.5 + 0j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, 0.8 - 0j, 0.5 + 0j, 0.1 - 1.2j) - src = gr.vector_source_c (src_data) - op = gr.constellation_decoder_cb (symbol_positions, symbol_values_out) + def test_binary_slicer_fb (self): + expected_result = ( 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1) + src_data = (-1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1) + src_data = [s + (1 - random.random()) for s in src_data] # add some noise + src = gr.vector_source_f (src_data) + op = digital_swig.binary_slicer_fb () dst = gr.vector_sink_b () + self.tb.connect (src, op) self.tb.connect (op, dst) self.tb.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink #print "actual result", actual_result #print "expected result", expected_result diff --git a/gr-digital/python/qa_clock_recovery_mm.py b/gr-digital/python/qa_clock_recovery_mm.py new file mode 100755 index 0000000000..5ef86eda07 --- /dev/null +++ b/gr-digital/python/qa_clock_recovery_mm.py @@ -0,0 +1,176 @@ +#!/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, gr_unittest +import digital_swig, psk2 +import random, cmath + +class test_clock_recovery_mm(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + # Test complex/complex version + omega = 2 + gain_omega = 0.001 + mu = 0.5 + gain_mu = 0.01 + omega_rel_lim = 0.001 + + self.test = digital_swig.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, + omega_rel_lim) + + data = 100*[complex(1, 1),] + self.src = gr.vector_source_c(data, False) + self.snk = gr.vector_sink_c() + + self.tb.connect(self.src, self.test, self.snk) + self.tb.run() + + expected_result = 100*[complex(0.99972, 0.99972)] # doesn't quite get to 1.0 + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 30 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #print expected_result + #print dst_data + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + + + def test02 (self): + # Test float/float version + omega = 2 + gain_omega = 0.01 + mu = 0.5 + gain_mu = 0.01 + omega_rel_lim = 0.001 + + self.test = digital_swig.clock_recovery_mm_ff(omega, gain_omega, + mu, gain_mu, + omega_rel_lim) + + data = 100*[1,] + self.src = gr.vector_source_f(data, False) + self.snk = gr.vector_sink_f() + + self.tb.connect(self.src, self.test, self.snk) + self.tb.run() + + expected_result = 100*[0.99972, ] # doesn't quite get to 1.0 + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 30 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #print expected_result + #print dst_data + + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + + + def test03 (self): + # Test complex/complex version with varying input + omega = 2 + gain_omega = 0.01 + mu = 0.25 + gain_mu = 0.1 + omega_rel_lim = 0.0001 + + self.test = digital_swig.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, + omega_rel_lim) + + data = 1000*[complex(1, 1), complex(1, 1), complex(-1, -1), complex(-1, -1)] + self.src = gr.vector_source_c(data, False) + self.snk = gr.vector_sink_c() + + self.tb.connect(self.src, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[complex(-1.2, -1.2), complex(1.2, 1.2)] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #print expected_result + #print dst_data + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + + def test04 (self): + # Test float/float version + omega = 2 + gain_omega = 0.01 + mu = 0.25 + gain_mu = 0.1 + omega_rel_lim = 0.001 + + self.test = digital_swig.clock_recovery_mm_ff(omega, gain_omega, + mu, gain_mu, + omega_rel_lim) + + data = 1000*[1, 1, -1, -1] + self.src = gr.vector_source_f(data, False) + self.snk = gr.vector_sink_f() + + self.tb.connect(self.src, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[-1.31, 1.31] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #print expected_result + #print dst_data + + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 1) + + +if __name__ == '__main__': + gr_unittest.run(test_clock_recovery_mm, "test_clock_recovery_mm.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py b/gr-digital/python/qa_cma_equalizer.py index 79e9cd092f..75fb0f05ed 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py +++ b/gr-digital/python/qa_cma_equalizer.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2010 Free Software Foundation, Inc. +# Copyright 2006,2007,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,7 @@ # from gnuradio import gr, gr_unittest +import digital_swig class test_cma_equalizer_fir(gr_unittest.TestCase): @@ -32,7 +33,7 @@ class test_cma_equalizer_fir(gr_unittest.TestCase): def transform(self, src_data): SRC = gr.vector_source_c(src_data, False) - EQU = gr.cma_equalizer_cc(4, 1.0, .001) + EQU = digital_swig.cma_equalizer_cc(4, 1.0, .001, 1) DST = gr.vector_sink_c() self.tb.connect(SRC, EQU, DST) self.tb.run() diff --git a/gr-digital/python/qa_constellation_decoder_cb.py b/gr-digital/python/qa_constellation_decoder_cb.py new file mode 100755 index 0000000000..5401a07fc0 --- /dev/null +++ b/gr-digital/python/qa_constellation_decoder_cb.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010,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, gr_unittest +import digital_swig +import math + +class test_constellation_decoder (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_constellation_decoder_cb_bpsk (self): + cnst = digital_swig.constellation_bpsk() + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j) + expected_result = ( 1, 1, 0, 0, + 1, 0, 1) + src = gr.vector_source_c (src_data) + op = digital_swig.constellation_decoder_cb (cnst.base()) + dst = gr.vector_sink_b () + + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () # run the graph and wait for it to finish + + actual_result = dst.data () # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_constellation_decoder_cb_qpsk (self): + cnst = digital_swig.constellation_qpsk() + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j) + expected_result = ( 3, 1, 0, 2, + 3, 2, 1) + src = gr.vector_source_c (src_data) + op = digital_swig.constellation_decoder_cb (cnst.base()) + dst = gr.vector_sink_b () + + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () # run the graph and wait for it to finish + + actual_result = dst.data () # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + +if __name__ == '__main__': + gr_unittest.run(test_constellation_decoder, "test_constellation_decoder.xml") + diff --git a/gr-digital/python/qa_constellation_receiver.py b/gr-digital/python/qa_constellation_receiver.py index 70b62c7aab..79dded8ba3 100755 --- a/gr-digital/python/qa_constellation_receiver.py +++ b/gr-digital/python/qa_constellation_receiver.py @@ -22,9 +22,9 @@ import random -from gnuradio import gr, blks2, packet_utils, gr_unittest +from gnuradio import gr, blks2, gr_unittest from utils import mod_codes, alignment -import digital_swig +import digital_swig, packet_utils from generic_mod_demod import generic_mod, generic_demod from qa_constellation import tested_constellations, twod_constell @@ -37,7 +37,7 @@ random.seed(1239) # TESTING PARAMETERS # The number of symbols to test with. # We need this many to let the frequency recovery block converge. -DATA_LENGTH = 200000 +DATA_LENGTH = 10000 # Test fails if fraction of output that is correct is less than this. REQ_CORRECT = 0.8 diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py b/gr-digital/python/qa_correlate_access_code.py index b3575f4e6b..6b6f25051e 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py +++ b/gr-digital/python/qa_correlate_access_code.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2010 Free Software Foundation, Inc. +# Copyright 2006,2007,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,7 @@ # from gnuradio import gr, gr_unittest +import digital_swig import math default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -52,7 +53,7 @@ class test_correlate_access_code(gr_unittest.TestCase): src_data = (1, 0, 1, 1, 1, 1, 0, 1, 1) + pad + (0,) * 7 expected_result = pad + (1, 0, 1, 1, 3, 1, 0, 1, 1, 2) + (0,) * 6 src = gr.vector_source_b (src_data) - op = gr.correlate_access_code_bb("1011", 0) + op = digital_swig.correlate_access_code_bb("1011", 0) dst = gr.vector_sink_b () self.tb.connect (src, op, dst) self.tb.run () @@ -69,7 +70,7 @@ class test_correlate_access_code(gr_unittest.TestCase): src_data = code + (1, 0, 1, 1) + pad expected_result = pad + code + (3, 0, 1, 1) src = gr.vector_source_b (src_data) - op = gr.correlate_access_code_bb(access_code, 0) + op = digital_swig.correlate_access_code_bb(access_code, 0) dst = gr.vector_sink_b () self.tb.connect (src, op, dst) self.tb.run () diff --git a/gr-digital/python/qa_costas_loop_cc.py b/gr-digital/python/qa_costas_loop_cc.py index 368704093b..124159dbaa 100755 --- a/gr-digital/python/qa_costas_loop_cc.py +++ b/gr-digital/python/qa_costas_loop_cc.py @@ -20,11 +20,11 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, blks2, gr_unittest -import digital_swig +from gnuradio import gr, gr_unittest +import digital_swig, psk2 import random, cmath -class test_digital(gr_unittest.TestCase): +class test_costas_loop_cc(gr_unittest.TestCase): def setUp (self): self.tb = gr.top_block () @@ -34,10 +34,9 @@ class test_digital(gr_unittest.TestCase): def test01 (self): # test basic functionality by setting all gains to 0 - damp = 0.4 - natfreq = 0.25 + natfreq = 0.0 order = 2 - self.test = digital_swig.costas_loop_cc(damp, natfreq, order) + self.test = digital_swig.costas_loop_cc(natfreq, order) data = 100*[complex(1,0),] self.src = gr.vector_source_c(data, False) @@ -52,10 +51,9 @@ class test_digital(gr_unittest.TestCase): def test02 (self): # Make sure it doesn't diverge given perfect data - damp = 0.4 natfreq = 0.25 order = 2 - self.test = digital_swig.costas_loop_cc(damp, natfreq, order) + self.test = digital_swig.costas_loop_cc(natfreq, order) data = [complex(2*random.randint(0,1)-1, 0) for i in xrange(100)] self.src = gr.vector_source_c(data, False) @@ -71,10 +69,9 @@ class test_digital(gr_unittest.TestCase): def test03 (self): # BPSK Convergence test with static rotation - damp = 0.4 natfreq = 0.25 order = 2 - self.test = digital_swig.costas_loop_cc(damp, natfreq, order) + self.test = digital_swig.costas_loop_cc(natfreq, order) rot = cmath.exp(0.2j) # some small rotation data = [complex(2*random.randint(0,1)-1, 0) for i in xrange(100)] @@ -97,10 +94,9 @@ class test_digital(gr_unittest.TestCase): def test04 (self): # QPSK Convergence test with static rotation - damp = 0.4 natfreq = 0.25 order = 4 - self.test = digital_swig.costas_loop_cc(damp, natfreq, order) + self.test = digital_swig.costas_loop_cc(natfreq, order) rot = cmath.exp(0.2j) # some small rotation data = [complex(2*random.randint(0,1)-1, 2*random.randint(0,1)-1) @@ -124,15 +120,14 @@ class test_digital(gr_unittest.TestCase): def test05 (self): # 8PSK Convergence test with static rotation - damp = 0.5 - natfreq = 0.5 + natfreq = 0.25 order = 8 - self.test = digital_swig.costas_loop_cc(damp, natfreq, order) + self.test = digital_swig.costas_loop_cc(natfreq, order) rot = cmath.exp(-cmath.pi/8.0j) # rotate to match Costas rotation - const = blks2.psk.make_constellation(order) + const = psk2.psk_constellation(order) data = [random.randint(0,7) for i in xrange(100)] - data = [2*rot*const[d] for d in data] + data = [2*rot*const.points()[d] for d in data] N = 40 # settling time expected_result = data[N:] @@ -153,4 +148,4 @@ class test_digital(gr_unittest.TestCase): self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 2) if __name__ == '__main__': - gr_unittest.run(test_digital, "test_digital.xml") + gr_unittest.run(test_costas_loop_cc, "test_costas_loop_cc.xml") diff --git a/gr-digital/python/qa_crc32.py b/gr-digital/python/qa_crc32.py new file mode 100644 index 0000000000..f86813f3f3 --- /dev/null +++ b/gr-digital/python/qa_crc32.py @@ -0,0 +1,60 @@ +#!/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, gr_unittest +import digital_swig +import random, cmath + +class test_crc32(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + data = 100*"0" + expected_result = 2943744955 + result = digital_swig.crc32(data) + #print hex(result) + + self.assertEqual (expected_result, result) + + def test02 (self): + data = 100*"1" + expected_result = 2326594156 + result = digital_swig.crc32(data) + #print hex(result) + + self.assertEqual (expected_result, result) + + def test03 (self): + data = 10*"0123456789" + expected_result = 3774345973 + result = digital_swig.crc32(data) + #print hex(result) + + self.assertEqual (expected_result, result) + +if __name__ == '__main__': + gr_unittest.run(test_crc32, "test_crc32.xml") diff --git a/gr-digital/python/qa_fll_band_edge.py b/gr-digital/python/qa_fll_band_edge.py new file mode 100644 index 0000000000..088eb2b680 --- /dev/null +++ b/gr-digital/python/qa_fll_band_edge.py @@ -0,0 +1,83 @@ +#!/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, gr_unittest +import digital_swig +import random, math + +class test_fll_band_edge_cc(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + sps = 4 + rolloff = 0.35 + bw = 2*math.pi/100.0 + ntaps = 45 + + # Create pulse shape filter + rrc_taps = gr.firdes.root_raised_cosine( + sps, sps, 1.0, rolloff, ntaps) + + # The frequency offset to correct + foffset = 0.2 / (2.0*math.pi) + + # Create a set of 1's and -1's, pulse shape and interpolate to sps + data = [2.0*random.randint(0, 2) - 1.0 for i in xrange(200)] + self.src = gr.vector_source_c(data, False) + self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps) + + # Mix symbols with a complex sinusoid to spin them + self.nco = gr.sig_source_c(1, gr.GR_SIN_WAVE, foffset, 1) + self.mix = gr.multiply_cc() + + # FLL will despin the symbols to an arbitrary phase + self.fll = digital_swig.fll_band_edge_cc(sps, rolloff, ntaps, bw) + + # Create sinks for all outputs of the FLL + # we will only care about the freq and error outputs + self.vsnk_frq = gr.vector_sink_f() + self.nsnk_fll = gr.null_sink(gr.sizeof_gr_complex) + self.nsnk_phs = gr.null_sink(gr.sizeof_float) + self.nsnk_err = gr.null_sink(gr.sizeof_float) + + # Connect the blocks + self.tb.connect(self.nco, (self.mix,1)) + self.tb.connect(self.src, self.rrc, (self.mix,0)) + self.tb.connect(self.mix, self.fll, self.nsnk_fll) + self.tb.connect((self.fll,1), self.vsnk_frq) + self.tb.connect((self.fll,2), self.nsnk_phs) + self.tb.connect((self.fll,3), self.nsnk_err) + self.tb.run() + + N = 700 + dst_data = self.vsnk_frq.data()[N:] + + expected_result = len(dst_data)* [-0.20,] + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + +if __name__ == '__main__': + gr_unittest.run(test_fll_band_edge_cc, "test_fll_band_edge_cc.xml") diff --git a/gr-digital/python/qa_lms_equalizer.py b/gr-digital/python/qa_lms_equalizer.py new file mode 100644 index 0000000000..025c785aa4 --- /dev/null +++ b/gr-digital/python/qa_lms_equalizer.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# Copyright 2006,2007,2010,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, gr_unittest +import digital_swig + +class test_lms_dd_equalizer(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def transform(self, src_data, gain, const): + SRC = gr.vector_source_c(src_data, False) + EQU = digital_swig.lms_dd_equalizer_cc(4, gain, 1, const.base()) + DST = gr.vector_sink_c() + self.tb.connect(SRC, EQU, DST) + self.tb.run() + return DST.data() + + def test_001_identity(self): + # Constant modulus signal so no adjustments + const = digital_swig.constellation_qpsk() + src_data = const.points()*1000 + + N = 100 # settling time + expected_data = src_data[N:] + result = self.transform(src_data, 0.1, const)[N:] + self.assertComplexTuplesAlmostEqual(expected_data, result, 5) + +if __name__ == "__main__": + gr_unittest.run(test_lms_dd_equalizer, "test_lms_dd_equalizer.xml") diff --git a/gr-digital/python/qa_mpsk_receiver.py b/gr-digital/python/qa_mpsk_receiver.py new file mode 100644 index 0000000000..7e9a76e1f2 --- /dev/null +++ b/gr-digital/python/qa_mpsk_receiver.py @@ -0,0 +1,123 @@ +#!/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, gr_unittest +import digital_swig, psk2 +import random, cmath + +class test_mpsk_receiver(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + # Test BPSK sync + M = 2 + theta = 0 + alpha = 0.1 + beta = 0.25*alpha*alpha + fmin = -0.5 + fmax = 0.5 + mu = 0.25 + gain_mu = 0.01 + omega = 2 + gain_omega = 0.001 + omega_rel = 0.001 + + self.test = digital_swig.mpsk_receiver_cc(M, theta, alpha, beta, + fmin, fmax, mu, gain_mu, + omega, gain_omega, + omega_rel) + + data = 1000*[complex(1,0), complex(1,0), complex(-1,0), complex(-1,0)] + self.src = gr.vector_source_c(data, False) + self.snk = gr.vector_sink_c() + + self.tb.connect(self.src, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[complex(-0.5,0), complex(0.5,0)] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #print expected_result + #print dst_data + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + + def test02 (self): + # Test QPSK sync + M = 4 + theta = 0 + alpha = 0.1 + beta = 0.25*alpha*alpha + fmin = -0.5 + fmax = 0.5 + mu = 0.25 + gain_mu = 0.01 + omega = 2 + gain_omega = 0.001 + omega_rel = 0.001 + + self.test = digital_swig.mpsk_receiver_cc(M, theta, alpha, beta, + fmin, fmax, mu, gain_mu, + omega, gain_omega, + omega_rel) + + data = 1000*[complex( 0.707, 0.707), complex( 0.707, 0.707), + complex(-0.707, 0.707), complex(-0.707, 0.707), + complex(-0.707, -0.707), complex(-0.707, -0.707), + complex( 0.707, -0.707), complex( 0.707, -0.707)] + self.src = gr.vector_source_c(data, False) + self.snk = gr.vector_sink_c() + + self.tb.connect(self.src, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[complex(1.2, 0), complex(0, 1.2), + complex(-1.2, 0), complex(0, -1.2)] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #print expected_result + #print dst_data + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + +if __name__ == '__main__': + gr_unittest.run(test_mpsk_receiver, "test_mpsk_receiver.xml") diff --git a/gr-digital/python/qam.py b/gr-digital/python/qam.py index ee2b1e416e..a5a2e6c2cf 100644 --- a/gr-digital/python/qam.py +++ b/gr-digital/python/qam.py @@ -26,10 +26,10 @@ QAM modulation and demodulation. from math import pi, sqrt, log from gnuradio import gr -import modulation_utils2 from generic_mod_demod import generic_mod, generic_demod from utils.gray_code import gray_code from utils import mod_codes +import modulation_utils2 # Default number of points in constellation. _def_constellation_points = 16 @@ -113,7 +113,7 @@ def make_differential_constellation(m, gray_coded): return const_map -def make_not_differential_constellation(m, gray_coded): +def make_non_differential_constellation(m, gray_coded): side = int(pow(m, 0.5)) if (not isinstance(m, int) or m < 4 or not is_power_of_four(m)): raise ValueError("m must be a power of 4 integer.") @@ -158,7 +158,7 @@ def qam_constellation(constellation_points=_def_constellation_points, if differential: points = make_differential_constellation(constellation_points, gray_coded) else: - points = make_not_differential_constellation(constellation_points, gray_coded) + points = make_non_differential_constellation(constellation_points, gray_coded) side = int(sqrt(constellation_points)) width = 2.0/(side-1) # No pre-diff code diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py index ea17244241..76e5df2701 100644 --- a/gr-digital/python/qpsk.py +++ b/gr-digital/python/qpsk.py @@ -23,17 +23,16 @@ QPSK modulation. Demodulation is not included since the generic_mod_demod -doesn't work for non-differential encodings. """ -from gnuradio import gr, modulation_utils2 -from gnuradio.digital.generic_mod_demod import generic_mod - +from gnuradio import gr +from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod +import digital_swig +import modulation_utils2 # Default number of points in constellation. _def_constellation_points = 4 -# Whether differential coding is used. -_def_differential = False +# Whether gray coding is used. _def_gray_coded = True # ///////////////////////////////////////////////////////////////////////////// @@ -43,7 +42,7 @@ _def_gray_coded = True def qpsk_constellation(m=_def_constellation_points): if m != _def_constellation_points: raise ValueError("QPSK can only have 4 constellation points.") - return gr.constellation_qpsk() + return digital_swig.constellation_qpsk() # ///////////////////////////////////////////////////////////////////////////// # QPSK modulator @@ -52,7 +51,6 @@ def qpsk_constellation(m=_def_constellation_points): class qpsk_mod(generic_mod): def __init__(self, constellation_points=_def_constellation_points, - differential=_def_differential, gray_coded=_def_gray_coded, *args, **kwargs): @@ -65,15 +63,47 @@ class qpsk_mod(generic_mod): See generic_mod block for list of parameters. """ - constellation = gr.constellation_qpsk() + constellation_points = _def_constellation_points + constellation = digital_swig.constellation_qpsk() if constellation_points != 4: raise ValueError("QPSK can only have 4 constellation points.") - if differential or not gray_coded: - raise ValueError("This QPSK mod/demod works only for gray-coded, non-differential.") - super(qpsk_mod, self).__init__(constellation, differential, gray_coded, *args, **kwargs) + if not gray_coded: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + super(qpsk_mod, self).__init__(constellation=constellation, + gray_coded=gray_coded, + *args, **kwargs) + + +# ///////////////////////////////////////////////////////////////////////////// +# QPSK demodulator +# +# ///////////////////////////////////////////////////////////////////////////// + +class qpsk_demod(generic_demod): + + def __init__(self, constellation_points=_def_constellation_points, + *args, **kwargs): + + """ + Hierarchical block for RRC-filtered QPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + See generic_demod block for list of parameters. + """ + + constellation_points = _def_constellation_points + constellation = digital_swig.constellation_qpsk() + if constellation_points != 4: + raise ValueError('Number of constellation points must be 4 for QPSK.') + super(qpsk_demod, self).__init__(constellation=constellation, + *args, **kwargs) # # Add these to the mod/demod registry # modulation_utils2.add_type_1_mod('qpsk', qpsk_mod) +modulation_utils2.add_type_1_demod('qpsk', qpsk_demod) modulation_utils2.add_type_1_constellation('qpsk', qpsk_constellation) + diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt index a7374f0f0d..b62c024e06 100644 --- a/gr-digital/swig/CMakeLists.txt +++ b/gr-digital/swig/CMakeLists.txt @@ -40,13 +40,20 @@ GR_SWIG_INSTALL( INSTALL( FILES + digital_binary_slicer_fb.i + digital_clock_recovery_mm_cc.i + digital_clock_recovery_mm_ff.i digital_constellation.i digital_constellation_receiver_cb.i digital_constellation_decoder_cb.i + digital_correlate_access_code_bb.i digital_costas_loop_cc.i digital_cma_equalizer_cc.i + digital_crc32.i + digital_fll_band_edge_cc.i digital_lms_dd_equalizer_cc.i digital_kurtotic_equalizer_cc.i + digital_mpsk_receiver_cc.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "digital_swig" ) diff --git a/gr-digital/swig/Makefile.am b/gr-digital/swig/Makefile.am index b9ebf4cc54..c0d28c24c6 100644 --- a/gr-digital/swig/Makefile.am +++ b/gr-digital/swig/Makefile.am @@ -58,13 +58,20 @@ digital_swig_la_swig_libadd = \ # additional SWIG files to be installed digital_swig_swiginclude_headers = \ + digital_binary_slicer_fb.i \ + digital_clock_recovery_mm_cc.i \ + digital_clock_recovery_mm_ff.i \ digital_constellation.i \ digital_constellation_receiver_cb.i \ digital_constellation_decoder_cb.i \ + digital_correlate_access_code_bb.i \ digital_costas_loop_cc.i \ digital_cma_equalizer_cc.i \ + digital_crc32.i \ + digital_fll_band_edge_cc.i \ digital_lms_dd_equalizer_cc.i \ - digital_kurtotic_equalizer_cc.i + digital_kurtotic_equalizer_cc.i \ + digital_mpsk_receiver_cc.i digital_swig_swig_args = \ -I$(abs_top_srcdir)/gr-digital/lib \ diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i b/gr-digital/swig/digital_binary_slicer_fb.i index b6f4e93124..30603748b3 100644 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i +++ b/gr-digital/swig/digital_binary_slicer_fb.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,14 +20,14 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,binary_slicer_fb); +GR_SWIG_BLOCK_MAGIC(digital,binary_slicer_fb); -gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); +digital_binary_slicer_fb_sptr digital_make_binary_slicer_fb (); -class gr_binary_slicer_fb : public gr_sync_block +class digital_binary_slicer_fb : public gr_sync_block { private: - gr_binary_slicer_fb (); + digital_binary_slicer_fb (); public: }; diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i b/gr-digital/swig/digital_clock_recovery_mm_cc.i index 27eb70b958..4ce9a9725d 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i +++ b/gr-digital/swig/digital_clock_recovery_mm_cc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,18 +20,19 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,clock_recovery_mm_cc); +GR_SWIG_BLOCK_MAGIC(digital,clock_recovery_mm_cc); -gr_clock_recovery_mm_cc_sptr -gr_make_clock_recovery_mm_cc (float omega, float gain_omega, - float mu, float gain_mu, - float omega_relative_limit) throw(std::exception); +digital_clock_recovery_mm_cc_sptr +digital_make_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit) throw(std::exception); -class gr_clock_recovery_mm_cc : public gr_sync_block +class digital_clock_recovery_mm_cc : public gr_sync_block { private: - gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, - float gain_mu, float omega_relative_limit); + digital_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit); public: float mu() const { return d_mu;} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i b/gr-digital/swig/digital_clock_recovery_mm_ff.i index 1b24370008..054ef9ebfe 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i +++ b/gr-digital/swig/digital_clock_recovery_mm_ff.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,18 +20,19 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,clock_recovery_mm_ff); +GR_SWIG_BLOCK_MAGIC(digital,clock_recovery_mm_ff); -gr_clock_recovery_mm_ff_sptr -gr_make_clock_recovery_mm_ff (float omega, float gain_omega, - float mu, float gain_mu, - float omega_relative_limit=0.001) throw(std::exception); +digital_clock_recovery_mm_ff_sptr +digital_make_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit=0.001) throw(std::exception); -class gr_clock_recovery_mm_ff : public gr_sync_block +class digital_clock_recovery_mm_ff : public gr_sync_block { private: - gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit); + digital_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit); public: float mu() const; diff --git a/gr-digital/swig/digital_constellation_receiver_cb.i b/gr-digital/swig/digital_constellation_receiver_cb.i index ad17ef3713..e4be5f39f1 100644 --- a/gr-digital/swig/digital_constellation_receiver_cb.i +++ b/gr-digital/swig/digital_constellation_receiver_cb.i @@ -26,22 +26,25 @@ GR_SWIG_BLOCK_MAGIC(digital,constellation_receiver_cb); digital_constellation_receiver_cb_sptr digital_make_constellation_receiver_cb (digital_constellation_sptr constellation, - float alpha, float beta, - float fmin, float fmax); + float loop_bw, float fmin, float fmax); class digital_constellation_receiver_cb : public gr_block { private: digital_constellation_receiver_cb (digital_contellation_sptr constellation, - float alpha, float beta, - float fmin, float fmax); + float loop_bw, float fmin, float fmax); public: - float alpha() const { return d_alpha; } - float beta() const { return d_beta; } - float freq() const { return d_freq; } - float phase() const { return d_phase; } - void set_alpha(float alpha) { d_alpha = alpha; } - void set_beta(float beta) { d_beta = beta; } - void set_freq(float freq) { d_freq = freq; } - void set_phase(float phase) { d_phase = phase; } + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_frequency(float freq); + void set_phase(float phase); + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_frequency() const; + float get_phase() const; }; diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i b/gr-digital/swig/digital_correlate_access_code_bb.i index bec4282f12..01087b8e93 100644 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i +++ b/gr-digital/swig/digital_correlate_access_code_bb.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,14 +20,14 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,correlate_access_code_bb); +GR_SWIG_BLOCK_MAGIC(digital,correlate_access_code_bb); /*! * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" * \param threshold maximum number of bits that may be wrong */ -gr_correlate_access_code_bb_sptr -gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) +digital_correlate_access_code_bb_sptr +digital_make_correlate_access_code_bb (const std::string &access_code, int threshold) throw(std::out_of_range); /*! @@ -43,15 +43,15 @@ gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) * flag bit and is 1 if the corresponding data bit is the first data * bit following the access code. Otherwise the flag bit is 0. */ -class gr_correlate_access_code_bb : public gr_sync_block +class digital_correlate_access_code_bb : public gr_sync_block { - friend gr_correlate_access_code_bb_sptr - gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + friend digital_correlate_access_code_bb_sptr + digital_make_correlate_access_code_bb (const std::string &access_code, int threshold); protected: - gr_correlate_access_code_bb(const std::string &access_code, int threshold); + digital_correlate_access_code_bb(const std::string &access_code, int threshold); public: - ~gr_correlate_access_code_bb(); + ~digital_correlate_access_code_bb(); /*! * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" diff --git a/gr-digital/swig/digital_costas_loop_cc.i b/gr-digital/swig/digital_costas_loop_cc.i index 6d3d009f8a..ab09200a0a 100644 --- a/gr-digital/swig/digital_costas_loop_cc.i +++ b/gr-digital/swig/digital_costas_loop_cc.i @@ -23,22 +23,11 @@ GR_SWIG_BLOCK_MAGIC(digital,costas_loop_cc); digital_costas_loop_cc_sptr -digital_make_costas_loop_cc (float damping, float nat_freq, - int order +digital_make_costas_loop_cc (float loop_bw, int order ) throw (std::invalid_argument); - -class digital_costas_loop_cc : public gr_sync_block +class digital_costas_loop_cc : public gr_sync_block, public gri_control_loop { private: - digital_costas_loop_cc (float damping, float nat_freq, - int order); - - public: - float alpha(); - float beta(); - float freq(); - - void set_natural_freq(float w); - void set_damping_factor(float eta); + digital_costas_loop_cc (float loop_bw, int order); }; diff --git a/gnuradio-core/src/lib/general/gr_crc32.i b/gr-digital/swig/digital_crc32.i index 7dca5c6a12..806bfad6a0 100644 --- a/gnuradio-core/src/lib/general/gr_crc32.i +++ b/gr-digital/swig/digital_crc32.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -%rename(update_crc32) gr_update_crc32; -%rename(crc32) gr_crc32; +%rename(update_crc32) digital_update_crc32; +%rename(crc32) digital_crc32; -unsigned int gr_update_crc32(unsigned int crc, const std::string buf); -unsigned int gr_crc32(const std::string buf); +unsigned int digital_update_crc32(unsigned int crc, const std::string buf); +unsigned int digital_crc32(const std::string buf); diff --git a/gr-digital/swig/digital_fll_band_edge_cc.i b/gr-digital/swig/digital_fll_band_edge_cc.i new file mode 100644 index 0000000000..f022bc7e18 --- /dev/null +++ b/gr-digital/swig/digital_fll_band_edge_cc.i @@ -0,0 +1,60 @@ +/* -*- 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(digital,fll_band_edge_cc); + +digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym, + float rolloff, + int filter_size, + float bandwidth); + +class digital_fll_band_edge_cc : public gr_sync_block +{ + private: + digital_fll_band_edge_cc (float samps_per_sym, float rolloff, + int filter_size, float bandwidth); + + public: + ~digital_fll_band_edge_cc (); + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_samples_per_symbol(float sps); + void set_rolloff(float rolloff); + void set_filter_size(int filter_size); + void set_frequency(float freq); + void set_phase(float phase); + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_samples_per_symbol() const; + float get_rolloff() const; + int get_filter_size() const; + float get_frequency() const; + float get_phase() const; + + void print_taps(); +}; diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i b/gr-digital/swig/digital_mpsk_receiver_cc.i index 88cb43e045..cdc9f661b5 100644 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i +++ b/gr-digital/swig/digital_mpsk_receiver_cc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,21 +20,22 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,mpsk_receiver_cc); +GR_SWIG_BLOCK_MAGIC(digital,mpsk_receiver_cc); -gr_mpsk_receiver_cc_sptr gr_make_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, - float fmin, float fmax, - float mu, float gain_mu, - float omega, float gain_omega, float omega_rel); -class gr_mpsk_receiver_cc : public gr_block +digital_mpsk_receiver_cc_sptr digital_make_mpsk_receiver_cc (unsigned int M, float theta, + float alpha, float beta, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, + float omega_rel); +class digital_mpsk_receiver_cc : public gr_block { private: - gr_mpsk_receiver_cc (unsigned int M,float theta, - float alpha, float beta, - float fmin, float fmax, - float mu, float gain_mu, - float omega, float gain_omega, float omega_rel); + digital_mpsk_receiver_cc (unsigned int M,float theta, + float alpha, float beta, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, float omega_rel); public: float mu() const { return d_mu;} float omega() const { return d_omega;} diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index 26a9dd130a..0328ca2fcc 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -21,23 +21,39 @@ %include "gnuradio.i" +%include <gri_control_loop.i> + %{ +#include "digital_binary_slicer_fb.h" +#include "digital_clock_recovery_mm_cc.h" +#include "digital_clock_recovery_mm_ff.h" +#include "digital_cma_equalizer_cc.h" #include "digital_constellation.h" +#include "digital_constellation_decoder_cb.h" +#include "digital_constellation_receiver_cb.h" +#include "digital_correlate_access_code_bb.h" #include "digital_costas_loop_cc.h" -#include "digital_cma_equalizer_cc.h" -#include "digital_lms_dd_equalizer_cc.h" +#include "digital_crc32.h" +#include "digital_fll_band_edge_cc.h" #include "digital_kurtotic_equalizer_cc.h" -#include "digital_constellation_receiver_cb.h" -#include "digital_constellation_decoder_cb.h" +#include "digital_lms_dd_equalizer_cc.h" +#include "digital_mpsk_receiver_cc.h" %} +%include "digital_binary_slicer_fb.i" +%include "digital_clock_recovery_mm_cc.i" +%include "digital_clock_recovery_mm_ff.i" +%include "digital_cma_equalizer_cc.i" %include "digital_constellation.i" +%include "digital_constellation_decoder_cb.i" +%include "digital_constellation_receiver_cb.i" +%include "digital_correlate_access_code_bb.i" %include "digital_costas_loop_cc.i" -%include "digital_cma_equalizer_cc.i" -%include "digital_lms_dd_equalizer_cc.i" +%include "digital_crc32.i" +%include "digital_fll_band_edge_cc.i" %include "digital_kurtotic_equalizer_cc.i" -%include "digital_constellation_receiver_cb.i" -%include "digital_constellation_decoder_cb.i" +%include "digital_lms_dd_equalizer_cc.i" +%include "digital_mpsk_receiver_cc.i" #if SWIGGUILE %scheme %{ diff --git a/gr-utils/src/python/gr_plot_const.py b/gr-utils/src/python/gr_plot_const.py index 5dd08c9a0d..0c52899b25 100755 --- a/gr-utils/src/python/gr_plot_const.py +++ b/gr-utils/src/python/gr_plot_const.py @@ -85,16 +85,23 @@ class draw_constellation: except MemoryError: print "End of File" else: - self.reals = scipy.array([r.real for r in iq]) - self.imags = scipy.array([i.imag for i in iq]) + # retesting length here as newer version of scipy does not throw a MemoryError, just + # returns a zero-length array + if(len(iq) > 0): + self.reals = scipy.array([r.real for r in iq]) + self.imags = scipy.array([i.imag for i in iq]) + + self.time = scipy.array([i*(1/self.sample_rate) for i in range(len(self.reals))]) + return Tr + else: + print "End of File" + return False - self.time = scipy.array([i*(1/self.sample_rate) for i in range(len(self.reals))]) - def make_plots(self): # if specified on the command-line, set file pointer self.hfile.seek(self.sizeof_data*self.start, 1) - self.get_data() + r = self.get_data() # Subplot for real and imaginary parts of signal self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.4, 0.6]) @@ -175,8 +182,9 @@ class draw_constellation: self.step_forward() def step_forward(self): - self.get_data() - self.update_plots() + r = self.get_data() + if(r): + self.update_plots() def step_backward(self): # Step back in file position @@ -184,8 +192,9 @@ class draw_constellation: self.hfile.seek(-2*self.sizeof_data*self.block_length, 1) else: self.hfile.seek(-self.hfile.tell(),1) - self.get_data() - self.update_plots() + r = self.get_data() + if(r): + self.update_plots() def mouse_button_callback(self, event): diff --git a/gruel/src/include/gruel/Makefile.am b/gruel/src/include/gruel/Makefile.am index d258f03791..fce739f088 100644 --- a/gruel/src/include/gruel/Makefile.am +++ b/gruel/src/include/gruel/Makefile.am @@ -26,8 +26,6 @@ EXTRA_DIST += inet.h.in gruelincludedir = $(prefix)/include/gruel gruelinclude_HEADERS = \ -<<<<<<< HEAD - $(BUILT_SOURCES) \ api.h \ attributes.h \ high_res_timer.h \ |