diff options
192 files changed, 6091 insertions, 6304 deletions
diff --git a/Makefile.common b/Makefile.common index 20b8a78cf..2a5addd65 100644 --- a/Makefile.common +++ b/Makefile.common @@ -110,6 +110,10 @@ GCELL_SPU_LA = @gcell_spu_LA@ # libtool aware wrapper for ppu-embedspu GCELL_EMBEDSPU_LIBTOOL = @abs_top_srcdir@/gcell/lib/runtime/gcell-embedspu-libtool +# GR-DIGITAL includes and libraries +GR_DIGITAL_INCLUDES = @gr_digital_INCLUDES@ +GR_DIGITAL_LA = @gr_digital_LA@ + # Fix for BSD make not defining $(RM). We define it now in configure.ac # using AM_PATH_PROG, but now here have to add a -f to be like GNU make RM=$(RM_PROG) -f diff --git a/config/grc_gr_digital.m4 b/config/grc_gr_digital.m4 index a0765a341..35fafa0dd 100644 --- a/config/grc_gr_digital.m4 +++ b/config/grc_gr_digital.m4 @@ -23,17 +23,34 @@ AC_DEFUN([GRC_GR_DIGITAL],[ dnl Don't do gr-digital if gnuradio-core skipped GRC_CHECK_DEPENDENCY(gr-digital, gnuradio-core) + if test $passed != with; then + dnl how and where to find INCLUDES and LA and such + gr_digital_INCLUDES="\ +-I\${abs_top_srcdir}/gr-digital/include \ +-I\${abs_top_srcdir}/gr-digital/swig" + gr_digital_LA="\${abs_top_builddir}/gr-digital/lib/libgnuradio-core.la" + gr_digital_LIBDIRPATH="\${abs_top_builddir}/gr-digital/lib:\${abs_top_builddir}/gr-digital/lib/.libs" + gr_digital_SWIGDIRPATH="\${abs_top_builddir}/gr-digtial/lib/swig:\${abs_top_builddir}/gr-digital/swig/.libs:\${abs_top_srcdir}/gr-digital/swig" + gr_digital_PYDIRPATH="\${abs_top_srcdir}/gr-digital/python" + fi + + AC_SUBST(gr_digital_I) + AC_SUBST(gr_digital_SWIGDIRPATH) + AC_SUBST(gr_digital_PYDIRPATH) + AC_CONFIG_FILES([\ gr-digital/Makefile \ gr-digital/gnuradio-digital.pc \ gr-digital/apps/Makefile \ gr-digital/grc/Makefile \ + gr-digital/include/Makefile \ gr-digital/lib/Makefile \ gr-digital/python/Makefile \ gr-digital/python/run_tests \ 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 4dd0bc187..fe1d9421d 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 244249dd8..a0e39855c 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))) @@ -280,13 +244,13 @@ (pass-if (true? (gr:phase-modulator-fc 0))) ;;; ./general/gr_pll_carriertracking_cc.h -(pass-if (true? (gr:pll-carriertracking-cc 0 0 0 0))) +(pass-if (true? (gr:pll-carriertracking-cc 0 0 0))) ;;; ./general/gr_pll_freqdet_cf.h -(pass-if (true? (gr:pll-freqdet-cf 0 0 0 0))) +(pass-if (true? (gr:pll-freqdet-cf 0 0 0))) ;;; ./general/gr_pll_refout_cc.h -(pass-if (true? (gr:pll-refout-cc 0 0 0 0))) +(pass-if (true? (gr:pll-refout-cc 0 0 0))) ;;; ./general/gr_pn_correlator_cc.h (pass-if (true? (gr:pn-correlator-cc 1 1 1))) diff --git a/gnuradio-core/src/lib/filter/CMakeLists.txt b/gnuradio-core/src/lib/filter/CMakeLists.txt index 1ff7e8065..551715467 100644 --- a/gnuradio-core/src/lib/filter/CMakeLists.txt +++ b/gnuradio-core/src/lib/filter/CMakeLists.txt @@ -320,7 +320,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 d8f634c38..48ec55a62 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 58bb4f0d5..2af7fcc5c 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_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc index a52d1d901..a939609f3 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, @@ -60,16 +60,20 @@ gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float gain, gr_make_io_signaturev (1, 4, iosig)), d_updated (false), d_nfilters(filter_size), d_max_dev(max_rate_deviation), - d_osps(osps) + d_osps(osps), d_error(0) { 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]; @@ -246,51 +367,51 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items, int nrequired = ninput_items[0] - d_taps_per_filter - d_osps; int i = 0, count = 0; - float error, error_r, error_i; + float error_r, error_i; // produce output as long as we can and there are enough input samples while((i < noutput_items-d_osps) && (count < nrequired)) { - d_filtnum = (int)floor(d_k); - - // Keep the current filter number in [0, d_nfilters] - // If we've run beyond the last filter, wrap around and go to next sample - // If we've go below 0, wrap around and go to previous sample - while(d_filtnum >= d_nfilters) { - d_k -= d_nfilters; - d_filtnum -= d_nfilters; - count += 1; - } - while(d_filtnum < 0) { - d_k += d_nfilters; - d_filtnum += d_nfilters; - count -= 1; - } - for(int k = 0; k < d_osps; k++) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + out[i+k] = d_filters[d_filtnum]->filter(&in[count+k]); + d_k = d_k + d_rate_i + d_rate_f; // update phase + + if(output_items.size() == 4) { + err[i] = d_error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } } + // Update the phase and rate estimates for this symbol 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 = (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; + error_r = out[i].real() * diff.real(); + error_i = out[i].imag() * diff.imag(); + d_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 estimates based on the error value + d_rate_f = d_rate_f + d_beta*d_error; + d_k = d_k + d_alpha*d_error; // Keep our rate within a good range d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); - 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; - outrate[i] = d_rate_f; - outk[i] = d_k; - } - } - i+=d_osps; count += (int)floor(d_sps); } 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 f4685c76a..0fd8ba35b 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,7 +118,7 @@ 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 @@ -127,36 +127,41 @@ class GR_CORE_API gr_pfb_clock_sync_ccf : public gr_block * \param 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; + float d_error; /*! * 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 +173,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 +191,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 +291,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 343ed0912..78b9a6589 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 83f8dc6eb..ab6201de1 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 @@ -95,6 +96,7 @@ LIST(APPEND gnuradio_core_sources LIST(APPEND test_gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/qa_general.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_circular_file.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_cpm.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_firdes.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt_nco.cc @@ -131,6 +133,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 +163,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 +181,16 @@ 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_cpm gr_ctcss_squelch_ff gr_decode_ccsds_27_fb gr_diff_decoder_bb @@ -208,7 +206,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 +223,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 7a7e6f496..e389e05e1 100644 --- a/gnuradio-core/src/lib/general/Makefile.am +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -44,24 +44,18 @@ 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_cpm.cc \ gr_ctcss_squelch_ff.cc \ gr_decode_ccsds_27_fb.cc \ gr_deinterleave.cc \ @@ -79,7 +73,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 +90,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 +154,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 \ @@ -187,6 +178,7 @@ libgeneral_la_SOURCES = \ libgeneral_qa_la_SOURCES = \ qa_general.cc \ qa_gr_circular_file.cc \ + qa_gr_cpm.cc \ qa_gr_firdes.cc \ qa_gr_fxpt.cc \ qa_gr_fxpt_nco.cc \ @@ -203,24 +195,18 @@ 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_cpm.h \ gr_ctcss_squelch_ff.h \ gr_decode_ccsds_27_fb.h \ gr_diff_decoder_bb.h \ @@ -238,7 +224,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 \ @@ -258,14 +243,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 \ @@ -335,6 +317,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 \ @@ -362,6 +345,7 @@ grinclude_HEADERS = \ noinst_HEADERS = \ qa_general.h \ qa_gr_circular_file.h \ + qa_gr_cpm.h \ qa_gr_firdes.h \ qa_gr_fxpt.h \ qa_gr_fxpt_nco.h \ @@ -380,22 +364,16 @@ 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_cpm.i \ gr_ctcss_squelch_ff.i \ gr_decode_ccsds_27_fb.i \ gr_diff_decoder_bb.i \ @@ -411,7 +389,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 \ @@ -429,10 +406,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 \ @@ -495,6 +469,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 bef55a252..107f5c9ea 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -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,15 +132,16 @@ #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> #include <gr_annotator_1to1.h> #include <gr_burst_tagger.h> +#include <gr_cpm.h> #include <gr_correlate_access_code_tag_bb.h> %} +%include "gri_control_loop.i" %include "gr_nop.i" %include "gr_null_sink.i" %include "gr_null_source.i" @@ -197,7 +189,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" @@ -205,13 +196,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" @@ -230,7 +216,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" @@ -238,10 +223,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" @@ -269,10 +251,10 @@ %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" %include "gr_annotator_1to1.i" %include "gr_burst_tagger.i" +%include "gr_cpm.i" %include "gr_correlate_access_code_tag_bb.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 5b87f1430..000000000 --- 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 8d9c9b56e..000000000 --- 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 b77b19745..000000000 --- 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 488cab370..000000000 --- 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_cpm.cc b/gnuradio-core/src/lib/general/gr_cpm.cc new file mode 100644 index 000000000..a00526b52 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.cc @@ -0,0 +1,214 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * 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. + */ + +// Calculate the taps for the CPM phase responses + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cmath> +#include <cfloat> +#include <gr_cpm.h> + +#ifndef M_TWOPI +# define M_TWOPI (2*M_PI) +#endif + +//! Normalised sinc function, sinc(x)=sin(pi*x)/pi*x +inline double +sinc(double x) +{ + if (x == 0) { + return 1.0; + } + + return sin(M_PI * x) / (M_PI * x); +} + + +//! Taps for L-RC CPM (Raised cosine of length L symbols) +std::vector<float> +generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L) +{ + std::vector<float> taps(samples_per_sym * L, 1.0/L/samples_per_sym); + for (unsigned i = 0; i < samples_per_sym * L; i++) { + taps[i] *= 1 - cos(M_TWOPI * i / L / samples_per_sym); + } + + return taps; +} + + +/*! Taps for L-SRC CPM (Spectral raised cosine of length L symbols). + * + * L-SRC has a time-continuous phase response function of + * + * g(t) = 1/LT * sinc(2t/LT) * cos(beta * 2pi t / LT) / (1 - (4beta / LT * t)^2) + * + * which is the Fourier transform of a cos-rolloff function with rolloff + * beta, and looks like a sinc-function, multiplied with a rolloff term. + * We return the main lobe of the sinc, i.e., everything between the + * zero crossings. + * The time-discrete IR is thus + * + * g(k) = 1/Ls * sinc(2k/Ls) * cos(beta * pi k / Ls) / (1 - (4beta / Ls * k)^2) + * where k = 0...Ls-1 + * and s = samples per symbol. + */ +std::vector<float> +generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta) +{ + double Ls = (double) L * samples_per_sym; + std::vector<double> taps_d(L * samples_per_sym, 0.0); + std::vector<float> taps(L * samples_per_sym, 0.0); + + double sum = 0; + for (unsigned i = 0; i < samples_per_sym * L; i++) { + double k = i - Ls/2; // Causal to acausal + + taps_d[i] = 1.0 / Ls * sinc(2.0 * k / Ls); + + // For k = +/-Ls/4*beta, the rolloff term's cos-function becomes zero + // and the whole thing converges to PI/4 (to prove this, use de + // l'hopital's rule). + if (fabs(fabs(k) - Ls/4/beta) < 2*DBL_EPSILON) { + taps_d[i] *= M_PI_4; + } else { + double tmp = 4.0 * beta * k / Ls; + taps_d[i] *= cos(beta * M_TWOPI * k / Ls) / (1 - tmp * tmp); + } + sum += taps_d[i]; + } + for (unsigned i = 0; i < samples_per_sym * L; i++) { + taps[i] = (float) taps_d[i] / sum; + } + + return taps; +} + + +//! Taps for L-REC CPM (Rectangular pulse shape of length L symbols) +std::vector<float> +generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) +{ + return std::vector<float>(samples_per_sym * L, 1.0/L/samples_per_sym); +} + + +//! Helper function for TFM +double tfm_g0(double k, double sps) +{ + if (fabs(k) < 2 * DBL_EPSILON) { + return 1.145393004159143; // 1 + pi^2/48 / sqrt(2) + } + + const double pi2_24 = 0.411233516712057; // pi^2/24 + double f = M_PI * k / sps; + return sinc(k/sps) - pi2_24 * (2 * sin(f) - 2*f*cos(f) - f*f*sin(f)) / (f*f*f); +} + + +//! Taps for TFM CPM (Tamed frequency modulation) +// +// See [2, Chapter 2.7.2]. +// +// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation +std::vector<float> +generate_cpm_tfm_taps(unsigned sps, unsigned L) +{ + unsigned causal_shift = sps * L / 2; + std::vector<double> taps_d(sps * L, 0.0); + std::vector<float> taps(sps * L, 0.0); + + double sum = 0; + for (unsigned i = 0; i < sps * L; i++) { + double k = (double)(((int)i) - ((int)causal_shift)); // Causal to acausal + + taps_d[i] = tfm_g0(k - sps, sps) + + 2 * tfm_g0(k, sps) + + tfm_g0(k + sps, sps); + sum += taps_d[i]; + } + for (unsigned i = 0; i < sps * L; i++) { + taps[i] = (float) taps_d[i] / sum; + } + + return taps; +} + + +//! Taps for Gaussian CPM. Phase response is truncated after \p L symbols. +// \p bt sets the 3dB-time-bandwidth product. +// +// Note: for h = 0.5, this is the phase response for GMSK. +// +// This C99-compatible formula for the taps is taken straight +// from [1, Chapter 9.2.3]. +// A version in Q-notation can be found in [2, Chapter 2.7.2]. +// +// [1]: Karl-Dirk Kammeyer; Nachrichtenübertragung, 4th Edition. +// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation +// +std::vector<float> +generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt) +{ + double Ls = (double) L * samples_per_sym; + std::vector<double> taps_d(L * samples_per_sym, 0.0); + std::vector<float> taps(L * samples_per_sym, 0.0); + + // alpha = sqrt(2/ln(2)) * pi * BT + double alpha = 5.336446256636997 * bt; + for (unsigned i = 0; i < samples_per_sym * L; i++) { + double k = i - Ls/2; // Causal to acausal + taps_d[i] = (erf(alpha * (k / samples_per_sym + 0.5)) - + erf(alpha * (k / samples_per_sym - 0.5))) + * 0.5 / samples_per_sym; + taps[i] = (float) taps_d[i]; + } + + return taps; +} + + +std::vector<float> +gr_cpm::phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta) +{ + switch (type) { + case LRC: + return generate_cpm_lrc_taps(samples_per_sym, L); + + case LSRC: + return generate_cpm_lsrc_taps(samples_per_sym, L, beta); + + case LREC: + return generate_cpm_lrec_taps(samples_per_sym, L); + + case TFM: + return generate_cpm_tfm_taps(samples_per_sym, L); + + case GAUSSIAN: + return generate_cpm_gaussian_taps(samples_per_sym, L, beta); + + default: + return generate_cpm_lrec_taps(samples_per_sym, 1); + } +} + diff --git a/gnuradio-core/src/lib/general/gr_cpm.h b/gnuradio-core/src/lib/general/gr_cpm.h new file mode 100644 index 000000000..ef2ff8414 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * 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_CPM_H +#define INCLUDED_GR_CPM_H + +#include <gr_core_api.h> +#include <vector> + +class GR_CORE_API gr_cpm +{ + public: + enum cpm_type { + LRC, + LSRC, + LREC, + TFM, + GAUSSIAN, + GENERIC = 999 + }; + + /*! \brief Return the taps for an interpolating FIR filter (gr_interp_fir_filter_fff). + * + * These taps represent the phase response \f$g(k)\f$ for use in a CPM modulator, + * see also gr_cpmmod_bc. + * + * \param type The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine, + * Tamed FM or Gaussian). + * \param samples_per_sym Samples per symbol. + * \param L The length of the phase response in symbols. + * \param beta For Spectral Raised Cosine, this is the rolloff factor. For Gaussian + * phase responses, this the 3dB-time-bandwidth product. For all other + * cases, it is ignored. + * + * Output: returns a vector of length \a K = \p samples_per_sym x \p L. + * This can be used directly in an interpolating FIR filter such as + * gr_interp_fir_filter_fff with interpolation factor \p samples_per_sym. + * + * All phase responses are normalised s.t. \f$ \sum_{k=0}^{K-1} g(k) = 1\f$; this will cause + * a maximum phase change of \f$ h \cdot \pi\f$ between two symbols, where \a h is the + * modulation index. + * + * The following phase responses can be generated: + * - LREC: Rectangular phase response. + * - LRC: Raised cosine phase response, looks like 1 - cos(x). + * - LSRC: Spectral raised cosine. This requires a rolloff factor beta. + * The phase response is the Fourier transform of raised cosine + * function. + * - TFM: Tamed frequency modulation. This scheme minimizes phase change for + * rapidly varying input symbols. + * - GAUSSIAN: A Gaussian phase response. For a modulation index h = 1/2, this + * results in GMSK. + * + * A short description of all these phase responses can be found in [1]. + * + * [1]: Anderson, Aulin and Sundberg; Digital Phase Modulation + */ + static std::vector<float> + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + +#endif /* INCLUDED_GR_CPM_H */ + diff --git a/gnuradio-core/src/lib/general/gr_cpm.i b/gnuradio-core/src/lib/general/gr_cpm.i new file mode 100644 index 000000000..f01aba34e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.i @@ -0,0 +1,40 @@ +/* -*- C++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%rename(cpm) gr_cpm; + +class gr_cpm +{ + public: + enum cpm_type { + LRC, + LSRC, + LREC, + TFM, + GAUSSIAN, + GENERIC = 999 + }; + + static std::vector<float> + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + 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 c32398e6d..000000000 --- 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 e3007b97a..000000000 --- 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 c9c792c8a..000000000 --- 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 8659386d5..000000000 --- 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_ff.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc deleted file mode 100644 index 8a5e22c2f..000000000 --- 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_pll_carriertracking_cc.cc b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc index 1668f71f0..e8ec1e235 100644 --- a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.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 * @@ -30,22 +30,24 @@ #include <math.h> #include <gr_math.h> -#define M_TWOPI (2*M_PI) +#ifndef M_TWOPI +#define M_TWOPI (2.0f*M_PI) +#endif gr_pll_carriertracking_cc_sptr -gr_make_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq) +gr_make_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq) { - return gnuradio::get_initial_sptr(new gr_pll_carriertracking_cc (alpha, beta, max_freq, min_freq)); + return gnuradio::get_initial_sptr(new gr_pll_carriertracking_cc (loop_bw, max_freq, min_freq)); } -gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq) +gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq) : gr_sync_block ("pll_carriertracking_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), - d_locksig(0),d_lock_threshold(0),d_squelch_enable(false) + gri_control_loop(loop_bw, max_freq, min_freq), + d_locksig(0), d_lock_threshold(0), d_squelch_enable(false) { } @@ -72,7 +74,7 @@ gr_pll_carriertracking_cc::phase_detector(gr_complex sample,float ref_phase) bool gr_pll_carriertracking_cc::lock_detector(void) { - return (fabs(d_locksig) > d_lock_threshold); + return (fabsf(d_locksig) > d_lock_threshold); } bool @@ -99,19 +101,16 @@ gr_pll_carriertracking_cc::work (int noutput_items, float t_imag, t_real; for (int i = 0; i < noutput_items; i++){ - gr_sincosf(d_phase,&t_imag,&t_real); - optr[i] = iptr[i] * gr_complex(t_real,-t_imag); + gr_sincosf(d_phase, &t_imag, &t_real); + optr[i] = iptr[i] * gr_complex(t_real, -t_imag); error = phase_detector(iptr[i],d_phase); - - d_freq = d_freq + d_beta * error; - d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; - d_locksig = d_locksig * (1.0 - d_alpha) + + + advance_loop(error); + phase_wrap(); + frequency_limit(); + + d_locksig = d_locksig * (1.0 - d_alpha) + \ d_alpha*(iptr[i].real() * t_real + iptr[i].imag() * t_imag); if ((d_squelch_enable) && !lock_detector()) diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h index 27e74f111..db74bb101 100644 --- a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,206 Free Software Foundation, Inc. + * Copyright 2004,2006,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,12 +25,14 @@ #include <gr_core_api.h> #include <gr_sync_block.h> +#include <gri_control_loop.h> class gr_pll_carriertracking_cc; typedef boost::shared_ptr<gr_pll_carriertracking_cc> gr_pll_carriertracking_cc_sptr; -GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); +GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq); /*! * \brief Implements a PLL which locks to the input frequency and outputs the * input signal mixed with that carrier. @@ -42,19 +44,20 @@ GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float * the input and outputs that signal, downconverted to DC * * All settings max_freq and min_freq are in terms of radians per sample, - * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian) - * and beta is the frequency gain (second order, units of radians per sample per radian) + * NOT HERTZ. The loop bandwidth determins the lock range and should be set + * around pi/200 -- 2pi/100. * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc */ -class GR_CORE_API gr_pll_carriertracking_cc : public gr_sync_block +class GR_CORE_API gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop { - friend GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); + friend GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_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,d_locksig,d_lock_threshold; + float d_locksig,d_lock_threshold; bool d_squelch_enable; - gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq); + gr_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq); int work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i index 3e84fccbe..d309111b2 100644 --- a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_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 * @@ -23,13 +23,14 @@ GR_SWIG_BLOCK_MAGIC(gr,pll_carriertracking_cc); gr_pll_carriertracking_cc_sptr -gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); +gr_make_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq); -class gr_pll_carriertracking_cc : public gr_sync_block +class gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop { private: - gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq); + gr_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq); public: bool lock_detector(void); bool squelch_enable(bool); diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc index 997ba4042..aa0d67855 100644 --- a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.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 @@ -31,21 +29,21 @@ #include <math.h> #include <gr_math.h> -#define M_TWOPI (2*M_PI) +#ifndef M_TWOPI +#define M_TWOPI (2.0f*M_PI) +#endif gr_pll_freqdet_cf_sptr -gr_make_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq) +gr_make_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq) { - return gnuradio::get_initial_sptr(new gr_pll_freqdet_cf (alpha, beta, max_freq, min_freq)); + return gnuradio::get_initial_sptr(new gr_pll_freqdet_cf (loop_bw, max_freq, min_freq)); } -gr_pll_freqdet_cf::gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq) +gr_pll_freqdet_cf::gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq) : gr_sync_block ("pll_freqdet_cf", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature (1, 1, sizeof (float))), - d_alpha(alpha), d_beta(beta), - d_max_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) { } @@ -70,8 +68,8 @@ gr_pll_freqdet_cf::phase_detector(gr_complex sample,float ref_phase) int gr_pll_freqdet_cf::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *iptr = (gr_complex *) input_items[0]; float *optr = (float *) output_items[0]; @@ -84,13 +82,9 @@ gr_pll_freqdet_cf::work (int noutput_items, error = phase_detector(*iptr++,d_phase); - d_freq = d_freq + d_beta * error; - d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; + advance_loop(error); + phase_wrap(); + frequency_limit(); } return noutput_items; } diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h index 6ed1f99c2..336f3fd31 100644 --- a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.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 * @@ -25,12 +25,14 @@ #include <gr_core_api.h> #include <gr_sync_block.h> +#include <gri_control_loop.h> class gr_pll_freqdet_cf; typedef boost::shared_ptr<gr_pll_freqdet_cf> gr_pll_freqdet_cf_sptr; -GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, - float max_freq, float min_freq); +GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw, + float max_freq, + float min_freq); /*! * \brief Implements a PLL which locks to the input frequency and outputs * an estimate of that frequency. Useful for FM Demod. @@ -41,24 +43,24 @@ GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float be * This PLL locks onto a [possibly noisy] reference carrier on * the input and outputs an estimate of that frequency in radians per sample. * All settings max_freq and min_freq are in terms of radians per sample, - * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian) - * and beta is the frequency gain (second order, units of radians per sample per radian) + * NOT HERTZ. The loop bandwidth determins the lock range and should be set + * around pi/200 -- 2pi/100. * \sa gr_pll_refout_cc, gr_pll_carriertracking_cc */ -class GR_CORE_API gr_pll_freqdet_cf : public gr_sync_block +class GR_CORE_API gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop { - friend GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, - float max_freq, float min_freq); + friend GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (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_freqdet_cf (float alpha, float beta, float max_freq, float min_freq); + float mod_2pi (float in); + gr_pll_freqdet_cf (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); }; diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i index b730f037a..f93e6e37e 100644 --- a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.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,12 @@ GR_SWIG_BLOCK_MAGIC(gr,pll_freqdet_cf) - gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, - float max_freq, float min_freq); + gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw, + float max_freq, + float min_freq); -class gr_pll_freqdet_cf : public gr_sync_block +class gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop { private: - gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq); + gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq); }; 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 d01f28e45..dfd5079da 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 @@ -32,21 +30,21 @@ #include <math.h> #include <gr_math.h> -#define M_TWOPI (2*M_PI) +#ifndef M_TWOPI +#define M_TWOPI (2.0f*M_PI) +#endif 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) { } @@ -87,13 +85,9 @@ gr_pll_refout_cc::work (int noutput_items, error = phase_detector(*iptr++,d_phase); - d_freq = d_freq + d_beta * error; - d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); - - if (d_freq > d_max_freq) - d_freq = d_max_freq; - else if (d_freq < d_min_freq) - d_freq = d_min_freq; + advance_loop(error); + phase_wrap(); + frequency_limit(); } return noutput_items; } 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 833ed51cc..dcbeb1efa 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 @@ -44,24 +43,23 @@ GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta * aligned to it. * * All settings max_freq and min_freq are in terms of radians per sample, - * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian) - * and beta is the frequency gain (second order, units of radians per sample per radian) + * NOT HERTZ. The loop bandwidth determins the lock range and should be set + * around pi/200 -- 2pi/100. * \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 026a684ed..834ea1e36 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 000000000..4c64bb922 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.cc @@ -0,0 +1,187 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_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 000000000..3aeac58f7 --- /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 000000000..67f8838cb --- /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/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc index 6984d798c..b9080f362 100644 --- a/gnuradio-core/src/lib/general/qa_general.cc +++ b/gnuradio-core/src/lib/general/qa_general.cc @@ -28,6 +28,7 @@ #include <qa_general.h> #include <qa_gr_firdes.h> #include <qa_gr_circular_file.h> +#include <qa_gr_cpm.h> #include <qa_gr_fxpt.h> #include <qa_gr_fxpt_nco.h> #include <qa_gr_fxpt_vco.h> @@ -41,6 +42,7 @@ qa_general::suite () s->addTest (qa_gr_firdes::suite ()); s->addTest (qa_gr_circular_file::suite ()); + s->addTest (qa_gr_cpm::suite ()); s->addTest (qa_gr_fxpt::suite ()); s->addTest (qa_gr_fxpt_nco::suite ()); s->addTest (qa_gr_fxpt_vco::suite ()); diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc new file mode 100644 index 000000000..cc32d1117 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <qa_gr_cpm.h> +#include <gr_cpm.h> +#include <cppunit/TestAssert.h> + +const double DELTA = 1e-5; +const int L = 5; +const int samples_per_sym = 4; +const float taps_lrc[20] = { + 0, 0.002447174185242, 0.009549150281253, 0.020610737385376, + 0.034549150281253, 0.050000000000000, 0.065450849718747, 0.079389262614624, + 0.090450849718747, 0.097552825814758, 0.100000000000000, 0.097552825814758, + 0.090450849718747, 0.079389262614624, 0.065450849718747, 0.050000000000000, + 0.034549150281253, 0.020610737385376, 0.009549150281253, 0.002447174185242 +}; + + +const float taps_lsrc[20] = { // beta = 0.2 + 0.000000000000000, 0.009062686687436, 0.019517618142920, 0.030875041875917, + 0.042552315421249, 0.053912556756416, 0.064308860403517, 0.073130584159352, + 0.079847961304114, 0.084051371489937, 0.085482007518284, 0.084051371489937, + 0.079847961304114, 0.073130584159352, 0.064308860403517, 0.053912556756416, + 0.042552315421249, 0.030875041875917, 0.019517618142920, 0.009062686687436 +}; + + +const float taps_tfm[20] = { + -0.003946522220317, -0.005147757690530, -0.003171631690177, 0.003959659609805, + 0.017498721302356, 0.037346982678383, 0.062251889790391, 0.087364237065604, + 0.110049050955117, 0.125677762224511, 0.132288693729399, 0.125677762224511, + 0.110049050955117, 0.087364237065604, 0.062251889790391, 0.037346982678383, + 0.017498721302356, 0.003959659609805, -0.003171631690177, -0.005147757690530 +}; + + +const float taps_gaussian[20] = { // BT = 0.3 + 0.000000743866524, 0.000009286258371, 0.000085441834550, 0.000581664421923, + 0.002945540765422, 0.011178079812344, 0.032117220937421, 0.070841188736816, + 0.122053715366673, 0.167389736919915, 0.185594670675172, 0.167389736919915, + 0.122053715366673, 0.070841188736816, 0.032117220937421, 0.011178079812344, + 0.002945540765422, 0.000581664421923, 0.000085441834550, 0.000009286258371 +}; + + +// Check LREC phase response +void +qa_gr_cpm::t1 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LREC, samples_per_sym, L)); + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], 0.05, DELTA); + } +} + + +// Check LRC phase response +void +qa_gr_cpm::t2 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LRC, samples_per_sym, L)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_lrc[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check LSRC phase response +void +qa_gr_cpm::t3 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LSRC, samples_per_sym, L, 0.2)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_lsrc[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check the TFM phase response +void +qa_gr_cpm::t4 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::TFM, samples_per_sym, L)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_tfm[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check the Gaussian phase response +void +qa_gr_cpm::t5 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::GAUSSIAN, samples_per_sym, L, 0.3)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_gaussian[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i b/gnuradio-core/src/lib/general/qa_gr_cpm.h index 9a9f22b6e..741cb2860 100644 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,19 +19,31 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ +#ifndef _QA_GR_CPM_H +#define _QA_GR_CPM_H +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> -GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_cc) +class qa_gr_cpm : public CppUnit::TestCase { -gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); + CPPUNIT_TEST_SUITE (qa_gr_cpm); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST_SUITE_END (); -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); + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); + }; + + +#endif /* _QA_GR_CPM_H */ + diff --git a/gnuradio-core/src/lib/hier/Makefile.am b/gnuradio-core/src/lib/hier/Makefile.am index b525d19b4..369feef75 100644 --- a/gnuradio-core/src/lib/hier/Makefile.am +++ b/gnuradio-core/src/lib/hier/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2009 Free Software Foundation, Inc. +# Copyright 2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # diff --git a/gnuradio-core/src/lib/hier/hier.i b/gnuradio-core/src/lib/hier/hier.i index dbcc8e915..bec3de7ed 100644 --- a/gnuradio-core/src/lib/hier/hier.i +++ b/gnuradio-core/src/lib/hier/hier.i @@ -29,3 +29,4 @@ %} %include "gr_channel_model.i" + diff --git a/gnuradio-core/src/python/gnuradio/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/CMakeLists.txt index a65b01806..57bc91552 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 7d27386a4..289e37662 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 235cf35be..8b0baedd9 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 7b24fb69d..9665dde0b 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 67cf9f569..000000000 --- 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 55e4890f3..000000000 --- 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 d7bcf5390..000000000 --- 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 42d534168..000000000 --- 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 e1e627707..000000000 --- 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 908437ef2..000000000 --- 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 0bdb9c6fb..000000000 --- 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 fc455f17c..000000000 --- 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 5509f3745..000000000 --- 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 6a7b35597..000000000 --- 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 45c970227..7bf1c0827 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/gr/qa_pll_carriertracking.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py index 47f0ecb22..5977c1b52 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010 Free Software Foundation, Inc. +# Copyright 2004,2007,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -34,115 +34,114 @@ class test_pll_carriertracking (gr_unittest.TestCase): def test_pll_carriertracking (self): expected_result = ((1.00000238419+7.21919457547e-09j), (0.998025715351+0.062790453434j), - (0.992878139019+0.119114711881j), - (0.985585451126+0.16916936636j), - (0.976963579655+0.21341380477j), - (0.967643141747+0.252319812775j), - (0.958120942116+0.286356031895j), - (0.948766887188+0.315971136093j), - (0.939851403236+0.341586351395j), - (0.931558966637+0.363589793444j), - (0.924019515514+0.382339715958j), - (0.917312920094+0.398162424564j), - (0.9114767313+0.411352336407j), - (0.906515955925+0.422172755003j), - (0.902329206467+0.431043088436j), - (0.8989828825+0.437978446484j), - (0.896438419819+0.443168222904j), - (0.894643902779+0.446782171726j), - (0.893543541431+0.448972672224j), - (0.893085837364+0.449881345034j), - (0.893211960793+0.449634194374j), - (0.893862366676+0.448344886303j), - (0.894974172115+0.446114838123j), - (0.89649784565+0.443042784929j), - (0.898379862309+0.439216792583j), - (0.900570392609+0.434715718031j), - (0.902926802635+0.429791986942j), - (0.905423760414+0.424503326416j), - (0.908115327358+0.418716549873j), - (0.910964310169+0.412489384413j), - (0.913929581642+0.405871063471j), - (0.916985273361+0.398915469646j), - (0.920104384422+0.391668856144j), - (0.923261523247+0.384174525738j), - (0.926428377628+0.376470327377j), - (0.929587602615+0.3685952425j), - (0.932724237442+0.360585510731j), - (0.935822367668+0.352472603321j), - (0.938865244389+0.344285786152j), - (0.941773712635+0.336241692305j), - (0.944620370865+0.328158795834j), - (0.94739818573+0.32005661726j), - (0.950098872185+0.311952739954j), - (0.952714562416+0.303861320019j), - (0.955247402191+0.295800030231j), - (0.957694888115+0.287783116102j), - (0.960053324699+0.279822826385j), - (0.962315440178+0.271930038929j), - (0.96448802948+0.264117747545j), - (0.966570436954+0.256397068501j), - (0.968563258648+0.248777091503j), - (0.970409572124+0.241460204124j), - (0.972127914429+0.234440952539j), - (0.97377294302+0.227515518665j), - (0.975345790386+0.220690101385j), - (0.976839780807+0.213968709111j), - (0.978262722492+0.207358703017j), - (0.979616940022+0.200864806771j), - (0.980905056+0.194491744041j), - (0.982122182846+0.188243359327j), - (0.983273088932+0.18212479353j), - (0.984363257885+0.176140069962j), - (0.985394001007+0.170292437077j), - (0.986363172531+0.16458517313j), - (0.98724168539+0.159217983484j), - (0.988072276115+0.153976023197j), - (0.988858819008+0.148855358362j), - (0.989599764347+0.143855035305j), - (0.990294575691+0.138971716166j), - (0.990951240063+0.134203910828j), - (0.991572141647+0.129550367594j), - (0.992157161236+0.125009477139j), - (0.992702245712+0.120578929782j), - (0.993216574192+0.116259463131j), - (0.993701457977+0.112050771713j), - (0.994158565998+0.107951454818j), - (0.994559407234+0.104160495102j), - (0.9949182868+0.100662395358j), - (0.995259582996+0.0972395762801j), - (0.995584189892+0.0938917249441j), - (0.995885193348+0.0906178206205j), - (0.99616932869+0.0874189138412j), - (0.996438741684+0.0842954516411j), - (0.996694862843+0.0812477469444j), - (0.996931552887+0.0782764554024j), - (0.997152447701+0.0753828883171j), - (0.997361660004+0.0725681483746j), - (0.997559130192+0.0698337852955j), - (0.997741162777+0.067180365324j), - (0.99789583683+0.0648084580898j), - (0.998042702675+0.0624987781048j), - (0.998183488846+0.0602464973927j), - (0.998314678669+0.0580499768257j), - (0.998434245586+0.0559054017067j), - (0.998548746109+0.053810685873j), - (0.998658537865+0.0517641305923j), - (0.998762428761+0.0497645735741j), - (0.998855054379+0.0478102117777j), - (0.998943626881+0.0459015443921j), - (0.999028742313+0.0440383702517j)) + (0.992777824402+0.119947694242j), + (0.985192835331+0.171441286802j), + (0.976061582565+0.217501848936j), + (0.966034710407+0.258409559727j), + (0.95565611124+0.294477283955j), + (0.945357382298+0.326030552387j), + (0.935475051403+0.353395611048j), + (0.926258146763+0.376889169216j), + (0.917895197868+0.39681750536j), + (0.910515546799+0.413470208645j), + (0.904196679592+0.427117019892j), + (0.898972511292+0.438006043434j), + (0.894769787788+0.446523308754j), + (0.891652584076+0.452715367079j), + (0.8895829916+0.456773489714j), + (0.888502895832+0.458873122931j), + (0.888343691826+0.459175437689j), + (0.889035582542+0.457833081484j), + (0.890497922897+0.454985737801j), + (0.892645597458+0.450762689114j), + (0.895388305187+0.445282936096j), + (0.898648142815+0.438664674759j), + (0.902342617512+0.431016951799j), + (0.906392872334+0.422441422939j), + (0.910642921925+0.413191765547j), + (0.915039420128+0.403358519077j), + (0.919594764709+0.392864197493j), + (0.92425006628+0.381792247295j), + (0.928944349289+0.370217680931j), + (0.933634519577+0.358220815659j), + (0.938279032707+0.345874190331j), + (0.942840516567+0.333247303963j), + (0.947280526161+0.32040438056j), + (0.951574921608+0.307409763336j), + (0.955703914165+0.294323593378j), + (0.959648966789+0.281201630831j), + (0.963392794132+0.268095195293j), + (0.966880619526+0.255221515894j), + (0.970162451267+0.242447137833j), + (0.973235487938+0.229809194803j), + (0.97609680891+0.217341512442j), + (0.978744983673+0.20507311821j), + (0.981189727783+0.193033605814j), + (0.983436584473+0.181248426437j), + (0.985490739346+0.169738590717j), + (0.987353682518+0.158523857594j), + (0.989041447639+0.147622272372j), + (0.990563035011+0.137049794197j), + (0.991928339005+0.126818582416j), + (0.993117690086+0.117111675441j), + (0.994156062603+0.107930034399j), + (0.995076179504+0.0990980416536j), + (0.995887458324+0.0906178802252j), + (0.996591091156+0.0824909061193j), + (0.997202515602+0.0747182965279j), + (0.997730851173+0.0672992765903j), + (0.998185396194+0.0602316558361j), + (0.99856698513+0.0535135567188j), + (0.998885989189+0.0471420884132j), + (0.99915266037+0.0411129891872j), + (0.999372899532+0.0354214012623j), + (0.999548316002+0.0300626158714j), + (0.999680638313+0.0252036750317j), + (0.999784469604+0.020652115345j), + (0.999865531921+0.0163950324059j), + (0.999923825264+0.0124222636223j), + (0.999960243702+0.00872156023979j), + (0.999983668327+0.00528120994568j), + (0.999997138977+0.00209015607834j), + (1.00000119209-0.00086285173893j), + (0.999992132187-0.00358882546425j), + (0.999979138374-0.00609711557627j), + (0.999963641167-0.00839691981673j), + (0.999947249889-0.0104993218556j), + (0.999924004078-0.0122378543019j), + (0.999904811382-0.0136305987835j), + (0.999888062477-0.0148707330227j), + (0.9998742342-0.0159679055214j), + (0.999856114388-0.0169314742088j), + (0.999839782715-0.0177700817585j), + (0.999826967716-0.0184917747974j), + (0.999818325043-0.0191045701504j), + (0.999807476997-0.0196143388748j), + (0.999797284603-0.0200265944004j), + (0.999791204929-0.0203481912613j), + (0.99978852272-0.0205836892128j), + (0.99978530407-0.0207380950451j), + (0.999785065651-0.0206423997879j), + (0.999787807465-0.0204866230488j), + (0.999794304371-0.0202808082104j), + (0.999800384045-0.0200312435627j), + (0.999803245068-0.0197458267212j), + (0.9998087883-0.0194311738014j), + (0.999816894531-0.0190933048725j), + (0.999825954437-0.0187371373177j), + (0.999829888344-0.0183679759502j), + (0.999835848808-0.017987690866j), + (0.999844014645-0.0176006518304j)) sampling_freq = 10e3 freq = sampling_freq / 100 - alpha = 0.1 - beta = alpha * alpha / 4.0 + loop_bw = math.pi/100.0 maxf = 1 minf = -1 src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0) - pll = gr.pll_carriertracking_cc(alpha, beta, maxf, minf) + pll = gr.pll_carriertracking_cc(loop_bw, maxf, minf) head = gr.head (gr.sizeof_gr_complex, int (freq)) dst = gr.vector_sink_c () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py index a044ca4e3..152026c35 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010 Free Software Foundation, Inc. +# Copyright 2004,2007,2010,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -31,118 +31,117 @@ class test_pll_freqdet (gr_unittest.TestCase): def tearDown (self): self.tb = None - def test_pll_refout (self): + def test_pll_freqdet (self): expected_result = (0.0, - 1.1489677586e-07, - 0.972820967928, - 2.74556447638, - 5.14063115504, - 8.00965893424, - 11.2291407849, - 14.6967083575, - 18.3279143967, - 22.0534772463, - 25.8170063427, - 29.5729048372, - 33.28476877, - 36.923851464, - 40.4367920663, - 43.8452165447, - 47.1363805488, - 50.3011890178, - 53.3336388558, - 56.2301430274, - 58.9891659262, - 61.6107668417, - 64.0962975824, - 66.4481415997, - 68.6694590418, - 70.7640385293, - 72.7048794706, - 74.5033240115, - 76.2012544926, - 77.8019140677, - 79.3088126954, - 80.7255967005, - 82.0560428456, - 83.3039575383, - 84.473129399, - 85.5673470484, - 86.5902864563, - 87.5456176636, - 88.4368624865, - 89.2363977903, - 89.9861118444, - 90.6888920639, - 91.3474657813, - 91.9644713943, - 92.5423101413, - 93.0832765389, - 93.5894931633, - 94.0629225081, - 94.5054203452, - 94.9186882929, - 95.3043331057, - 95.6326268597, - 95.9117515522, - 96.1801447842, - 96.437391527, - 96.6831953314, - 96.9173605408, - 97.1397982206, - 97.3504727968, - 97.5493842694, - 97.7366275022, - 97.9123032879, - 98.0766013539, - 98.2297054988, - 98.3408027946, - 98.4487102971, - 98.5534280064, - 98.6549025616, - 98.7531576788, - 98.848110352, - 98.9397131494, - 99.0278712074, - 99.1124718752, - 99.193408431, - 99.2705445084, - 99.3437733855, - 99.3817366678, - 99.391110391, - 99.4089151289, - 99.4333959024, - 99.4630289627, - 99.4964565726, - 99.5325047932, - 99.5701419814, - 99.6084313579, - 99.6465902967, - 99.6838954618, - 99.7197776709, - 99.7537270313, - 99.7542606398, - 99.7595848672, - 99.7691305308, - 99.7823047325, - 99.7986450115, - 99.8176059012, - 99.838724941, - 99.8615040962, - 99.8854690481, - 99.910157336, - 99.9351302152) + 4.33888922882e-08, + 0.367369994515, + 1.08135249597, + 2.10983253908, + 3.42221529438, + 4.98940390402, + 6.78379190842, + 8.77923286024, + 10.9510106794, + 13.2758363182, + 15.7317829127, + 18.2982902299, + 20.9561068599, + 23.6755271122, + 26.452952094, + 29.2731265301, + 32.1219053479, + 34.9862418188, + 37.8540971414, + 40.7144315483, + 43.5571390869, + 46.3730179743, + 49.1537231663, + 51.8917218889, + 54.58026103, + 57.2015358514, + 59.7513664199, + 62.2380533124, + 64.657612252, + 67.006640002, + 69.2822432184, + 71.4820384499, + 73.6041047056, + 75.6469478817, + 77.6094829742, + 79.4909866472, + 81.2911031615, + 83.0097850853, + 84.6355598352, + 86.1820937186, + 87.6504420946, + 89.0418441206, + 90.3577286819, + 91.5996432431, + 92.7692775646, + 93.8684162704, + 94.8989269904, + 95.8627662892, + 96.7619381633, + 97.598505899, + 98.362769679, + 99.0579904444, + 99.6992633875, + 100.288805948, + 100.828805921, + 101.321421457, + 101.76878699, + 102.17300138, + 102.536116055, + 102.860158727, + 103.147085962, + 103.398830608, + 103.617254366, + 103.792467691, + 103.939387906, + 104.060030865, + 104.15631756, + 104.230085975, + 104.283067372, + 104.316933727, + 104.333238432, + 104.333440018, + 104.318914008, + 104.290941063, + 104.250742554, + 104.187634452, + 104.103822339, + 104.013227468, + 103.916810336, + 103.815448432, + 103.709936239, + 103.600997093, + 103.489283183, + 103.375351833, + 103.259712936, + 103.142828952, + 103.025091195, + 102.90686726, + 102.776726069, + 102.648078982, + 102.521459607, + 102.397294831, + 102.275999684, + 102.157882471, + 102.043215927, + 101.93218978, + 101.824958181, + 101.72159228, + 101.622151366) sampling_freq = 10e3 freq = sampling_freq / 100 - alpha = 0.2 - beta = alpha * alpha / 4.0 + loop_bw = math.pi/100.0 maxf = 1 minf = -1 src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0) - pll = gr.pll_freqdet_cf(alpha, beta, maxf, minf) + pll = gr.pll_freqdet_cf(loop_bw, maxf, minf) head = gr.head (gr.sizeof_float, int (freq)) dst = gr.vector_sink_f () @@ -154,7 +153,7 @@ class test_pll_freqdet (gr_unittest.TestCase): # convert it from normalized frequency to absolute frequency (Hz) dst_data = [i*(sampling_freq/(2*math.pi)) for i in dst_data] - + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 3) if __name__ == '__main__': diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py index c719d901d..4d82ed692 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py @@ -33,116 +33,115 @@ class test_pll_refout (gr_unittest.TestCase): def test_pll_refout (self): expected_result = ((1+0j), - (1+7.39965699825e-10j), - (0.999980390072+0.00626518437639j), - (0.999828696251+0.0185074303299j), - (0.999342679977+0.0362518914044j), - (0.998255133629+0.0590478256345j), - (0.996255218983+0.0864609181881j), - (0.993005692959+0.118066303432j), - (0.988157629967+0.153442293406j), - (0.981362581253+0.192165210843j), - (0.972283244133+0.233806177974j), - (0.960601866245+0.277928203344j), - (0.946027696133+0.324085712433j), - (0.928303182125+0.371824204922j), - (0.907292485237+0.420500129461j), - (0.882742881775+0.469856321812j), - (0.854515135288+0.519426465034j), - (0.822515428066+0.568742752075j), - (0.786696374416+0.617340147495j), - (0.747057676315+0.664759278297j), - (0.703645706177+0.710551023483j), - (0.656552672386+0.754280149937j), - (0.605915188789+0.795529305935j), - (0.551911652088+0.833902597427j), - (0.494760125875+0.869029581547j), - (0.43471467495+0.900568246841j), - (0.37224906683+0.928132891655j), - (0.307677358389+0.95149075985j), - (0.241136670113+0.970491170883j), - (0.17298206687+0.984924972057j), - (0.103586681187+0.99462044239j), - (0.0333374515176+0.999444127083j), - (-0.0373689383268+0.999301552773j), - (-0.108129791915+0.994136810303j), - (-0.178540587425+0.983932554722j), - (-0.248198464513+0.968709230423j), - (-0.316705435514+0.948523938656j), - (-0.383672863245+0.92346906662j), - (-0.448723107576+0.893670797348j), - (-0.511321544647+0.859389483929j), - (-0.571328163147+0.820721685886j), - (-0.628419756889+0.777874410152j), - (-0.682292759418+0.731079041958j), - (-0.73266518116+0.680589199066j), - (-0.779277086258+0.626679480076j), - (-0.821892678738+0.569642364979j), - (-0.860300958157+0.509786486626j), - (-0.894316911697+0.447434008121j), - (-0.923782110214+0.382918506861j), - (-0.948564827442+0.316582858562j), - (-0.968560934067+0.248776495457j), - (-0.983657181263+0.180051460862j), - (-0.993847966194+0.110752984881j), - (-0.999158382416+0.0410190448165j), - (-0.999585151672-0.0288016609848j), - (-0.995150506496-0.0983637422323j), - (-0.985901653767-0.167325690389j), - (-0.971909880638-0.235353350639j), - (-0.953269898891-0.302119880915j), - (-0.930099308491-0.367308050394j), - (-0.902536988258-0.430612236261j), - (-0.870742440224-0.491739332676j), - (-0.834894299507-0.550410330296j), - (-0.795189321041-0.606361210346j), - (-0.751972556114-0.659194409847j), - (-0.705345034599-0.708864152431j), - (-0.65554022789-0.755160212517j), - (-0.602804005146-0.79788929224j), - (-0.547393083572-0.836875617504j), - (-0.489574193954-0.871961593628j), - (-0.429622590542-0.903008520603j), - (-0.367820799351-0.929896712303j), - (-0.30445766449-0.952525854111j), - (-0.239826664329-0.970815718174j), - (-0.174224823713-0.984705924988j), - (-0.107951194048-0.994156181812j), - (-0.0415062084794-0.999138236046j), - (0.0248276274651-0.999691724777j), - (0.0909758731723-0.995853126049j), - (0.156649366021-0.987654268742j), - (0.221562758088-0.975146114826j), - (0.285434871912-0.958398103714j), - (0.34799093008-0.937497913837j), - (0.408963024616-0.912550985813j), - (0.468091547489-0.883679986j), - (0.525126516819-0.851024150848j), - (0.579828321934-0.814738690853j), - (0.631969094276-0.774993598461j), - (0.68133354187-0.731973052025j), - (0.727582633495-0.68602001667j), - (0.770699501038-0.637198805809j), - (0.810512304306-0.585721611977j), - (0.846863090992-0.531810939312j), - (0.879608631134-0.475698083639j), - (0.908620357513-0.417623102665j), - (0.933785498142-0.357833325863j), - (0.955007135868-0.29658266902j), - (0.972205162048-0.23413066566j), - (0.985315918922-0.170741200447j), - (0.994293212891-0.106681533158j)) + (1+6.4087357643e-10j), + (0.999985277653+0.00542619498447j), + (0.999868750572+0.0162021834403j), + (0.99948567152+0.0320679470897j), + (0.99860727787+0.0527590736747j), + (0.996953129768+0.0780025869608j), + (0.994203746319+0.107512556016j), + (0.990011692047+0.140985429287j), + (0.984013140202+0.178095817566j), + (0.975838363171+0.218493551016j), + (0.965121984482+0.261800557375j), + (0.95151245594+0.307610183954j), + (0.934681296349+0.355486690998j), + (0.914401650429+0.404808044434j), + (0.890356600285+0.455263823271j), + (0.862329125404+0.506348133087j), + (0.830152392387+0.557536482811j), + (0.793714106083+0.608290970325j), + (0.752960026264+0.658066213131j), + (0.707896590233+0.706316053867j), + (0.658591926098+0.752500295639j), + (0.605175673962+0.796091973782j), + (0.547837555408+0.836584687233j), + (0.48682525754+0.873499393463j), + (0.42244040966+0.906390726566j), + (0.355197101831+0.934791445732j), + (0.285494059324+0.958380460739j), + (0.213591173291+0.976923108101j), + (0.139945343137+0.990159213543j), + (0.065038472414+0.997882783413j), + (-0.0106285437942+0.999943494797j), + (-0.0865436866879+0.996248066425j), + (-0.162189796567+0.986759603024j), + (-0.23705175519+0.971496999264j), + (-0.310622543097+0.950533330441j), + (-0.38240903616+0.923993110657j), + (-0.451937526464+0.89204955101j), + (-0.518758952618+0.854920566082j), + (-0.582311093807+0.812966048717j), + (-0.642372369766+0.76639264822j), + (-0.698591887951+0.715520322323j), + (-0.750654160976+0.660695314407j), + (-0.798280358315+0.602286040783j), + (-0.841228663921+0.540679454803j), + (-0.87929558754+0.476276367903j), + (-0.912315964699+0.409486919641j), + (-0.940161883831+0.340728074312j), + (-0.962742805481+0.270418733358j), + (-0.980004072189+0.198977485299j), + (-0.991925954819+0.126818284392j), + (-0.99851256609+0.0545223206282j), + (-0.999846458435-0.0175215266645j), + (-0.996021270752-0.0891158208251j), + (-0.987133920193-0.159895718098j), + (-0.973306238651-0.2295101583j), + (-0.954683184624-0.297624111176j), + (-0.931430280209-0.363919824362j), + (-0.903732538223-0.428097635508j), + (-0.871792256832-0.489875763655j), + (-0.835827112198-0.548992812634j), + (-0.796068251133-0.605206847191j), + (-0.752758979797-0.658296227455j), + (-0.706152498722-0.70805978775j), + (-0.656641483307-0.754202902317j), + (-0.604367733002-0.79670548439j), + (-0.549597978592-0.835429251194j), + (-0.492602348328-0.870254516602j), + (-0.433654457331-0.901079237461j), + (-0.373029649258-0.927819430828j), + (-0.31100410223-0.950408577919j), + (-0.247853919864-0.968797445297j), + (-0.183855071664-0.982953369617j), + (-0.119282215834-0.992860376835j), + (-0.0544078871608-0.998518764973j), + (0.0104992967099-0.999944865704j), + (0.0749994292855-0.997183561325j), + (0.138844624162-0.990314185619j), + (0.201967850327-0.979392170906j), + (0.264124274254-0.964488625526j), + (0.325075358152-0.945688128471j), + (0.3845885396-0.92308807373j), + (0.442438393831-0.89679890871j), + (0.498407125473-0.866943061352j), + (0.552284479141-0.833655714989j), + (0.603869199753-0.797083437443j), + (0.652970373631-0.757383465767j), + (0.69940674305-0.714723825455j), + (0.743007957935-0.66928255558j), + (0.78350687027-0.62138313055j), + (0.820889055729-0.571087777615j), + (0.855021059513-0.51859331131j), + (0.885780930519-0.46410369873j), + (0.913058102131-0.407829582691j), + (0.936754107475-0.349988251925j), + (0.956783294678-0.290801793337j), + (0.973072886467-0.230497643352j), + (0.985563337803-0.169307261705j), + (0.9942086339-0.1074674353j), + (0.9989772439-0.0452152714133j)) sampling_freq = 10e3 freq = sampling_freq / 100 - alpha = 0.1 - beta = alpha * alpha / 4.0 + loop_bw = math.pi/100.0 maxf = 1 minf = -1 src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0) - pll = gr.pll_refout_cc(alpha, beta, maxf, minf) + pll = gr.pll_refout_cc(loop_bw, maxf, minf) head = gr.head (gr.sizeof_gr_complex, int (freq)) dst = gr.vector_sink_c () @@ -151,8 +150,7 @@ class test_pll_refout (gr_unittest.TestCase): self.tb.run () dst_data = dst.data () - - self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) if __name__ == '__main__': gr_unittest.run(test_pll_refout, "test_pll_refout.xml") diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt index 1863e96fd..aa9338764 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 ffae4b809..903bc2695 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/gnuradio-examples/python/digital/Makefile.am b/gnuradio-examples/python/digital/Makefile.am index e32180cd4..f9d129400 100644 --- a/gnuradio-examples/python/digital/Makefile.am +++ b/gnuradio-examples/python/digital/Makefile.am @@ -41,8 +41,4 @@ dist_ourdata_SCRIPTS = \ benchmark_tx.py \ benchmark_qt_rx.py \ benchmark_qt_loopback.py\ - gen_whitener.py \ - rx_voice.py \ - run_length.py \ - tunnel.py \ - tx_voice.py + tunnel.py
\ No newline at end of file diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt index cc00da69a..23bb48f94 100644 --- a/gr-digital/CMakeLists.txt +++ b/gr-digital/CMakeLists.txt @@ -32,7 +32,7 @@ GR_REGISTER_COMPONENT("gr-digital" ENABLE_GR_DIGITAL ) GR_SET_GLOBAL(GR_DIGITAL_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/lib + ${CMAKE_CURRENT_SOURCE_DIR}/include ) GR_SET_GLOBAL(GR_DIGITAL_SWIG_INCLUDE_DIRS @@ -81,11 +81,13 @@ CPACK_COMPONENT("digital_swig" ######################################################################## # Add subdirectories ######################################################################## +ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(lib) IF(ENABLE_PYTHON) ADD_SUBDIRECTORY(swig) ADD_SUBDIRECTORY(python) ADD_SUBDIRECTORY(grc) + ADD_SUBDIRECTORY(examples) ENDIF(ENABLE_PYTHON) ######################################################################## diff --git a/gr-digital/Makefile.am b/gr-digital/Makefile.am index 62c40f2df..b70d00d05 100644 --- a/gr-digital/Makefile.am +++ b/gr-digital/Makefile.am @@ -21,10 +21,10 @@ include $(top_srcdir)/Makefile.common -SUBDIRS = lib +SUBDIRS = include 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 000000000..d7028d40d --- /dev/null +++ b/gr-digital/examples/.gitignore @@ -0,0 +1,8 @@ +/Makefile +/Makefile.in +/*.8b +/*.16s +/*.16i +/*.32f +/*.32fc +/*.16sc diff --git a/gr-digital/examples/CMakeLists.txt b/gr-digital/examples/CMakeLists.txt new file mode 100644 index 000000000..f494d0f1e --- /dev/null +++ b/gr-digital/examples/CMakeLists.txt @@ -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(GrPython) + +GR_PYTHON_INSTALL(PROGRAMS + transmit_path.py + receive_path.py + benchmark_tx.py + benchmark_rx.py + tx_voice.py + rx_voice.py + run_length.py + gen_whitener.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/digital + COMPONENT "digital_python" +) diff --git a/gr-digital/examples/Makefile.am b/gr-digital/examples/Makefile.am new file mode 100644 index 000000000..4f745f3a9 --- /dev/null +++ b/gr-digital/examples/Makefile.am @@ -0,0 +1,42 @@ +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +ourdatadir = $(exampledir)/digital + +noinst_PYTHON = \ + example_costas.py \ + example_fll.py \ + example_timing.py + +dist_ourdata_SCRIPTS = \ + transmit_path.py \ + receive_path.py \ + uhd_interface.py \ + benchmark_tx.py \ + benchmark_rx.py \ + tx_voice.py \ + rx_voice.py \ + run_length.py \ + gen_whitener.py + + diff --git a/gr-digital/examples/benchmark_add_channel.py b/gr-digital/examples/benchmark_add_channel.py new file mode 100755 index 000000000..def1f8267 --- /dev/null +++ b/gr-digital/examples/benchmark_add_channel.py @@ -0,0 +1,101 @@ +#!/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 +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, math, sys + +class my_top_block(gr.top_block): + def __init__(self, ifile, ofile, options): + gr.top_block.__init__(self) + + SNR = 10.0**(options.snr/10.0) + frequency_offset = options.frequency_offset + time_offset = options.time_offset + phase_offset = options.phase_offset*(math.pi/180.0) + + # calculate noise voltage from SNR + # FIXME: normalize to signal amplitude + power_in_signal = abs(1.0)**2 + noise_power = power_in_signal/SNR + noise_voltage = math.sqrt(noise_power) + print noise_voltage + + self.src = gr.file_source(gr.sizeof_gr_complex, ifile) + #self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate) + self.channel = gr.channel_model(noise_voltage, frequency_offset, + time_offset, noise_seed=random.randint(0,100000)) + self.phase = gr.multiply_const_cc(complex(math.cos(phase_offset), + math.sin(phase_offset))) + self.snk = gr.file_sink(gr.sizeof_gr_complex, ofile) + + self.connect(self.src, self.channel, self.phase, self.snk) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + # Create Options Parser: + usage = "benchmack_add_channel.py [options] <input file> <output file>" + parser = OptionParser (usage=usage, option_class=eng_option, conflict_handler="resolve") + parser.add_option("-n", "--snr", type="eng_float", default=30, + help="set the SNR of the channel in dB [default=%default]") + parser.add_option("", "--seed", action="store_true", default=False, + help="use a random seed for AWGN noise [default=%default]") + parser.add_option("-f", "--frequency-offset", type="eng_float", default=0, + help="set frequency offset introduced by channel [default=%default]") + parser.add_option("-t", "--time-offset", type="eng_float", default=1.0, + help="set timing offset between Tx and Rx [default=%default]") + parser.add_option("-p", "--phase-offset", type="eng_float", default=0, + help="set phase offset (in degrees) between Tx and Rx [default=%default]") + parser.add_option("-m", "--use-multipath", action="store_true", default=False, + help="Use a multipath channel [default=%default]") + + (options, args) = parser.parse_args () + + if len(args) != 2: + parser.print_help(sys.stderr) + sys.exit(1) + + ifile = args[0] + ofile = args[1] + + # build the graph + tb = my_top_block(ifile, ofile, 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_rx.py b/gr-digital/examples/benchmark_rx.py new file mode 100755 index 000000000..7eb4fb9b4 --- /dev/null +++ b/gr-digital/examples/benchmark_rx.py @@ -0,0 +1,135 @@ +#!/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 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 +from uhd_interface import uhd_receiver + +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) + + if(options.tx_freq is not None): + self.source = uhd_receiver(options.address, options.bitrate, + options.samples_per_symbol, + options.rx_freq, options.rx_gain, + options.antenna, options.verbose) + options.samples_per_symbol = self.source._sps + + elif(options.from_file is not None): + self.source = gr.file_source(gr.sizeof_gr_complex, options.from_file) + else: + self.source = gr.null_source(gr.sizeof_gr_complex) + + # Set up receive path + # do this after for any adjustments to the options that may + # occur in the sinks (specifically the UHD sink) + self.rxpath = receive_path(demodulator, rx_callback, options) + + self.connect(self.source, 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) + uhd_receiver.add_options(parser) + + 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 000000000..a4396dd98 --- /dev/null +++ b/gr-digital/examples/benchmark_tx.py @@ -0,0 +1,150 @@ +#!/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 +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 +from uhd_interface import uhd_transmitter + +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) + + if(options.tx_freq is not None): + self.sink = uhd_transmitter(options.address, options.bitrate, + options.samples_per_symbol, + options.tx_freq, options.tx_gain, + options.antenna, options.verbose) + options.samples_per_symbol = self.sink._sps + + elif(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) + + # do this after for any adjustments to the options that may + # occur in the sinks (specifically the UHD sink) + self.txpath = transmit_path(modulator, options) + + 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) + uhd_transmitter.add_options(parser) + + 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.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 000000000..aef0196cc --- /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 000000000..3b75b5a75 --- /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 000000000..fd86acfb1 --- /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/gnuradio-examples/python/digital/gen_whitener.py b/gr-digital/examples/gen_whitener.py index 9a81e4eaa..9a81e4eaa 100755 --- a/gnuradio-examples/python/digital/gen_whitener.py +++ b/gr-digital/examples/gen_whitener.py diff --git a/gr-digital/examples/receive_path.py b/gr-digital/examples/receive_path.py new file mode 100644 index 000000000..1c5e58963 --- /dev/null +++ b/gr-digital/examples/receive_path.py @@ -0,0 +1,145 @@ +#!/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), + gr.io_signature(0, 0, 0)) + + 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 a packet arrives + 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=2, + 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/gnuradio-examples/python/digital/run_length.py b/gr-digital/examples/run_length.py index 5020655db..5020655db 100755 --- a/gnuradio-examples/python/digital/run_length.py +++ b/gr-digital/examples/run_length.py diff --git a/gnuradio-examples/python/digital/rx_voice.py b/gr-digital/examples/rx_voice.py index 1aad1ff8e..d29d64ed6 100755 --- a/gnuradio-examples/python/digital/rx_voice.py +++ b/gr-digital/examples/rx_voice.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2009 Free Software Foundation, Inc. +# Copyright 2005,2006,2009,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,8 +20,8 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, modulation_utils -from gnuradio import usrp +from gnuradio import gr +from gnuradio import uhd from gnuradio import audio from gnuradio import eng_notation from gnuradio.eng_option import eng_option @@ -29,12 +29,15 @@ from optparse import OptionParser from gnuradio.vocoder import gsm_full_rate +# From gr-digital +from gnuradio import digital + import random import struct import sys # from current dir -import usrp_receive_path +from receive_path import receive_path #import os #print os.getpid() @@ -47,11 +50,12 @@ class audio_tx(gr.hier_block2): gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature + sample_rate = 8000 self.packet_src = gr.message_source(33) voice_decoder = gsm_full_rate.decode_ps() s2f = gr.short_to_float () sink_scale = gr.multiply_const_ff(1.0/32767.) - audio_sink = audio.sink(8000, audio_output_dev) + audio_sink = audio.sink(sample_rate, audio_output_dev) self.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink) def msgq(self): @@ -61,9 +65,18 @@ class audio_tx(gr.hier_block2): class my_top_block(gr.top_block): def __init__(self, demod_class, rx_callback, options): gr.top_block.__init__(self) - self.rxpath = usrp_receive_path.usrp_receive_path(demod_class, rx_callback, options) + self.rxpath = receive_path(demod_class, rx_callback, options) self.audio_tx = audio_tx(options.audio_output) - self.connect(self.rxpath) + + if(options.from_file is not None): + self.thr = gr.throttle(gr.sizeof_gr_complex, options.bitrate) + 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) + self.connect(self.audio_tx) # ///////////////////////////////////////////////////////////////////////////// @@ -89,7 +102,7 @@ def main(): print "ok = %r n_rcvd = %4d n_right = %4d" % ( ok, n_rcvd, n_right) - demods = modulation_utils.type_1_demods() + demods = digital.modulation_utils2.type_1_demods() # Create Options Parser: parser = OptionParser (option_class=eng_option, conflict_handler="resolve") @@ -101,7 +114,9 @@ def main(): % (', '.join(demods.keys()),)) parser.add_option("-O", "--audio-output", type="string", default="", help="pcm output device name. E.g., hw:0,0 or /dev/dsp") - usrp_receive_path.add_options(parser, expert_grp) + 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) @@ -113,10 +128,11 @@ def main(): parser.print_help(sys.stderr) sys.exit(1) - 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) + 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 diff --git a/gr-digital/examples/transmit_path.py b/gr-digital/examples/transmit_path.py new file mode 100644 index 000000000..3af37f330 --- /dev/null +++ b/gr-digital/examples/transmit_path.py @@ -0,0 +1,121 @@ +# +# 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), + gr.io_signature(1,1,gr.sizeof_gr_complex)) + + 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=2, + 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/gnuradio-examples/python/digital/tx_voice.py b/gr-digital/examples/tx_voice.py index d8692beb4..f4f2c3a86 100755 --- a/gnuradio-examples/python/digital/tx_voice.py +++ b/gr-digital/examples/tx_voice.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc. +# Copyright 2005-2007,2009,2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,8 +20,8 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, modulation_utils -from gnuradio import usrp +from gnuradio import gr +from gnuradio import uhd from gnuradio import audio from gnuradio import eng_notation from gnuradio.eng_option import eng_option @@ -29,13 +29,16 @@ from optparse import OptionParser from gnuradio.vocoder import gsm_full_rate +# From gr-digital +from gnuradio import digital + import random import time import struct import sys # from current dir -import usrp_transmit_path +from transmit_path import transmit_path #import os #print os.getpid() @@ -64,11 +67,17 @@ class my_top_block(gr.top_block): def __init__(self, modulator_class, options): gr.top_block.__init__(self) - self.txpath = usrp_transmit_path.usrp_transmit_path(modulator_class, options) + self.txpath = transmit_path(modulator_class, options) self.audio_rx = audio_rx(options.audio_input) - self.connect(self.txpath) - self.connect(self.audio_rx) + 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.audio_rx) + self.connect(self.txpath, self.sink) + # ///////////////////////////////////////////////////////////////////////////// # main @@ -82,7 +91,7 @@ def main(): def rx_callback(ok, payload): print "ok = %r, payload = '%s'" % (ok, payload) - mods = modulation_utils.type_1_mods() + mods = digital.modulation_utils2.type_1_mods() parser = OptionParser(option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") @@ -95,7 +104,9 @@ def main(): help="set megabytes to transmit [default=inf]") parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp") - usrp_transmit_path.add_options(parser, expert_grp) + 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) @@ -107,11 +118,11 @@ def main(): parser.print_help() sys.exit(1) - 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.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) # build the graph tb = my_top_block(mods[options.modulation], options) diff --git a/gr-digital/examples/uhd_interface.py b/gr-digital/examples/uhd_interface.py new file mode 100644 index 000000000..3e2162ba3 --- /dev/null +++ b/gr-digital/examples/uhd_interface.py @@ -0,0 +1,215 @@ +#!/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, uhd +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import sys + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") + +class uhd_interface: + def __init__(self, istx, address, bitrate, sps, freq=None, + gain=None, antenna=None): + + if(istx): + self.u = uhd.usrp_sink(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + else: + self.u = uhd.usrp_source(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self._addr = address + self._ant = antenna + self._gain = self.set_gain(gain) + self._freq = self.set_freq(freq) + + self._rate, self._sps = self.set_sample_rate(bitrate, sps) + + if(antenna): + self.u.set_antenna(antenna, 0) + + def set_sample_rate(self, bitrate, req_sps): + start_sps = req_sps + while(True): + asked_samp_rate = bitrate * req_sps + self.u.set_samp_rate(asked_samp_rate) + actual_samp_rate = self.u.get_samp_rate() + + sps = actual_samp_rate/bitrate + if(sps < 2): + req_sps +=1 + else: + actual_sps = sps + break + + if(sps != req_sps): + print "\nBit Rate: %f" % (bitrate) + print "Requested sps: %f" % (start_sps) + print "Given sample rate: %f" % (actual_samp_rate) + print "Actual sps for rate: %f" % (actual_sps) + + if(actual_samp_rate != asked_samp_rate): + print "\nRequested sample rate: %f" % (asked_samp_rate) + print "Actual sample rate: %f" % (actual_samp_rate) + + return (actual_samp_rate, actual_sps) + + def set_gain(self, gain=None): + if gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + gain = float(g.start()+g.stop())/2 + print "\nNo gain specified." + print "Setting gain to %f (from [%f, %f])" % \ + (gain, g.start(), g.stop()) + + self.u.set_gain(gain, 0) + return gain + + def set_freq(self, freq=None): + if(freq is None): + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + sys.exit(1) + + r = self.u.set_center_freq(freq, 0) + if r: + return freq + else: + frange = self.u.get_freq_range() + sys.stderr.write(("\nRequested frequency (%f) out or range [%f, %f]\n") % \ + (freq, frange.start(), frange.stop())) + sys.exit(1) + +#-------------------------------------------------------------------# +# TRANSMITTER +#-------------------------------------------------------------------# + +class uhd_transmitter(uhd_interface, gr.hier_block2): + def __init__(self, address, bitrate, sps, freq=None, gain=None, + antenna=None, verbose=False): + gr.hier_block2.__init__(self, "uhd_transmitter", + gr.io_signature(1,1,gr.sizeof_gr_complex), + gr.io_signature(0,0,0)) + + # Set up the UHD interface as a transmitter + uhd_interface.__init__(self, True, address, bitrate, sps, + freq, gain, antenna) + + self.connect(self, self.u) + + if(verbose): + self._print_verbage() + + def add_options(parser): + add_freq_option(parser) + parser.add_option("-a", "--address", type="string", default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("", "--tx-freq", type="eng_float", default=None, + help="set transmit frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("", "--tx-gain", type="eng_float", default=None, + help="set transmit gain in dB (default is midpoint)") + parser.add_option("-v", "--verbose", action="store_true", default=False) + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the UHD transmitter + """ + print "\nUHD Transmitter:" + print "Address: %s" % (self._addr) + print "Freq: %sHz" % (eng_notation.num_to_str(self._freq)) + print "Gain: %f dB" % (self._gain) + print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate)) + print "Antenna: %s" % (self._ant) + + + +#-------------------------------------------------------------------# +# RECEIVER +#-------------------------------------------------------------------# + + +class uhd_receiver(uhd_interface, gr.hier_block2): + def __init__(self, address, bitrate, sps, freq=None, gain=None, + antenna=None, verbose=False): + gr.hier_block2.__init__(self, "uhd_receiver", + gr.io_signature(0,0,0), + gr.io_signature(1,1,gr.sizeof_gr_complex)) + + # Set up the UHD interface as a receiver + uhd_interface.__init__(self, False, address, bitrate, sps, + freq, gain, antenna) + + self.connect(self.u, self) + + if(verbose): + self._print_verbage() + + def add_options(parser): + add_freq_option(parser) + parser.add_option("-a", "--address", type="string", default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("", "--rx-freq", type="eng_float", default=None, + help="set receive frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("", "--rx-gain", type="eng_float", default=None, + help="set receive gain in dB (default is midpoint)") + parser.add_option("-v", "--verbose", action="store_true", default=False) + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the UHD transmitter + """ + print "\nUHD Receiver:" + print "Address: %s" % (self._addr) + print "Freq: %sHz" % (eng_notation.num_to_str(self._freq)) + print "Gain: %f dB" % (self._gain) + print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate)) + print "Antenna: %s" % (self._ant) + diff --git a/gr-digital/grc/CMakeLists.txt b/gr-digital/grc/CMakeLists.txt index b6c26b0db..89c6db6e2 100644 --- a/gr-digital/grc/CMakeLists.txt +++ b/gr-digital/grc/CMakeLists.txt @@ -19,10 +19,16 @@ INSTALL(FILES digital_block_tree.xml + digital_binary_slicer_fb.xml + digital_clock_recovery_mm_xx.xml + digital_constellation_decoder_cb.xml + digital_correlate_access_code_bb.xml digital_costas_loop_cc.xml digital_cma_equalizer_cc.xml - digital_lms_dd_equalizer_cc.xml + digital_fll_band_edge_cc.xml digital_kurtotic_equalizer_cc.xml + digital_lms_dd_equalizer_cc.xml + digital_mpsk_receiver_cc.xml digital_dxpsk_mod.xml digital_dxpsk_demod.xml digital_psk_mod.xml diff --git a/gr-digital/grc/Makefile.am b/gr-digital/grc/Makefile.am index d271ca06a..e4426e721 100644 --- a/gr-digital/grc/Makefile.am +++ b/gr-digital/grc/Makefile.am @@ -25,10 +25,16 @@ grcblocksdir = $(grc_blocksdir) dist_grcblocks_DATA = \ digital_block_tree.xml \ + digital_binary_slicer_fb.xml \ + digital_clock_recovery_mm_xx.xml \ + digital_constellation_decoder_cb.xml \ + digital_correlate_access_code_bb.xml \ digital_costas_loop_cc.xml \ digital_cma_equalizer_cc.xml \ - digital_lms_dd_equalizer_cc.xml \ + digital_fll_band_edge_cc.xml \ digital_kurtotic_equalizer_cc.xml \ + digital_lms_dd_equalizer_cc.xml \ + digital_mpsk_receiver_cc.xml \ digital_dxpsk_mod.xml \ digital_dxpsk_demod.xml \ digital_psk_mod.xml \ diff --git a/grc/blocks/gr_binary_slicer_fb.xml b/gr-digital/grc/digital_binary_slicer_fb.xml index 85d71e709..3187d13f9 100644 --- a/grc/blocks/gr_binary_slicer_fb.xml +++ b/gr-digital/grc/digital_binary_slicer_fb.xml @@ -6,9 +6,9 @@ --> <block> <name>Binary Slicer</name> - <key>gr_binary_slicer_fb</key> - <import>from gnuradio import gr</import> - <make>gr.binary_slicer_fb()</make> + <key>digital_binary_slicer_fb</key> + <import>from gnuradio import digital</import> + <make>digital.binary_slicer_fb()</make> <sink> <name>in</name> <type>float</type> diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml index 1be4110e1..088fe1c10 100644 --- a/gr-digital/grc/digital_block_tree.xml +++ b/gr-digital/grc/digital_block_tree.xml @@ -30,10 +30,16 @@ <name></name> <!-- Blank for Root Name --> <cat> <name>Digital</name> - <block>digital_costas_loop_cc</block> + <block>digital_binary_slicer_fb</block> + <block>digital_clock_recovery_mm_xx</block> <block>digital_cma_equalizer_cc</block> - <block>digital_lms_dd_equalizer_cc</block> + <block>digital_constellation_decoder_cb</block> + <block>digital_correlate_access_code_bb</block> + <block>digital_costas_loop_cc</block> + <block>digital_fll_band_edge_cc</block> <block>digital_kurtotic_equalizer_cc</block> + <block>digital_lms_dd_equalizer_cc</block> + <block>digital_mpsk_receiver_cc</block> </cat> <cat> <name>Digital Modulators</name> diff --git a/grc/blocks/gr_clock_recovery_mm_xx.xml b/gr-digital/grc/digital_clock_recovery_mm_xx.xml index 613cc23bf..d9c5ea4ff 100644 --- a/grc/blocks/gr_clock_recovery_mm_xx.xml +++ b/gr-digital/grc/digital_clock_recovery_mm_xx.xml @@ -6,9 +6,9 @@ --> <block> <name>Clock Recovery MM</name> - <key>gr_clock_recovery_mm_xx</key> - <import>from gnuradio import gr</import> - <make>gr.clock_recovery_mm_$(type.fcn)($omega, $gain_omega, $mu, $gain_mu, $omega_relative_limit)</make> + <key>digital_clock_recovery_mm_xx</key> + <import>from gnuradio import digital</import> + <make>digital.clock_recovery_mm_$(type.fcn)($omega, $gain_omega, $mu, $gain_mu, $omega_relative_limit)</make> <callback>set_omega($omega)</callback> <callback>set_gain_omega($gain_omega)</callback> <callback>set_mu($mu)</callback> diff --git a/grc/blocks/gr_constellation_decoder_cb.xml b/gr-digital/grc/digital_constellation_decoder_cb.xml index 99d897a3a..c7353e288 100644 --- a/grc/blocks/gr_constellation_decoder_cb.xml +++ b/gr-digital/grc/digital_constellation_decoder_cb.xml @@ -6,18 +6,13 @@ --> <block> <name>Constellation Decoder</name> - <key>gr_constellation_decoder_cb</key> - <import>from gnuradio import gr</import> - <make>gr.constellation_decoder_cb($sym_position, $sym_value_out)</make> + <key>digital_constellation_decoder_cb</key> + <import>from gnuradio import digital</import> + <make>digital.constellation_decoder_cb($constellation)</make> <param> - <name>Symbol Position</name> - <key>sym_position</key> - <type>complex_vector</type> - </param> - <param> - <name>Symbol Value Out</name> - <key>sym_value_out</key> - <type>int_vector</type> + <name>Constellation Object</name> + <key>constellation</key> + <type>raw</type> </param> <sink> <name>in</name> diff --git a/grc/blocks/gr_correlate_access_code_bb.xml b/gr-digital/grc/digital_correlate_access_code_bb.xml index e13d2d070..3941834c4 100644 --- a/grc/blocks/gr_correlate_access_code_bb.xml +++ b/gr-digital/grc/digital_correlate_access_code_bb.xml @@ -6,9 +6,9 @@ --> <block> <name>Correlate Access Code</name> - <key>gr_correlate_access_code_bb</key> - <import>from gnuradio import gr</import> - <make>gr.correlate_access_code_bb($access_code, $threshold)</make> + <key>digital_correlate_access_code_bb</key> + <import>from gnuradio import digital</import> + <make>digital.correlate_access_code_bb($access_code, $threshold)</make> <param> <name>Access Code</name> <key>access_code</key> diff --git a/gr-digital/grc/digital_costas_loop_cc.xml b/gr-digital/grc/digital_costas_loop_cc.xml index 087535b87..668c43dec 100644 --- a/gr-digital/grc/digital_costas_loop_cc.xml +++ b/gr-digital/grc/digital_costas_loop_cc.xml @@ -8,16 +8,10 @@ <name>Costas Loop</name> <key>digital_costas_loop_cc</key> <import>from gnuradio import digital</import> - <make>digital.costas_loop_cc($eta, $w, $order)</make> - <callback>set_damping_factor($eta)</callback> - <callback>set_natural_freq($w)</callback> + <make>digital.costas_loop_cc($w, $order)</make> + <callback>set_loop_bandwidth($w)</callback> <param> - <name>Damping Factor</name> - <key>eta</key> - <type>real</type> - </param> - <param> - <name>Natural Frequency</name> + <name>Loop Bandwidth</name> <key>w</key> <type>real</type> </param> diff --git a/gr-digital/grc/digital_dxpsk_mod.xml b/gr-digital/grc/digital_dxpsk_mod.xml index 5d59f36e0..fbda9fb1f 100644 --- a/gr-digital/grc/digital_dxpsk_mod.xml +++ b/gr-digital/grc/digital_dxpsk_mod.xml @@ -23,7 +23,7 @@ <!-- ################################################### -##DPSK2 Mod - 2, 4, 8 +## DPSK Mod - 2, 4, 8 ################################################### --> <block> @@ -33,7 +33,7 @@ <make>digital.$(type)_mod( samples_per_symbol=$samples_per_symbol, excess_bw=$excess_bw, - gray_code=$gray_code, + gray_coded=$gray_coded, verbose=$verbose, log=$log) </make> @@ -68,7 +68,7 @@ </param> <param> <name>Gray Code</name> - <key>gray_code</key> + <key>gray_coded</key> <value>True</value> <type>bool</type> <option> diff --git a/grc/blocks/gr_fll_band_edge_cc.xml b/gr-digital/grc/digital_fll_band_edge_cc.xml index 5a13ac49b..e4da773db 100644 --- a/grc/blocks/gr_fll_band_edge_cc.xml +++ b/gr-digital/grc/digital_fll_band_edge_cc.xml @@ -6,12 +6,10 @@ --> <block> <name>FLL Band-Edge</name> - <key>gr_fll_band_edge_cc</key> - <import>from gnuradio import gr</import> - <make>gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $alpha, $beta)</make> - <callback>set_alpha($alpha)</callback> - <callback>set_beta($beta)</callback> - + <key>digital_fll_band_edge_cc</key> + <import>from gnuradio import digital</import> + <make>digital.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $w)</make> + <callback>set_loop_bandwidth($w)</callback> <param> <name>Type</name> <key>type</key> @@ -41,15 +39,11 @@ </param> <param> - <name>Alpha</name> - <key>alpha</key> - <type>real</type> - </param> - <param> - <name>Beta</name> - <key>beta</key> + <name>Loop Bandwidth</name> + <key>w</key> <type>real</type> </param> + <sink> <name>in</name> <type>$type.input</type> diff --git a/grc/blocks/gr_mpsk_receiver_cc.xml b/gr-digital/grc/digital_mpsk_receiver_cc.xml index 843c3a4c1..ab7e5c209 100644 --- a/grc/blocks/gr_mpsk_receiver_cc.xml +++ b/gr-digital/grc/digital_mpsk_receiver_cc.xml @@ -6,11 +6,10 @@ --> <block> <name>MPSK Receiver</name> - <key>gr_mpsk_receiver_cc</key> - <import>from gnuradio import gr</import> - <make>gr.mpsk_receiver_cc($M, $theta, $alpha, $beta, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit)</make> - <callback>set_alpha($alpha)</callback> - <callback>set_beta($beta)</callback> + <key>digital_mpsk_receiver_cc</key> + <import>from gnuradio import digital</import> + <make>digital.mpsk_receiver_cc($M, $theta, $w, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit)</make> + <callback>set_loop_bandwidth($w)</callback> <callback>set_mu($mu)</callback> <callback>set_gain_mu($gain_mu)</callback> <callback>set_omega($omega)</callback> @@ -26,13 +25,8 @@ <type>real</type> </param> <param> - <name>Alpha</name> - <key>alpha</key> - <type>real</type> - </param> - <param> - <name>Beta</name> - <key>beta</key> + <name>Loop Bandwidth</name> + <key>w</key> <type>real</type> </param> <param> diff --git a/gr-digital/grc/digital_psk_mod.xml b/gr-digital/grc/digital_psk_mod.xml index f4566c2b4..34ed42c97 100644 --- a/gr-digital/grc/digital_psk_mod.xml +++ b/gr-digital/grc/digital_psk_mod.xml @@ -51,11 +51,11 @@ <type>enum</type> <option> <name>Yes</name> - <key>gray</key> + <key>"gray"</key> </option> <option> <name>No</name> - <key>none</key> + <key>"none"</key> </option> </param> <param> @@ -116,15 +116,10 @@ </param> <sink> <name>in</name> - <type>complex</type> + <type>byte</type> </sink> <source> <name>out</name> - <type>byte</type> - </source> - <source> - <name>sync</name> <type>complex</type> - <optional>1</optional> </source> </block> diff --git a/gr-digital/grc/digital_qam_mod.xml b/gr-digital/grc/digital_qam_mod.xml index 87782fe86..4d73d9a68 100644 --- a/gr-digital/grc/digital_qam_mod.xml +++ b/gr-digital/grc/digital_qam_mod.xml @@ -51,11 +51,11 @@ <type>enum</type> <option> <name>Yes</name> - <key>gray</key> + <key>"gray"</key> </option> <option> <name>No</name> - <key>none</key> + <key>"none"</key> </option> </param> <param> @@ -116,15 +116,10 @@ </param> <sink> <name>in</name> - <type>complex</type> + <type>byte</type> </sink> <source> <name>out</name> - <type>byte</type> - </source> - <source> - <name>sync</name> <type>complex</type> - <optional>1</optional> </source> </block> diff --git a/gr-digital/include/.gitignore b/gr-digital/include/.gitignore new file mode 100644 index 000000000..b336cc7ce --- /dev/null +++ b/gr-digital/include/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gr-digital/include/CMakeLists.txt b/gr-digital/include/CMakeLists.txt new file mode 100644 index 000000000..7b38e645b --- /dev/null +++ b/gr-digital/include/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install header files +######################################################################## +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 + digital_gmskmod_bc.h + digital_cpmmod_bc.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "digital_devel" +) diff --git a/gr-digital/include/Makefile.am b/gr-digital/include/Makefile.am new file mode 100644 index 000000000..346d036ce --- /dev/null +++ b/gr-digital/include/Makefile.am @@ -0,0 +1,45 @@ +# +# 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 + +# 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_mpsk_receiver_cc.h \ + digital_gmskmod_bc.h \ + digital_cpmmod_bc.h + +libgnuradio_digital_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS) diff --git a/gr-digital/lib/digital_api.h b/gr-digital/include/digital_api.h index d45ace13f..d45ace13f 100644 --- a/gr-digital/lib/digital_api.h +++ b/gr-digital/include/digital_api.h diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h b/gr-digital/include/digital_binary_slicer_fb.h index 45d8e6213..9da776012 100644 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h +++ b/gr-digital/include/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.h b/gr-digital/include/digital_clock_recovery_mm_cc.h index 292b066dc..e45b79229 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h +++ b/gr-digital/include/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.h b/gr-digital/include/digital_clock_recovery_mm_ff.h index 2b3346338..6f88a4dcd 100644 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h +++ b/gr-digital/include/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_cma_equalizer_cc.h b/gr-digital/include/digital_cma_equalizer_cc.h index 69e2f657a..69e2f657a 100644 --- a/gr-digital/lib/digital_cma_equalizer_cc.h +++ b/gr-digital/include/digital_cma_equalizer_cc.h diff --git a/gr-digital/lib/digital_constellation.h b/gr-digital/include/digital_constellation.h index df00f3898..9b2a58588 100644 --- a/gr-digital/lib/digital_constellation.h +++ b/gr-digital/include/digital_constellation.h @@ -42,8 +42,10 @@ typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr; class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation> { public: - digital_constellation (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, unsigned int dimensionality); + digital_constellation (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); digital_constellation (); //! Returns the constellation points for a symbol value @@ -74,6 +76,8 @@ public: std::vector<std::vector<gr_complex> > v_points(); //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding) bool apply_pre_diff_code() { return d_apply_pre_diff_code;} + //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding) + void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;} //! Returns the encoding to apply before differential encoding. std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;} //! Returns the order of rotational symmetry. @@ -82,7 +86,7 @@ public: unsigned int dimensionality() {return d_dimensionality;} unsigned int bits_per_symbol () { - return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0)); + return floor(log(d_constellation.size())/d_dimensionality/log(2)); } unsigned int arity () { @@ -120,17 +124,19 @@ typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_ // public constructor DIGITAL_API digital_constellation_calcdist_sptr -digital_make_constellation_calcdist (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, unsigned int dimensionality); +digital_make_constellation_calcdist (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); class DIGITAL_API digital_constellation_calcdist : public digital_constellation { public: digital_constellation_calcdist (std::vector<gr_complex> constellation, - std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality); + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); unsigned int decision_maker (const gr_complex *sample); // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type); // void calc_euclidean_metric(gr_complex *sample, float *metric); @@ -155,10 +161,10 @@ class DIGITAL_API digital_constellation_sector : public digital_constellation public: digital_constellation_sector (std::vector<gr_complex> constellation, - std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - unsigned int n_sectors); + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + unsigned int n_sectors); unsigned int decision_maker (const gr_complex *sample); @@ -194,19 +200,25 @@ typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect // public constructor DIGITAL_API digital_constellation_rect_sptr -digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, unsigned int imag_sectors, - float width_real_sectors, float width_imag_sectors); +digital_make_constellation_rect (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); class DIGITAL_API digital_constellation_rect : public digital_constellation_sector { public: - digital_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, unsigned int imag_sectors, - float width_real_sectors, float width_imag_sectors); + digital_constellation_rect (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); protected: @@ -222,10 +234,13 @@ class DIGITAL_API digital_constellation_rect : public digital_constellation_sect float d_width_imag_sectors; friend DIGITAL_API digital_constellation_rect_sptr - digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, unsigned int imag_sectors, - float width_real_sectors, float width_imag_sectors); + digital_make_constellation_rect (std::vector<gr_complex> constellation, + std::vector<unsigned int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); }; @@ -323,6 +338,33 @@ class DIGITAL_API digital_constellation_qpsk : public digital_constellation }; +/************************************************************/ +/* digital_constellation_dqpsk */ +/* */ +/* Works with differential encoding; slower decisions. */ +/* */ +/************************************************************/ + +//! \brief DQPSK-specific constellation and decision maker +class digital_constellation_dqpsk; +typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr; + +// public constructor +DIGITAL_API digital_constellation_dqpsk_sptr +digital_make_constellation_dqpsk (); + +class DIGITAL_API digital_constellation_dqpsk : public digital_constellation +{ + public: + + digital_constellation_dqpsk (); + unsigned int decision_maker (const gr_complex *sample); + + friend DIGITAL_API digital_constellation_dqpsk_sptr + digital_make_constellation_dqpsk (); + +}; + /************************************************************/ /* digital_constellation_8psk */ diff --git a/gr-digital/lib/digital_constellation_decoder_cb.h b/gr-digital/include/digital_constellation_decoder_cb.h index 1ce01fe12..1ce01fe12 100644 --- a/gr-digital/lib/digital_constellation_decoder_cb.h +++ b/gr-digital/include/digital_constellation_decoder_cb.h diff --git a/gr-digital/lib/digital_constellation_receiver_cb.h b/gr-digital/include/digital_constellation_receiver_cb.h index 36169d76b..d33be8958 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.h +++ b/gr-digital/include/digital_constellation_receiver_cb.h @@ -24,9 +24,9 @@ #define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_H #include <digital_api.h> -#include <gruel/attributes.h> #include <gr_block.h> #include <digital_constellation.h> +#include <gri_control_loop.h> #include <gr_complex.h> #include <math.h> #include <fstream> @@ -37,8 +37,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 @@ -66,41 +65,14 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation * */ -class DIGITAL_API digital_constellation_receiver_cb : public gr_block +class DIGITAL_API digital_constellation_receiver_cb : public gr_block, public gri_control_loop { - public: +public: int general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - - // 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; } - - //! (CL) Returns the current value of the frequency of the NCO in the Costas loop - float freq() const { return d_freq; } - - //! (CL) Returns the current value of the phase of the NCO in the Costal loop - float phase() const { return d_phase; } - - //! (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; } - - //! (CL) Sets the current value of the frequency of the NCO in the Costas loop - void set_freq(float freq) { d_freq = freq; } - - //! (CL) Setss the current value of the phase of the NCO in the Costal loop - void set_phase(float phase) { d_phase = phase; } - - protected: /*! @@ -116,20 +88,13 @@ 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); - private: +private: 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; - digital_constellation_sptr d_constellation; unsigned int d_current_const_point; @@ -137,15 +102,14 @@ 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; 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.h b/gr-digital/include/digital_correlate_access_code_bb.h index 8b5429e39..c4cb60428 100644 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h +++ b/gr-digital/include/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.h b/gr-digital/include/digital_costas_loop_cc.h index 099fca3be..c78726341 100644 --- a/gr-digital/lib/digital_costas_loop_cc.h +++ b/gr-digital/include/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/gr-digital/include/digital_cpmmod_bc.h b/gr-digital/include/digital_cpmmod_bc.h new file mode 100644 index 000000000..4e9547cd6 --- /dev/null +++ b/gr-digital/include/digital_cpmmod_bc.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 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_CPMMOD_BC_H +#define INCLUDED_DIGITAL_CPMMOD_BC_H + +#include <digital_api.h> +#include <gr_hier_block2.h> +#include <gr_char_to_float.h> +#include <gr_interp_fir_filter_fff.h> +#include <gr_frequency_modulator_fc.h> +#include <gr_cpm.h> + + +class digital_cpmmod_bc; +typedef boost::shared_ptr<digital_cpmmod_bc> digital_cpmmod_bc_sptr; + + +DIGITAL_API digital_cpmmod_bc_sptr +digital_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta=0.3); + +/*! + * \brief Generic CPM modulator + * + * \ingroup modulation_blk + * + * \param type The modulation type. Can be one of LREC, LRC, LSRC, TFM + * or GAUSSIAN. See gr_cpm::phase_response() for a + * detailed description. + * \param h The modulation index. \f$ h \cdot \pi\f$ is the maximum + * phase change that can occur between two symbols, i.e., if + * you only send ones, the phase will increase by \f$ h \cdot + * \pi\f$ every \p samples_per_sym samples. Set this to 0.5 + * for Minimum Shift Keying variants. + * \param samples_per_sym Samples per symbol. + * \param L The length of the phase duration in symbols. For L=1, this + * yields full- response CPM symbols, for L > 1, + * partial-response. + * \param beta For LSRC, this is the rolloff factor. For Gaussian + * pulses, this is the 3 dB time-bandwidth product. + * + * Examples: + * - Setting h = 0.5, L = 1, type = LREC yields MSK. + * - Setting h = 0.5, type = GAUSSIAN and beta = 0.3 yields GMSK + * as used in GSM. + * + * The input of this block are symbols from an M-ary alphabet + * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the + * valid inputs are +/-1. + * The modulator will silently accept any other inputs, though. + * The output is the phase-modulated signal. + */ +class DIGITAL_API digital_cpmmod_bc : public gr_hier_block2 +{ + friend DIGITAL_API digital_cpmmod_bc_sptr digital_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta); + + std::vector<float> d_taps; + gr_char_to_float_sptr d_char_to_float; + gr_interp_fir_filter_fff_sptr d_pulse_shaper; + gr_frequency_modulator_fc_sptr d_fm; + +protected: + digital_cpmmod_bc(gr_cpm::cpm_type type, float h, + unsigned samples_per_sym, + unsigned L, double beta); + +public: + //! Return the phase response FIR taps + std::vector<float> get_taps() { return d_taps; }; +}; + +#endif /* INCLUDED_DIGITAL_CPMMOD_BC_H */ + diff --git a/gnuradio-core/src/lib/general/gr_crc32.h b/gr-digital/include/digital_crc32.h index b59bf9cdc..852d06f49 100644 --- a/gnuradio-core/src/lib/general/gr_crc32.h +++ b/gr-digital/include/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/include/digital_fll_band_edge_cc.h b/gr-digital/include/digital_fll_band_edge_cc.h new file mode 100644 index 000000000..6ef8376ac --- /dev/null +++ b/gr-digital/include/digital_fll_band_edge_cc.h @@ -0,0 +1,213 @@ +/* -*- 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> +#include <gri_control_loop.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, public gri_control_loop +{ + 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; + + std::vector<gr_complex> d_taps_lower; + std::vector<gr_complex> d_taps_upper; + bool d_updated; + + /*! + * 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); + + /*! + * 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 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); + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \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; + + /*! + * 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/gr-digital/include/digital_gmskmod_bc.h b/gr-digital/include/digital_gmskmod_bc.h new file mode 100644 index 000000000..33fcc6c12 --- /dev/null +++ b/gr-digital/include/digital_gmskmod_bc.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 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_GMSKMOD_BC_H +#define INCLUDED_DIGITAL_GMSKMOD_BC_H + +#include <digital_api.h> +#include <digital_cpmmod_bc.h> + +class digital_gmskmod_bc; +typedef boost::shared_ptr<digital_gmskmod_bc> digital_gmskmod_bc_sptr; + + +DIGITAL_API digital_gmskmod_bc_sptr +digital_make_gmskmod_bc(unsigned samples_per_sym=2, + double bt=0.3, unsigned L=4); + +/*! + * \brief GMSK modulator + * + * \ingroup modulation_blk + * + * \param samples_per_sym Samples per symbol. + * \param bt The 3 dB time-bandwidth product. + * \param L The length of the phase duration in symbols. The Gaussian + * pulse is truncated after L symbols. + * + * The input of this block are symbols from an M-ary alphabet + * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the + * valid inputs are +/-1. + * The modulator will silently accept any other inputs, though. + * The output is the phase-modulated signal. + */ +class DIGITAL_API digital_gmskmod_bc : public digital_cpmmod_bc +{ + friend DIGITAL_API digital_gmskmod_bc_sptr digital_make_gmskmod_bc(unsigned samples_per_sym, + double bt, unsigned L); + digital_gmskmod_bc(unsigned samples_per_sym, + double bt, unsigned L); +}; + +#endif /* INCLUDED_DIGITAL_GMSKMOD_BC_H */ + diff --git a/gr-digital/lib/digital_kurtotic_equalizer_cc.h b/gr-digital/include/digital_kurtotic_equalizer_cc.h index c07862e11..c07862e11 100644 --- a/gr-digital/lib/digital_kurtotic_equalizer_cc.h +++ b/gr-digital/include/digital_kurtotic_equalizer_cc.h diff --git a/gr-digital/lib/digital_lms_dd_equalizer_cc.h b/gr-digital/include/digital_lms_dd_equalizer_cc.h index edfa18e23..edfa18e23 100644 --- a/gr-digital/lib/digital_lms_dd_equalizer_cc.h +++ b/gr-digital/include/digital_lms_dd_equalizer_cc.h diff --git a/gr-digital/lib/digital_metric_type.h b/gr-digital/include/digital_metric_type.h index 83de166f0..83de166f0 100644 --- a/gr-digital/lib/digital_metric_type.h +++ b/gr-digital/include/digital_metric_type.h diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h b/gr-digital/include/digital_mpsk_receiver_cc.h index 1a3f0792a..85cd81e99 100644 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h +++ b/gr-digital/include/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,61 +20,69 @@ * 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 <gri_control_loop.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 loop_bw, + 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 - * synchronization. + * \brief This block takes care of receiving M-PSK modulated signals + * through phase, frequency, and symbol synchronization. * \ingroup sync_blk * \ingroup demod_blk * - * This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol - * synchronization. It performs carrier frequency and phase locking as well as symbol timing recovery. - * It works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It should also work for OQPSK and - * PI/4 DQPSK. + * This block takes care of receiving M-PSK modulated signals through + * phase, frequency, and symbol synchronization. It performs carrier + * frequency and phase locking as well as symbol timing recovery. It + * works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It + * should also work for OQPSK and PI/4 DQPSK. * - * The phase and frequency synchronization are based on a Costas loop that finds the error of the incoming - * signal point compared to its nearest constellation point. The frequency and phase of the NCO are - * updated according to this error. There are optimized phase error detectors for BPSK and QPSK, but 8PSK - * is done using a brute-force computation of the constellation points to find the minimum. + * The phase and frequency synchronization are based on a Costas loop + * that finds the error of the incoming signal point compared to its + * nearest constellation point. The frequency and phase of the NCO are + * updated according to this error. There are optimized phase error + * detectors for BPSK and QPSK, but 8PSK is done using a brute-force + * computation of the constellation points to find the minimum. * - * The symbol synchronization is done using a modified Mueller and Muller circuit from the paper: + * The symbol synchronization is done using a modified Mueller and + * Muller circuit from the paper: * - * 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. + * 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. * - * This circuit interpolates the downconverted sample (using the NCO developed by the Costas loop) - * every mu samples, then it finds the sampling error based on this and the past symbols and the decision - * made on the samples. Like the phase error detector, there are optimized decision algorithms for BPSK - * and QPKS, but 8PSK uses another brute force computation against all possible symbols. The modifications - * to the M&M used here reduce self-noise. + * This circuit interpolates the downconverted sample (using the NCO + * developed by the Costas loop) every mu samples, then it finds the + * sampling error based on this and the past symbols and the decision + * made on the samples. Like the phase error detector, there are + * optimized decision algorithms for BPSK and QPKS, but 8PSK uses + * another brute force computation against all possible symbols. The + * modifications to the M&M used here reduce self-noise. * */ -class GR_CORE_API gr_mpsk_receiver_cc : public gr_block +class DIGITAL_API digital_mpsk_receiver_cc : public gr_block, public gri_control_loop { 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, @@ -112,43 +120,14 @@ class GR_CORE_API gr_mpsk_receiver_cc : public gr_block //! (M&M) Sets value for omega gain factor void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } - - - // 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; } - - //! (CL) Returns the current value of the frequency of the NCO in the Costas loop - float freq() const { return d_freq; } - - //! (CL) Returns the current value of the phase of the NCO in the Costal loop - float phase() const { return d_phase; } - - //! (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; } - - //! (CL) Sets the current value of the frequency of the NCO in the Costas loop - void set_freq(float freq) { d_freq = freq; } - - //! (CL) Setss the current value of the phase of the NCO in the Costal loop - void set_phase(float phase) { d_phase = phase; } - - protected: - - /*! + + /*! * \brief Constructor to synchronize incoming M-PSK symbols * * \param M modulation order of the M-PSK modulation * \param theta any constant phase rotation from the real axis of the constellation - * \param alpha gain parameter to adjust the phase in the Costas loop (~0.01) - * \param beta gain parameter to adjust the frequency in the Costas loop (~alpha^2/4) + * \param loop_bw Loop bandwidth to set gains of phase/freq tracking loop * \param fmin minimum normalized frequency value the loop can achieve * \param fmax maximum normalized frequency value the loop can achieve * \param mu initial parameter for the interpolator [0,1] @@ -160,11 +139,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 loop_bw, + 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); @@ -172,54 +151,61 @@ protected: void phase_error_tracking(gr_complex sample); -/*! + /*! * \brief Phase error detector for MPSK modulations. * * \param sample the I&Q sample from which to determine the phase error * - * This function determines the phase error for any MPSK signal by creating a set of PSK constellation points - * and doing a brute-force search to see which point minimizes the Euclidean distance. This point is then used - * to derotate the sample to the real-axis and a atan (using the fast approximation function) to determine the - * phase difference between the incoming sample and the real constellation point + * This function determines the phase error for any MPSK signal by + * creating a set of PSK constellation points and doing a + * brute-force search to see which point minimizes the Euclidean + * distance. This point is then used to derotate the sample to the + * real-axis and a atan (using the fast approximation function) to + * determine the phase difference between the incoming sample and + * the real constellation point * * This should be cleaned up and made more efficient. * * \returns the approximated phase error. - */ + */ float phase_error_detector_generic(gr_complex sample) const; // generic for M but more costly - /*! + /*! * \brief Phase error detector for BPSK modulation. * * \param sample the I&Q sample from which to determine the phase error * - * This function determines the phase error using a simple BPSK phase error detector by multiplying the real - * and imaginary (the error signal) components together. As the imaginary part goes to 0, so does this error. + * This function determines the phase error using a simple BPSK + * phase error detector by multiplying the real and imaginary (the + * error signal) components together. As the imaginary part goes to + * 0, so does this error. * * \returns the approximated phase error. - */ + */ float phase_error_detector_bpsk(gr_complex sample) const; // optimized for BPSK - /*! + /*! * \brief Phase error detector for QPSK modulation. * * \param sample the I&Q sample from which to determine the phase error * - * This function determines the phase error using the limiter approach in a standard 4th order Costas loop + * This function determines the phase error using the limiter + * approach in a standard 4th order Costas loop * * \returns the approximated phase error. - */ + */ float phase_error_detector_qpsk(gr_complex sample) const; - /*! + /*! * \brief Decision maker for a generic MPSK constellation. * * \param sample the baseband I&Q sample from which to make the decision * - * This decision maker is a generic implementation that does a brute-force search - * for the constellation point that minimizes the error between it and the incoming signal. + * This decision maker is a generic implementation that does a + * brute-force search for the constellation point that minimizes the + * error between it and the incoming signal. * * \returns the index to d_constellation that minimizes the error/ */ @@ -231,47 +217,45 @@ protected: * * \param sample the baseband I&Q sample from which to make the decision * - * This decision maker is a simple slicer function that makes a decision on the symbol based on its - * placement on the real axis of greater than 0 or less than 0; the quadrature component is always 0. + * This decision maker is a simple slicer function that makes a + * decision on the symbol based on its placement on the real axis of + * greater than 0 or less than 0; the quadrature component is always + * 0. * * \returns the index to d_constellation that minimizes the error/ - */ + */ unsigned int decision_bpsk(gr_complex sample) const; - /*! + /*! * \brief Decision maker for QPSK constellation. * * \param sample the baseband I&Q sample from which to make the decision * - * This decision maker is a simple slicer function that makes a decision on the symbol based on its - * placement versus both axes and returns which quadrant the symbol is in. + * This decision maker is a simple slicer function that makes a + * decision on the symbol based on its placement versus both axes + * and returns which quadrant the symbol is in. * * \returns the index to d_constellation that minimizes the error/ - */ + */ unsigned int decision_qpsk(gr_complex sample) const; - private: +private: unsigned int d_M; float d_theta; - // 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; - -/*! + /*! * \brief Decision maker function pointer * * \param sample the baseband I&Q sample from which to make the decision * - * This is a function pointer that is set in the constructor to point to the proper decision function - * for the specified constellation order. + * This is a function pointer that is set in the constructor to + * point to the proper decision function for the specified + * constellation order. * * \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; @@ -283,15 +267,16 @@ protected: gr_complex d_p_2T, d_p_1T, d_p_0T; gr_complex d_c_2T, d_c_1T, d_c_0T; - /*! + /*! * \brief Phase error detector function pointer * * \param sample the I&Q sample from which to determine the phase error * - * 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; + * 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 (digital_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const; //! get interpolated value @@ -306,12 +291,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 loop_bw, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, float omega_rel); }; #endif diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index 86e082b31..7cd89a56f 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/CMakeLists.txt @@ -32,13 +32,22 @@ 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 + digital_gmskmod_bc.cc + digital_cpmmod_bc.cc ) LIST(APPEND digital_libs @@ -56,20 +65,3 @@ INSTALL(TARGETS gnuradio-digital ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT "digital_devel" # .lib file RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT "digital_runtime" # .dll file ) - -######################################################################## -# Install header files -######################################################################## -INSTALL(FILES - digital_api.h - digital_constellation.h - digital_constellation_receiver_cb.h - digital_constellation_decoder_cb.h - digital_costas_loop_cc.h - digital_cma_equalizer_cc.h - digital_lms_dd_equalizer_cc.h - digital_kurtotic_equalizer_cc.h - digital_metric_type.h - DESTINATION ${GR_INCLUDE_DIR}/gnuradio - COMPONENT "digital_devel" -) diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am index 1cdb27a38..17baf2101 100644 --- a/gr-digital/lib/Makefile.am +++ b/gr-digital/lib/Makefile.am @@ -21,30 +21,28 @@ include $(top_srcdir)/Makefile.common -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) - -# These headers get installed in ${prefix}/include/gnuradio -grinclude_HEADERS = \ - digital_api.h \ - digital_constellation.h \ - digital_constellation_receiver_cb.h \ - digital_constellation_decoder_cb.h \ - digital_costas_loop_cc.h \ - digital_cma_equalizer_cc.h \ - digital_lms_dd_equalizer_cc.h \ - digital_kurtotic_equalizer_cc.h \ - digital_metric_type.h +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \ + $(GR_DIGITAL_INCLUDES) $(WITH_INCLUDES) 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 \ + digital_gmskmod_bc.cc \ + digital_cpmmod_bc.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 ae8903abb..fcdb4291f 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_clock_recovery_mm_cc.cc b/gr-digital/lib/digital_clock_recovery_mm_cc.cc index 7c20f7fd9..198eb4b89 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_ff.cc b/gr-digital/lib/digital_clock_recovery_mm_ff.cc index bb5a27071..04057f0e9 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/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc index d1f218439..0c100f38e 100644 --- a/gr-digital/lib/digital_constellation.cc +++ b/gr-digital/lib/digital_constellation.cc @@ -411,6 +411,20 @@ digital_constellation_qpsk::digital_constellation_qpsk () d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO); d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO); d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO); + + /* + d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO); + d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO); + d_constellation[2] = gr_complex(SQRT_TWO, -SQRT_TWO); + d_constellation[3] = gr_complex(SQRT_TWO, -SQRT_TWO); + */ + + d_pre_diff_code.resize(4); + d_pre_diff_code[0] = 0x0; + d_pre_diff_code[1] = 0x2; + d_pre_diff_code[2] = 0x3; + d_pre_diff_code[3] = 0x1; + d_rotational_symmetry = 4; d_dimensionality = 1; calc_arity(); @@ -422,8 +436,80 @@ digital_constellation_qpsk::decision_maker(const gr_complex *sample) // Real component determines small bit. // Imag component determines big bit. return 2*(imag(*sample)>0) + (real(*sample)>0); + + /* + bool a = real(*sample) > 0; + bool b = imag(*sample) > 0; + if(a) { + if(b) + return 0x0; + else + return 0x1; + } + else { + if(b) + return 0x2; + else + return 0x3; + } + */ +} + + +/********************************************************************/ + + +digital_constellation_dqpsk_sptr +digital_make_constellation_dqpsk() +{ + return digital_constellation_dqpsk_sptr(new digital_constellation_dqpsk ()); } +digital_constellation_dqpsk::digital_constellation_dqpsk () +{ + // This constellation is not gray coded, which allows + // us to use differential encodings (through gr_diff_encode and + // gr_diff_decode) on the symbols. + d_constellation.resize(4); + d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO); + d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO); + d_constellation[2] = gr_complex(-SQRT_TWO, -SQRT_TWO); + d_constellation[3] = gr_complex(+SQRT_TWO, -SQRT_TWO); + + // Use this mapping to convert to gray code before diff enc. + d_pre_diff_code.resize(4); + d_pre_diff_code[0] = 0x0; + d_pre_diff_code[1] = 0x1; + d_pre_diff_code[2] = 0x3; + d_pre_diff_code[3] = 0x2; + d_apply_pre_diff_code = true; + + d_rotational_symmetry = 4; + d_dimensionality = 1; + calc_arity(); +} + +unsigned int +digital_constellation_dqpsk::decision_maker(const gr_complex *sample) +{ + // Slower deicison maker as we can't slice along one axis. + // Maybe there's a better way to do this, still. + + bool a = real(*sample) > 0; + bool b = imag(*sample) > 0; + if(a) { + if(b) + return 0x0; + else + return 0x3; + } + else { + if(b) + return 0x1; + else + return 0x2; + } +} digital_constellation_8psk_sptr digital_make_constellation_8psk() diff --git a/gr-digital/lib/digital_constellation_receiver_cb.cc b/gr-digital/lib/digital_constellation_receiver_cb.cc index 573c4e855..b9239962a 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.cc +++ b/gr-digital/lib/digital_constellation_receiver_cb.cc @@ -40,23 +40,21 @@ 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), + gri_control_loop(loop_bw, fmax, fmin), d_constellation(constellation), d_current_const_point(0) { @@ -67,17 +65,9 @@ digital_constellation_receiver_cb::digital_constellation_receiver_cb (digital_co void digital_constellation_receiver_cb::phase_error_tracking(float phase_error) { - d_freq += d_beta*phase_error; // adjust frequency based on error - d_phase += d_freq + d_alpha*phase_error; // adjust phase based on error - - // Make sure we stay within +-2pi - while(d_phase > M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase < -M_TWOPI) - d_phase += M_TWOPI; - - // Limit the frequency range - d_freq = gr_branchless_clip(d_freq, d_max_freq); + advance_loop(phase_error); + phase_wrap(); + frequency_limit(); #if VERBOSE_COSTAS printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n", @@ -113,10 +103,12 @@ digital_constellation_receiver_cb::general_work (int noutput_items, sample = in[i]; nco = gr_expj(d_phase); // get the NCO value for derotating the current sample sample = nco*sample; // get the downconverted symbol + sym_value = d_constellation->decision_maker_pe(&sample, &phase_error); - // phase_error = -arg(sample*conj(d_constellation->points()[sym_value])); phase_error_tracking(phase_error); // corrects phase and frequency offsets + out[i] = sym_value; + if(output_items.size() == 4) { out_err[i] = phase_error; out_phase[i] = d_phase; 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 15f673411..f21b57d92 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/gr-digital/lib/digital_costas_loop_cc.cc b/gr-digital/lib/digital_costas_loop_cc.cc index 5d98bde4c..370dc7e5c 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_cpmmod_bc.cc b/gr-digital/lib/digital_cpmmod_bc.cc new file mode 100644 index 000000000..a95b604d1 --- /dev/null +++ b/gr-digital/lib/digital_cpmmod_bc.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * 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_cpmmod_bc.h> +#include <gr_io_signature.h> + + +// Shared pointer constructor +digital_cpmmod_bc_sptr +digital_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta) +{ + return gnuradio::get_initial_sptr(new digital_cpmmod_bc((gr_cpm::cpm_type)type, + h, samples_per_sym, + L, beta)); +} + + +digital_cpmmod_bc::digital_cpmmod_bc(gr_cpm::cpm_type type, float h, + unsigned samples_per_sym, + unsigned L, double beta) + : gr_hier_block2("digital_cpmmod_bc", + gr_make_io_signature(1, 1, sizeof(char)), + gr_make_io_signature2(1, 1, sizeof(gr_complex), sizeof(float))), + d_taps(gr_cpm::phase_response(type, samples_per_sym, L, beta)), + d_char_to_float(gr_make_char_to_float()), + d_pulse_shaper(gr_make_interp_fir_filter_fff(samples_per_sym, d_taps)), + d_fm(gr_make_frequency_modulator_fc(M_PI * h)) +{ + switch (type) { + case gr_cpm::LRC: + case gr_cpm::LSRC: + case gr_cpm::LREC: + case gr_cpm::TFM: + case gr_cpm::GAUSSIAN: + break; + + default: + throw std::invalid_argument("invalid CPM type"); + } + + connect(self(), 0, d_char_to_float, 0); + connect(d_char_to_float, 0, d_pulse_shaper, 0); + connect(d_pulse_shaper, 0, d_fm, 0); + connect(d_fm, 0, self(), 0); +} + diff --git a/gnuradio-core/src/lib/general/gr_crc32.cc b/gr-digital/lib/digital_crc32.cc index d4e843528..8806d6e9c 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/gr-digital/lib/digital_fll_band_edge_cc.cc b/gr-digital/lib/digital_fll_band_edge_cc.cc new file mode 100644 index 000000000..05c092622 --- /dev/null +++ b/gr-digital/lib/digital_fll_band_edge_cc.cc @@ -0,0 +1,259 @@ +/* -*- 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)), + gri_control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym), -M_TWOPI*(2.0/samps_per_sym)), + 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; + + // Build the band edge filters + design_filter(d_sps, d_rolloff, d_filter_size); +} + +digital_fll_band_edge_cc::~digital_fll_band_edge_cc () +{ +} + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + +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); +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + +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; +} + + +/******************************************************************* +*******************************************************************/ + +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); + + advance_loop(error); + phase_wrap(); + frequency_limit(); + + if(output_items.size() == 4) { + frq[i] = d_freq; + phs[i] = d_phase; + err[i] = error; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc b/gr-digital/lib/digital_gmskmod_bc.cc index f80bfd518..e53e90037 100644 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc +++ b/gr-digital/lib/digital_gmskmod_bc.cc @@ -1,9 +1,9 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2010 Free Software Foundation, Inc. + * Copyright 2010 Free Software Foundation, Inc. * * This file is part of GNU Radio - * + * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) @@ -24,19 +24,21 @@ #include "config.h" #endif -#include <gr_cma_equalizer_cc.h> +#include <digital_gmskmod_bc.h> +#include <gr_io_signature.h> -gr_cma_equalizer_cc_sptr -gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu) +// Shared pointer constructor +digital_gmskmod_bc_sptr +digital_make_gmskmod_bc(unsigned samples_per_sym, + double bt, unsigned L) { - return gnuradio::get_initial_sptr(new gr_cma_equalizer_cc(num_taps, modulus, mu)); + return gnuradio::get_initial_sptr(new digital_gmskmod_bc(samples_per_sym, bt, L)); } -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) + +digital_gmskmod_bc::digital_gmskmod_bc(unsigned samples_per_sym, + double bt, unsigned L) + : digital_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt) { - if (num_taps > 0) - d_taps[0] = 1.0; } diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc b/gr-digital/lib/digital_mpsk_receiver_cc.cc index bc51c6769..363b86c9f 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,30 +39,32 @@ // Public constructor -gr_mpsk_receiver_cc_sptr -gr_make_mpsk_receiver_cc(unsigned int M, float theta, - float alpha, float beta, +digital_mpsk_receiver_cc_sptr +digital_make_mpsk_receiver_cc(unsigned int M, float theta, + float loop_bw, 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, - alpha, beta, - fmin, fmax, - mu, gain_mu, - omega, gain_omega, omega_rel)); + return gnuradio::get_initial_sptr(new digital_mpsk_receiver_cc (M, theta, + loop_bw, + fmin, fmax, + mu, gain_mu, + omega, gain_omega, + omega_rel)); } -gr_mpsk_receiver_cc::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::digital_mpsk_receiver_cc (unsigned int M, float theta, + float loop_bw, + float fmin, float fmax, + float mu, float gain_mu, + float omega, float gain_omega, + float omega_rel) : gr_block ("mpsk_receiver_cc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature (1, 1, sizeof (gr_complex))), + gri_control_loop(loop_bw, fmax, fmin), d_M(M), d_theta(theta), - d_alpha(alpha), d_beta(beta), d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0), d_current_const_point(0), d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega), d_omega_rel(omega_rel), d_max_omega(0), d_min_omega(0), @@ -90,29 +92,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 +123,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 +143,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 +172,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 +193,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 +201,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 +224,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,24 +261,16 @@ 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; // Make phase and frequency corrections based on sampled value phase_error = (*this.*d_phase_error_detector)(sample); - - d_freq += d_beta*phase_error; // adjust frequency based on error - d_phase += d_freq + d_alpha*phase_error; // adjust phase based on error - - // Make sure we stay within +-2pi - while(d_phase > M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase < -M_TWOPI) - d_phase += M_TWOPI; - // Limit the frequency range - d_freq = gr_branchless_clip(d_freq, d_max_freq); + advance_loop(phase_error); + phase_wrap(); + frequency_limit(); #if VERBOSE_COSTAS printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n", @@ -286,10 +280,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/gr-digital/python/CMakeLists.txt b/gr-digital/python/CMakeLists.txt index 194894c73..2d09a4945 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 392ce45c1..a33e4963d 100644 --- a/gr-digital/python/Makefile.am +++ b/gr-digital/python/Makefile.am @@ -32,23 +32,33 @@ digitaldir = $(grpythondir)/digital noinst_PYTHON = \ qa_digital.py \ + qa_binary_slicer_fb.py \ + qa_clock_recovery_mm.py \ + qa_cma_equalizer.py \ + qa_cpm.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 3d0be3865..0fc48cc79 100644 --- a/gr-digital/python/__init__.py +++ b/gr-digital/python/__init__.py @@ -22,11 +22,12 @@ # 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 gmsk import * from pkt import * +from crc import * +from packet_utils import * from modulation_utils2 import * diff --git a/gr-digital/python/bpsk.py b/gr-digital/python/bpsk.py index 6d2eb5d6d..58a8289a5 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 8f593cd51..8f593cd51 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 d31aca0ea..198ab059f 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 8bed395a7..46290faed 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 2e9b756e6..9e065263f 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 29afd5530..5e17d24bc 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 f8051db0a..dc69fc0b5 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,28 +38,29 @@ _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): """ Sets options common to both modulator and demodulator. """ 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="set the number of constellation points (must be a power of 2 for psk, power of 4 for QAM) [default=%default]") + parser.add_option("", "--non-differential", action="store_false", + dest="differential", + help="do not use differential encoding [default=False]") + 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", - help="do not use differential encoding [default=%default]") 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,19 +110,17 @@ 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 %f" % 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._constellation.apply_pre_diff_code(): + if gray_coded == True: self.symbol_mapper = gr.map_bb(self._constellation.pre_diff_code()) if differential: @@ -127,19 +129,20 @@ 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 blocks = [self, self.bytes2chunks] - if self._constellation.apply_pre_diff_code(): + if gray_coded == True: blocks.append(self.symbol_mapper) if differential: blocks.append(self.diffenc) @@ -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,10 @@ 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, + gray_coded=True, + freq_bw=_def_freq_bw, + timing_bw=_def_timing_bw, + phase_bw=_def_phase_bw, verbose=_def_verbose, log=_def_log): """ @@ -226,14 +229,14 @@ 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 gray_coded: turn gray coding on/off + @type gray_coded: bool + @param freq_bw: loop filter lock-in bandwidth + @type freq_bw: float + @param timing_bw: timing recovery 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,53 +250,46 @@ 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) + fll_ntaps = 55 + self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, + fll_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 if differential: self.diffdec = gr.diff_decoder_bb(arity) - if self._constellation.apply_pre_diff_code(): + if gray_coded: self.symbol_mapper = gr.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) @@ -305,9 +301,10 @@ class generic_demod(gr.hier_block2): if log: self._setup_logging() - + # Connect and Initialize base class - blocks = [self, self.agc, self.freq_recov, self.time_recov, self.receiver] + blocks = [self, self.agc, self.freq_recov, + self.time_recov, self.receiver] if differential: blocks.append(self.diffdec) if self._constellation.apply_pre_diff_code(): @@ -325,49 +322,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 +370,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 3b6c016a0..ba122821e 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/gmsk.py +++ b/gr-digital/python/gmsk.py @@ -25,7 +25,9 @@ # See gnuradio-examples/python/digital for examples from gnuradio import gr -from gnuradio import modulation_utils +import digital_swig +import modulation_utils2 + from math import pi import numpy from pprint import pprint @@ -37,11 +39,9 @@ _def_bt = 0.35 _def_verbose = False _def_log = False -_def_gain_mu = None -_def_mu = 0.5 -_def_freq_error = 0.0 -_def_omega_relative_limit = 0.005 - +# Symbol timing recovery +_def_timing_bw = 2*pi/100.0 +_def_timing_max_dev = 1.5 # ///////////////////////////////////////////////////////////////////////////// # GMSK modulator @@ -79,7 +79,8 @@ class gmsk_mod(gr.hier_block2): self._bt = bt if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,)) + raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % \ + (samples_per_symbol,)) ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2 @@ -128,11 +129,11 @@ class gmsk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.nrz, - gr.file_sink(gr.sizeof_float, "nrz.dat")) + gr.file_sink(gr.sizeof_float, "tx_gmsk_nrz.32f")) self.connect(self.gaussian_filter, - gr.file_sink(gr.sizeof_float, "gaussian_filter.dat")) + gr.file_sink(gr.sizeof_float, "tx_gmsk_gaussian_filter.32f")) self.connect(self.fmmod, - gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) + gr.file_sink(gr.sizeof_gr_complex, "tx_gmsk_fmmod.32fc")) def add_options(parser): @@ -148,7 +149,7 @@ class gmsk_mod(gr.hier_block2): """ Given command line options, create dictionary suitable for passing to __init__ """ - return modulation_utils.extract_kwargs_from_options(gmsk_mod.__init__, + return modulation_utils2.extract_kwargs_from_options(gmsk_mod.__init__, ('self',), options) extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) @@ -162,10 +163,8 @@ class gmsk_demod(gr.hier_block2): def __init__(self, samples_per_symbol=_def_samples_per_symbol, - gain_mu=_def_gain_mu, - mu=_def_mu, - omega_relative_limit=_def_omega_relative_limit, - freq_error=_def_freq_error, + bt=_def_bt, + timing_bw=_def_timing_bw, verbose=_def_verbose, log=_def_log): """ @@ -177,21 +176,12 @@ class gmsk_demod(gr.hier_block2): @param samples_per_symbol: samples per baud @type samples_per_symbol: integer + @param timing_bw: timing recovery loop lock-in bandwidth + @type timing_bw: float @param verbose: Print information about modulator? @type verbose: bool @param log: Print modualtion data to files? @type log: bool - - Clock recovery parameters. These all have reasonble defaults. - - @param gain_mu: controls rate of mu adjustment - @type gain_mu: float - @param mu: fractional delay [0.0, 1.0] - @type mu: float - @param omega_relative_limit: sets max variation in omega - @type omega_relative_limit: float, typically 0.000200 (200 ppm) - @param freq_error: bit rate error as a fraction - @param float """ gr.hier_block2.__init__(self, "gmsk_demod", @@ -199,33 +189,31 @@ class gmsk_demod(gr.hier_block2): gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = samples_per_symbol - self._gain_mu = gain_mu - self._mu = mu - self._omega_relative_limit = omega_relative_limit - self._freq_error = freq_error + self._bt = bt + self._timing_bw = timing_bw + self._timing_max_dev= _def_timing_max_dev if samples_per_symbol < 2: raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol - self._omega = samples_per_symbol*(1+self._freq_error) - - if not self._gain_mu: - self._gain_mu = 0.175 - - self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped - # Demodulate FM sensitivity = (pi / 2) / samples_per_symbol self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity) # the clock recovery block tracks the symbol clock and resamples as needed. # the output of the block is a stream of soft symbols (float) - self.clock_recovery = gr.clock_recovery_mm_ff(self._omega, self._gain_omega, - self._mu, self._gain_mu, - self._omega_relative_limit) - + nfilts = 32 + ntaps = 11 * int(self._samples_per_symbol*nfilts) + taps = gr.firdes.gaussian(nfilts, + nfilts*self._samples_per_symbol, + self._bt, ntaps) + self.clock_recovery = \ + gr.pfb_clock_sync_fff(self._samples_per_symbol, + self._timing_bw, taps, + nfilts, nfilts//2, self._timing_max_dev) + # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample - self.slicer = gr.binary_slicer_fb() + self.slicer = digital_swig.binary_slicer_fb() if verbose: self._print_verbage() @@ -245,48 +233,38 @@ class gmsk_demod(gr.hier_block2): def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "M&M clock recovery omega = %f" % self._omega - print "M&M clock recovery gain mu = %f" % self._gain_mu - print "M&M clock recovery mu = %f" % self._mu - print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit - print "frequency error = %f" % self._freq_error + print "bits per symbol: %d" % self.bits_per_symbol() + print "Bandwidth-Time Prod: %f" % self._bw + print "Timing bandwidth: %.2e" % self._timing_bw def _setup_logging(self): print "Demodulation logging turned on." self.connect(self.fmdemod, - gr.file_sink(gr.sizeof_float, "fmdemod.dat")) + gr.file_sink(gr.sizeof_float, "rx_gmsk_fmdemod.32f")) self.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_float, "clock_recovery.dat")) + gr.file_sink(gr.sizeof_float, "rx_gmsk_clock_recovery.32f")) self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) + gr.file_sink(gr.sizeof_char, "rx_gmsk_slicer.8b")) def add_options(parser): """ Adds GMSK demodulation-specific options to the standard parser """ - parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu, - help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)") - parser.add_option("", "--mu", type="float", default=_def_mu, - help="M&M clock recovery mu [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)") - parser.add_option("", "--freq-error", type="float", default=_def_freq_error, - help="M&M clock recovery frequency error [default=%default] (GMSK)") + 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(options): """ Given command line options, create dictionary suitable for passing to __init__ """ - return modulation_utils.extract_kwargs_from_options(gmsk_demod.__init__, - ('self',), options) + return modulation_utils2.extract_kwargs_from_options(gmsk_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('gmsk', gmsk_mod) -modulation_utils.add_type_1_demod('gmsk', gmsk_demod) +modulation_utils2.add_type_1_mod('gmsk', gmsk_mod) +modulation_utils2.add_type_1_demod('gmsk', gmsk_demod) diff --git a/gnuradio-core/src/python/gnuradio/modulation_utils.py b/gr-digital/python/modulation_utils.py index 71ba77389..71ba77389 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 f30055f4a..cb3a9812d 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 e36b05413..2e216ff50 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 aa720d1a5..8650bdbb0 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 @@ -50,18 +52,13 @@ class mod_pkts(gr.hier_block2): @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 - @param modulate: If false, no modulation will be performed. See gmsk_mod for remaining parameters """ - if modulate: - output_size = gr.sizeof_gr_complex - else: - output_size = gr.sizeof_char gr.hier_block2.__init__(self, "mod_pkts", gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, output_size)) # Output signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._modulator = modulator self._pad_for_usrp = pad_for_usrp @@ -76,10 +73,7 @@ class mod_pkts(gr.hier_block2): # accepts messages from the outside world self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) - if modulate: - self.connect(self._pkt_input, self._modulator, self) - else: - self.connect(self._pkt_input, self) + self.connect(self._pkt_input, self._modulator, self) def send_pkt(self, payload='', eof=False): """ @@ -115,15 +109,13 @@ class demod_pkts(gr.hier_block2): app via the callback. """ - def __init__(self, demodulator, access_code=None, callback=None, threshold=-1, demodulate=True): + 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. - If demodulator is None it is assumed the input is already demodulated. - @param demodulator: instance of demodulator class (gr_block or hier_block2) @type demodulator: complex baseband in @param access_code: AKA sync vector @@ -134,14 +126,9 @@ class demod_pkts(gr.hier_block2): @type threshold: int """ - if demodulator is not None: - input_size = gr.sizeof_gr_complex - else: - input_size = gr.sizeof_char - gr.hier_block2.__init__(self, "demod_pkts", - gr.io_signature(1, 1, input_size), # Input signature - gr.io_signature(0, 0, 0)) # Output signature + 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: @@ -154,16 +141,12 @@ 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: - self.connect(self, self._demodulator, self.correlator, self.framer_sink) - else: - self.connect(self, self.correlator, self.framer_sink) + self.connect(self, self._demodulator, self.correlator, self.framer_sink) - if callback is not None: - self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) class _queue_watcher_thread(_threading.Thread): diff --git a/gr-digital/python/psk2.py b/gr-digital/python/psk2.py index 778c1e5e5..82781e63b 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 27e1802e0..944dc1b5a 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 000000000..5ef86eda0 --- /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 79e9cd092..75fb0f05e 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.py b/gr-digital/python/qa_constellation.py index 02afb8d2d..264ff7de6 100755 --- a/gr-digital/python/qa_constellation.py +++ b/gr-digital/python/qa_constellation.py @@ -70,10 +70,8 @@ tested_constellation_info = ( 'mod_code': tested_mod_codes, }, True, None), (digital_swig.constellation_bpsk, {}, True, None), - # No differential testing for qpsk because it is gray-coded. - # This is because soft decision making is simpler if we can assume - # gray coding. (digital_swig.constellation_qpsk, {}, False, None), + (digital_swig.constellation_dqpsk, {}, True, None), (digital_swig.constellation_8psk, {}, False, None), (twod_constell, {}, True, None), (threed_constell, {}, True, None), @@ -143,8 +141,8 @@ class test_constellation (gr_unittest.TestCase): class mod_demod(gr.hier_block2): def __init__(self, constellation, differential, rotation): if constellation.arity() > 256: - # If this becomes limiting some of the blocks should be generalised so that they can work - # with shorts and ints as well as chars. + # If this becomes limiting some of the blocks should be generalised so + # that they can work with shorts and ints as well as chars. raise ValueError("Constellation cannot contain more than 256 points.") gr.hier_block2.__init__(self, "mod_demod", @@ -174,7 +172,8 @@ class mod_demod(gr.hier_block2): if self.differential: self.blocks.append(gr.diff_encoder_bb(arity)) # Convert to constellation symbols. - self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality())) + self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), + self.constellation.dimensionality())) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: 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 000000000..5401a07fc --- /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 70b62c7aa..25107e4a7 100755 --- a/gr-digital/python/qa_constellation_receiver.py +++ b/gr-digital/python/qa_constellation_receiver.py @@ -22,13 +22,14 @@ 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 +import math # Set a seed so that if errors turn up they are reproducible. # 1234 fails @@ -37,7 +38,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 @@ -47,11 +48,8 @@ FREQUENCY_OFFSET = 0.01 TIMING_OFFSET = 1.0 # RECEIVER PARAMETERS -# Increased from normal default of 0.01 to speed things up. -FREQ_ALPHA = 0.02 -# Decreased from normal default of 0.1 is required for the constellations -# with smaller point separations. -PHASE_ALPHA = 0.02 +FREQ_BW = 2*math.pi/100.0 +PHASE_BW = 2*math.pi/100.0 class test_constellation_receiver (gr_unittest.TestCase): @@ -127,8 +125,8 @@ class rec_test_tb (gr.top_block): channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET) # Receiver Blocks demod = generic_demod(constellation, differential=differential, - freq_alpha=FREQ_ALPHA, - phase_alpha=PHASE_ALPHA) + freq_bw=FREQ_BW, + phase_bw=PHASE_BW) self.dst = gr.vector_sink_b() self.connect(src, packer, mod, channel, demod, self.dst) diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py b/gr-digital/python/qa_correlate_access_code.py index b3575f4e6..6b6f25051 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 368704093..124159dba 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_cpm.py b/gr-digital/python/qa_cpm.py new file mode 100755 index 000000000..12a84c76c --- /dev/null +++ b/gr-digital/python/qa_cpm.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# +# Copyright 2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with 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 numpy + +class test_cpm(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def do_check_phase_shift(self, type, name): + sps = 2 + L = 1 + in_bits = (1,) * 20 + src = gr.vector_source_b(in_bits, False) + cpm = digital_swig.cpmmod_bc(type, 0.5, sps, L) + arg = gr.complex_to_arg() + sink = gr.vector_sink_f() + + self.tb.connect(src, cpm, arg, sink) + self.tb.run() + + symbol_phases = numpy.array(sink.data()[sps*L-1::sps]) + phase_diff = numpy.mod(numpy.subtract(symbol_phases[1:], symbol_phases[:-1]), + (2*numpy.pi,) * (len(symbol_phases)-1)) + self.assertFloatTuplesAlmostEqual(tuple(phase_diff), (0.5 * numpy.pi,) * len(phase_diff), 5, + msg="Phase shift was not correct for CPM method " + name) + + def test_001_lrec(self): + self.do_check_phase_shift(gr.cpm.LRC, 'LREC') + + def test_001_lrc(self): + self.do_check_phase_shift(gr.cpm.LRC, 'LRC') + + def test_001_lsrc(self): + self.do_check_phase_shift(gr.cpm.LSRC, 'LSRC') + + def test_001_ltfm(self): + self.do_check_phase_shift(gr.cpm.TFM, 'TFM') + + def test_001_lgmsk(self): + sps = 2 + L = 5 + bt = 0.3 + in_bits = (1,) * 20 + src = gr.vector_source_b(in_bits, False) + gmsk = digital_swig.gmskmod_bc(sps, bt, L) + arg = gr.complex_to_arg() + sink = gr.vector_sink_f() + + self.tb.connect(src, gmsk, arg, sink) + self.tb.run() + + symbol_phases = numpy.array(sink.data()[sps*L-1::sps]) + phase_diff = numpy.mod(numpy.subtract(symbol_phases[1:], symbol_phases[:-1]), + (2*numpy.pi,) * (len(symbol_phases)-1)) + self.assertFloatTuplesAlmostEqual(tuple(phase_diff), (0.5 * numpy.pi,) * len(phase_diff), 5, + msg="Phase shift was not correct for GMSK") + + def test_phase_response(self): + phase_response = gr.cpm.phase_response(gr.cpm.LREC, 2, 4) + self.assertAlmostEqual(numpy.sum(phase_response), 1) + + +if __name__ == '__main__': + gr_unittest.run(test_cpm, "test_cpm.xml") + diff --git a/gr-digital/python/qa_crc32.py b/gr-digital/python/qa_crc32.py new file mode 100755 index 000000000..f86813f3f --- /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 100755 index 000000000..088eb2b68 --- /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 100755 index 000000000..025c785aa --- /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 100755 index 000000000..6531e59f7 --- /dev/null +++ b/gr-digital/python/qa_mpsk_receiver.py @@ -0,0 +1,121 @@ +#!/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 + loop_bw = cmath.pi/100.0 + 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, loop_bw, + 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:] + + #for e,d in zip(expected_result, dst_data): + # print e, d + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + + def test02 (self): + # Test QPSK sync + M = 4 + theta = 0 + loop_bw = 2*cmath.pi/100.0 + 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, loop_bw, + 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(0, -1.0), complex(1.0, 0), + complex(0, 1.0), complex(-1.0, 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:] + + #for e,d in zip(expected_result, dst_data): + # print e, d + + 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 ee2b1e416..a5a2e6c2c 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 ea1724424..481b7cb5b 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,114 @@ 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) + + + +# ///////////////////////////////////////////////////////////////////////////// +# DQPSK constellation +# ///////////////////////////////////////////////////////////////////////////// + +def dqpsk_constellation(m=_def_constellation_points): + if m != _def_constellation_points: + raise ValueError("DQPSK can only have 4 constellation points.") + return digital_swig.constellation_dqpsk() + +# ///////////////////////////////////////////////////////////////////////////// +# DQPSK modulator +# ///////////////////////////////////////////////////////////////////////////// + +class dqpsk_mod(generic_mod): + + def __init__(self, constellation_points=_def_constellation_points, + gray_coded=_def_gray_coded, + differential=True, *args, **kwargs): + """ + Hierarchical block for RRC-filtered DQPSK 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_dqpsk() + if constellation_points != 4: + raise ValueError('Number of constellation points must be 4 for DQPSK.') + super(dqpsk_mod, self).__init__(constellation=constellation, + gray_coded=gray_coded, + differential=True, + *args, **kwargs) + +# ///////////////////////////////////////////////////////////////////////////// +# DQPSK demodulator +# +# ///////////////////////////////////////////////////////////////////////////// + +class dqpsk_demod(generic_demod): + + def __init__(self, constellation_points=_def_constellation_points, + differential=True, *args, **kwargs): + + """ + Hierarchical block for RRC-filtered DQPSK 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_dqpsk() + if constellation_points != 4: + raise ValueError('Number of constellation points must be 4 for DQPSK.') + super(dqpsk_demod, self).__init__(constellation=constellation, + differential=True, + *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) +modulation_utils2.add_type_1_mod('dqpsk', dqpsk_mod) +modulation_utils2.add_type_1_demod('dqpsk', dqpsk_demod) +modulation_utils2.add_type_1_constellation('dqpsk', dqpsk_constellation) + diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt index a7374f0f0..307fba248 100644 --- a/gr-digital/swig/CMakeLists.txt +++ b/gr-digital/swig/CMakeLists.txt @@ -33,20 +33,29 @@ SET(GR_SWIG_LIBRARIES gnuradio-digital) GR_SWIG_MAKE(digital_swig digital_swig.i) GR_SWIG_INSTALL( - TARGETS digital_swig + TARGETS digital_hier digital_swig DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital COMPONENT "digital_python" ) 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 + digital_gmskmod_bc.i + digital_cpmmod_bc.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 b9ebf4cc5..abc24be19 100644 --- a/gr-digital/swig/Makefile.am +++ b/gr-digital/swig/Makefile.am @@ -26,8 +26,7 @@ TESTS = EXTRA_DIST += $(nobase_guile_DATA) AM_CPPFLAGS = \ - -I$(abs_top_srcdir)/gr-digital/lib \ - -I$(abs_top_builddir)/gr-digital/lib \ + $(GR_DIGITAL_INCLUDES) \ $(STD_DEFINES_AND_INCLUDES) \ $(PYTHON_CPPFLAGS) \ $(WITH_INCLUDES) @@ -58,17 +57,25 @@ 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_gmskmod_bc.i \ + digital_cpmmod_bc.i digital_swig_swig_args = \ - -I$(abs_top_srcdir)/gr-digital/lib \ - -I$(abs_top_builddir)/gr-digital/lib + $(GR_DIGITAL_INCLUDES) if GUILE TESTS += run_guile_tests diff --git a/gr-digital/swig/Makefile.swig.gen b/gr-digital/swig/Makefile.swig.gen index bd9aabcea..ff3eff4e9 100644 --- a/gr-digital/swig/Makefile.swig.gen +++ b/gr-digital/swig/Makefile.swig.gen @@ -101,8 +101,7 @@ _digital_swig_la_LDFLAGS = \ _digital_swig_la_CXXFLAGS = \ $(STD_SWIG_CXX_FLAGS) \ - -I$(top_builddir) \ - $(digital_swig_la_swig_cxxflags) + -I$(top_builddir) python/digital_swig.cc: digital_swig.py digital_swig.py: digital_swig.i @@ -141,5 +140,3 @@ gnuradio/digital_swig-primitive.scm: gnuradio/digital_swig.scm -include guile/digital_swig.d endif # end of GUILE - - diff --git a/gnuradio-core/src/lib/general/gr_crc32.i b/gr-digital/swig/_digital_hier.i index 7dca5c6a1..022e38644 100644 --- a/gnuradio-core/src/lib/general/gr_crc32.i +++ b/gr-digital/swig/_digital_hier.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,8 +20,14 @@ * Boston, MA 02110-1301, USA. */ -%rename(update_crc32) gr_update_crc32; -%rename(crc32) gr_crc32; +%{ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -unsigned int gr_update_crc32(unsigned int crc, const std::string buf); -unsigned int gr_crc32(const std::string buf); +#include <digital_cpmmod_bc.h> +#include <digital_gmskmod_bc.h> +%} + +%include "digital_cpmmod_bc.i" +%include "digital_gmskmod_bc.i" diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i b/gr-digital/swig/digital_binary_slicer_fb.i index b6f4e9312..30603748b 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 27eb70b95..4ce9a9725 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 1b2437000..054ef9ebf 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.i b/gr-digital/swig/digital_constellation.i index ae31d443e..7e0ad6afe 100644 --- a/gr-digital/swig/digital_constellation.i +++ b/gr-digital/swig/digital_constellation.i @@ -50,6 +50,7 @@ public: unsigned int arity (); digital_constellation_sptr base (); bool apply_pre_diff_code(); + void set_pre_diff_code(bool a); std::vector<unsigned int> pre_diff_code(); unsigned int rotational_symmetry(); unsigned int dimensionality(); @@ -152,6 +153,23 @@ public: digital_constellation_qpsk (); }; +/* + DQPSK Constellation +*/ + +class digital_constellation_dqpsk; +typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr; +%template(digital_constellation_dqpsk_sptr) boost::shared_ptr<digital_constellation_dqpsk>; +%rename(constellation_dqpsk) digital_make_constellation_dqpsk; +digital_constellation_dqpsk_sptr digital_make_constellation_dqpsk(); +%ignore digital_constellation_dqpsk; + +class digital_constellation_dqpsk : public digital_constellation +{ +public: + digital_constellation_dqpsk (); +}; + /* 8PSK Constellation diff --git a/gr-digital/swig/digital_constellation_receiver_cb.i b/gr-digital/swig/digital_constellation_receiver_cb.i index ad17ef371..9c4ba645e 100644 --- a/gr-digital/swig/digital_constellation_receiver_cb.i +++ b/gr-digital/swig/digital_constellation_receiver_cb.i @@ -26,22 +26,11 @@ 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 +class digital_constellation_receiver_cb : public gr_block, public gri_control_loop { private: digital_constellation_receiver_cb (digital_contellation_sptr constellation, - float alpha, float beta, - 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; } + float loop_bw, float fmin, float fmax); }; 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 bec4282f1..01087b8e9 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 6d3d009f8..ab09200a0 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/filter/gr_cma_equalizer_cc.i b/gr-digital/swig/digital_cpmmod_bc.i index 30e2fb8bd..fa7c50da7 100644 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i +++ b/gr-digital/swig/digital_cpmmod_bc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2009 Free Software Foundation, Inc. + * Copyright 2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,18 +20,21 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,cma_equalizer_cc) +GR_SWIG_BLOCK_MAGIC(digital, cpmmod_bc) -// retrieve info on the base class, without generating wrappers since -// the base class has a pure virual method. -%import "gr_adaptive_fir_ccf.i" +digital_cpmmod_bc_sptr +digital_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta=0.3); -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 +class digital_cpmmod_bc : public gr_hier_block2 { -private: - gr_cma_equalizer_cc(int num_taps, float modulus, float mu); - -public: + private: + digital_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta); + + public: + std::vector<float> get_taps(); }; + diff --git a/gr-digital/swig/digital_crc32.i b/gr-digital/swig/digital_crc32.i new file mode 100644 index 000000000..806bfad6a --- /dev/null +++ b/gr-digital/swig/digital_crc32.i @@ -0,0 +1,27 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +%rename(update_crc32) digital_update_crc32; +%rename(crc32) digital_crc32; + +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 000000000..3efcb89ed --- /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, public gri_control_loop +{ + 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_lms_dfe_ff.i b/gr-digital/swig/digital_gmskmod_bc.i index 3ca488b52..ad7b82237 100644 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i +++ b/gr-digital/swig/digital_gmskmod_bc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,15 +20,20 @@ * Boston, MA 02110-1301, USA. */ +GR_SWIG_BLOCK_MAGIC(digital, gmskmod_bc) -GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_ff) +digital_gmskmod_bc_sptr +digital_make_gmskmod_bc(unsigned samples_per_sym=2, + double bt=0.3, unsigned L=4); -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 +class digital_gmskmod_bc : public gr_hier_block2 { private: - gr_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); + digital_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + double beta, unsigned L); + + public: + std::vector<float> get_taps(); }; + diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i b/gr-digital/swig/digital_mpsk_receiver_cc.i index 88cb43e04..b51411f6f 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 loop_bw, + 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, public gri_control_loop { 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 loop_bw, + 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;} @@ -48,12 +49,4 @@ public: } void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } - 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; } }; diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index 26a9dd130..2e3a3242e 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -21,23 +21,43 @@ %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_cpmmod_bc.h" +#include "digital_gmskmod_bc.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" +%include "digital_cpmmod_bc.i" +%include "digital_gmskmod_bc.i" #if SWIGGUILE %scheme %{ diff --git a/gr-trellis/src/lib/Makefile.am b/gr-trellis/src/lib/Makefile.am index 2c50dd635..435a093d6 100644 --- a/gr-trellis/src/lib/Makefile.am +++ b/gr-trellis/src/lib/Makefile.am @@ -29,8 +29,9 @@ EXTRA_DIST += \ trellis.test -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) \ - -I$(abs_top_srcdir)/gr-digital/lib -I/home +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \ + $(GR_DIGITAL_INCLUDES) \ + $(WITH_INCLUDES) # ---------------------------------------------------------------- # these scripts generate trellis codes from template files @@ -166,8 +167,7 @@ BUILT_SOURCES += $(python_built_sources) # Location of non-standard SWIG interface files trellis_swig_args = \ - -I$(top_srcdir)/gr-digital/lib \ - -I$(top_srcdir)/gr-digital/swig + $(GR_DIGITAL_INCLUDES) if GUILE TESTS += run_guile_tests diff --git a/gr-utils/src/python/gr_plot_const.py b/gr-utils/src/python/gr_plot_const.py index 5dd08c9a0..8873e5b7e 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 True + 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/grc/blocks/Makefile.am b/grc/blocks/Makefile.am index a9f9427e9..9813154bd 100644 --- a/grc/blocks/Makefile.am +++ b/grc/blocks/Makefile.am @@ -30,10 +30,6 @@ dist_ourdata_DATA = \ blks2_analysis_filterbank.xml \ blks2_cvsd_encode.xml \ blks2_cvsd_decode.xml \ - blks2_dxpsk_demod.xml \ - blks2_dxpsk_mod.xml \ - blks2_dxpsk2_demod.xml \ - blks2_dxpsk2_mod.xml \ blks2_error_rate.xml \ blks2_fm_deemph.xml \ blks2_fm_demod_cf.xml \ @@ -71,12 +67,9 @@ dist_ourdata_DATA = \ gr_and_xx.xml \ gr_and_const_xx.xml \ gr_argmax_xx.xml \ - gr_binary_slicer_fb.xml \ gr_channel_model.xml \ gr_char_to_float.xml \ gr_chunks_to_symbols.xml \ - gr_clock_recovery_mm_xx.xml \ - gr_cma_equalizer_cc.xml \ gr_complex_to_arg.xml \ gr_complex_to_float.xml \ gr_complex_to_imag.xml \ @@ -85,13 +78,11 @@ dist_ourdata_DATA = \ gr_complex_to_mag_squared.xml \ gr_complex_to_real.xml \ gr_conjugate_cc.xml \ - gr_constellation_decoder_cb.xml \ gr_copy.xml \ - gr_correlate_access_code_bb.xml \ - gr_costas_loop_cc.xml \ gr_cpfsk_bc.xml \ gr_ctcss_squelch_ff.xml \ gr_dc_blocker.xml \ + gr_cpmmod_bc.xml \ gr_decode_ccsds_27_fb.xml \ gr_deinterleave.xml \ gr_delay.xml \ @@ -109,7 +100,6 @@ dist_ourdata_DATA = \ gr_file_source.xml \ gr_filter_delay_fc.xml \ gr_fir_filter_xxx.xml \ - gr_fll_band_edge_cc.xml \ gr_float_to_char.xml \ gr_float_to_complex.xml \ gr_float_to_short.xml \ @@ -118,6 +108,7 @@ dist_ourdata_DATA = \ gr_freq_xlating_fir_filter_xxx.xml \ gr_frequency_modulator_fc.xml \ gr_glfsr_source_x.xml \ + gr_gmskmod_bc.xml \ gr_goertzel_fc.xml \ gr_head.xml \ gr_hilbert_fc.xml \ @@ -135,7 +126,6 @@ dist_ourdata_DATA = \ gr_message_sink.xml \ gr_message_source.xml \ gr_moving_average_xx.xml \ - gr_mpsk_receiver_cc.xml \ gr_mpsk_sync_cc.xml \ gr_multiply_const_vxx.xml \ gr_multiply_xx.xml \ diff --git a/grc/blocks/blks2_dxpsk2_demod.xml b/grc/blocks/blks2_dxpsk2_demod.xml deleted file mode 100644 index 7fe4be32b..000000000 --- a/grc/blocks/blks2_dxpsk2_demod.xml +++ /dev/null @@ -1,152 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##DPSK2 Demod - 2, 4 -################################################### - --> -<block> - <name>DPSK2 Demod</name> - <key>blks2_dxpsk2_demod</key> - <import>from gnuradio import blks2</import> - <make>blks2.$(type)2_demod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - freq_alpha=$freq_alpha, - phase_alpha=$phase_alpha, - timing_alpha=$timing_alpha, - timing_max_dev=$timing_max_dev, - gray_code=$gray_code, - verbose=$verbose, - log=$log, - sync_out=$sync_out, -)</make> - <callback>clock_recov.set_alpha($costas_alpha)</callback> - <callback>clock_recov.set_beta(0.25*$costas_alpha**2)</callback> - <callback>time_recov.set_alpha($timing_alpha)</callback> - <param> - <name>Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>DBPSK</name> - <key>dbpsk</key> - </option> - <option> - <name>DQPSK</name> - <key>dqpsk</key> - </option> - </param> - <param> - <name>Samples/Symbol</name> - <key>samples_per_symbol</key> - <value>2</value> - <type>int</type> - </param> - <param> - <name>Excess BW</name> - <key>excess_bw</key> - <value>0.35</value> - <type>real</type> - </param> - <param> - <name>FLL Alpha</name> - <key>freq_alpha</key> - <value>0.010</value> - <type>real</type> - </param> - <param> - <name>Phase Alpha</name> - <key>phase_alpha</key> - <value>0.100</value> - <type>real</type> - </param> - <param> - <name>Timing Alpha</name> - <key>timing_alpha</key> - <value>0.100</value> - <type>real</type> - </param> - <param> - <name>Timing Max Dev</name> - <key>timing_max_dev</key> - <value>1.5</value> - <type>real</type> - </param> - <param> - <name>Omega Relative Limit</name> - <key>omega_relative_limit</key> - <value>0.005</value> - <type>real</type> - </param> - <param> - <name>Gray Code</name> - <key>gray_code</key> - <value>True</value> - <type>bool</type> - <option> - <name>Yes</name> - <key>True</key> - </option> - <option> - <name>No</name> - <key>False</key> - </option> - </param> - <param> - <name>Verbose</name> - <key>verbose</key> - <value>False</value> - <type>bool</type> - <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <param> - <name>Logging</name> - <key>log</key> - <value>False</value> - <type>bool</type> - <hide>#if str($log) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <param> - <name>Sync Out</name> - <key>sync_out</key> - <value>False</value> - <type>bool</type> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> - <source> - <name>sync</name> - <type>complex</type> - <optional>1</optional> - </source> -</block> diff --git a/grc/blocks/blks2_dxpsk2_mod.xml b/grc/blocks/blks2_dxpsk2_mod.xml deleted file mode 100644 index bf292be17..000000000 --- a/grc/blocks/blks2_dxpsk2_mod.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##DPSK2 Mod - 2, 4 -################################################### - --> -<block> - <name>DPSK2 Mod</name> - <key>blks2_dxpsk2_mod</key> - <import>from gnuradio import blks2</import> - <make>blks2.$(type)2_mod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - gray_code=$gray_code, - verbose=$verbose, - log=$log, -)</make> - <param> - <name>Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>DBPSK</name> - <key>dbpsk</key> - </option> - <option> - <name>DQPSK</name> - <key>dqpsk</key> - </option> - </param> - <param> - <name>Samples/Symbol</name> - <key>samples_per_symbol</key> - <value>2</value> - <type>int</type> - </param> - <param> - <name>Excess BW</name> - <key>excess_bw</key> - <value>0.35</value> - <type>real</type> - </param> - <param> - <name>Gray Code</name> - <key>gray_code</key> - <value>True</value> - <type>bool</type> - <option> - <name>Yes</name> - <key>True</key> - </option> - <option> - <name>No</name> - <key>False</key> - </option> - </param> - <param> - <name>Verbose</name> - <key>verbose</key> - <value>False</value> - <type>bool</type> - <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <param> - <name>Logging</name> - <key>log</key> - <value>False</value> - <type>bool</type> - <hide>#if str($log) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/blks2_dxpsk_demod.xml b/grc/blocks/blks2_dxpsk_demod.xml deleted file mode 100644 index 1c96b6cec..000000000 --- a/grc/blocks/blks2_dxpsk_demod.xml +++ /dev/null @@ -1,127 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##DPSK Demod - 2, 4, 8 -################################################### - --> -<block> - <name>DPSK Demod</name> - <key>blks2_dxpsk_demod</key> - <import>from gnuradio import blks2</import> - <make>blks2.$(type)_demod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - costas_alpha=$costas_alpha, - gain_mu=$gain_mu, - mu=$mu, - omega_relative_limit=$omega_relative_limit, - gray_code=$gray_code, - verbose=$verbose, - log=$log, -)</make> - <param> - <name>Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>DBPSK</name> - <key>dbpsk</key> - </option> - <option> - <name>DQPSK</name> - <key>dqpsk</key> - </option> - <option> - <name>D8PSK</name> - <key>d8psk</key> - </option> - </param> - <param> - <name>Samples/Symbol</name> - <key>samples_per_symbol</key> - <value>2</value> - <type>int</type> - </param> - <param> - <name>Excess BW</name> - <key>excess_bw</key> - <value>0.35</value> - <type>real</type> - </param> - <param> - <name>Costas Alpha</name> - <key>costas_alpha</key> - <value>0.175</value> - <type>real</type> - </param> - <param> - <name>Gain Mu</name> - <key>gain_mu</key> - <value>0.175</value> - <type>real</type> - </param> - <param> - <name>Mu</name> - <key>mu</key> - <value>0.5</value> - <type>real</type> - </param> - <param> - <name>Omega Relative Limit</name> - <key>omega_relative_limit</key> - <value>0.005</value> - <type>real</type> - </param> - <param> - <name>Gray Code</name> - <key>gray_code</key> - <value>True</value> - <type>bool</type> - <option> - <name>Yes</name> - <key>True</key> - </option> - <option> - <name>No</name> - <key>False</key> - </option> - </param> - <param> - <name>Verbose</name> - <key>verbose</key> - <value>False</value> - <type>bool</type> - <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <param> - <name>Logging</name> - <key>log</key> - <value>False</value> - <type>bool</type> - <hide>#if str($log) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/blks2_dxpsk_mod.xml b/grc/blocks/blks2_dxpsk_mod.xml deleted file mode 100644 index 77505d8ad..000000000 --- a/grc/blocks/blks2_dxpsk_mod.xml +++ /dev/null @@ -1,99 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##DPSK Mod - 2, 4, 8 -################################################### - --> -<block> - <name>DPSK Mod</name> - <key>blks2_dxpsk_mod</key> - <import>from gnuradio import blks2</import> - <make>blks2.$(type)_mod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - gray_code=$gray_code, - verbose=$verbose, - log=$log, -)</make> - <param> - <name>Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>DBPSK</name> - <key>dbpsk</key> - </option> - <option> - <name>DQPSK</name> - <key>dqpsk</key> - </option> - <option> - <name>D8PSK</name> - <key>d8psk</key> - </option> - </param> - <param> - <name>Samples/Symbol</name> - <key>samples_per_symbol</key> - <value>2</value> - <type>int</type> - </param> - <param> - <name>Excess BW</name> - <key>excess_bw</key> - <value>0.35</value> - <type>real</type> - </param> - <param> - <name>Gray Code</name> - <key>gray_code</key> - <value>True</value> - <type>bool</type> - <option> - <name>Yes</name> - <key>True</key> - </option> - <option> - <name>No</name> - <key>False</key> - </option> - </param> - <param> - <name>Verbose</name> - <key>verbose</key> - <value>False</value> - <type>bool</type> - <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <param> - <name>Logging</name> - <key>log</key> - <value>False</value> - <type>bool</type> - <hide>#if str($log) == 'False' then 'part' else 'none'#</hide> - <option> - <name>On</name> - <key>True</key> - </option> - <option> - <name>Off</name> - <key>False</key> - </option> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index f82d40f85..ea7d744d4 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -110,26 +110,19 @@ <block>gr_unpacked_to_packed_xx</block> <block>gr_packed_to_unpacked_xx</block> <block>gr_unpack_k_bits_bb</block> - <block>gr_binary_slicer_fb</block> <block>gr_chunks_to_symbols_xx</block> <block>gr_map_bb</block> </cat> <cat> <name>Synchronizers</name> - <block>gr_clock_recovery_mm_xx</block> <block>gr_pfb_clock_sync_xxx</block> - <block>gr_costas_loop_cc</block> <block>gr_mpsk_sync_cc</block> - <block>gr_mpsk_receiver_cc</block> <block>gr_pll_carriertracking_cc</block> <block>gr_pll_freqdet_cf</block> <block>gr_pll_refout_cc</block> - <block>gr_fll_band_edge_cc</block> - - <block>gr_correlate_access_code_bb</block> <block>gr_pn_correlator_cc</block> <block>gr_simple_correlator</block> <block>gr_simple_framer</block> @@ -182,7 +175,6 @@ <block>gr_single_pole_iir_filter_xx</block> <block>gr_hilbert_fc</block> <block>gr_goertzel_fc</block> - <block>gr_cma_equalizer_cc</block> <block>gr_rational_resampler_base_xxx</block> <block>blks2_rational_resampler_xxx</block> <block>gr_fractional_interpolator_xx</block> @@ -198,9 +190,10 @@ <block>gr_phase_modulator_fc</block> <block>gr_quadrature_demod_cf</block> <block>gr_cpfsk_bc</block> + <block>gr_cpmmod_bc</block> + <block>gr_gmskmod_bc</block> <block>gr_diff_phasor_cc</block> - <block>gr_constellation_decoder_cb</block> <block>gr_diff_encoder_bb</block> <block>gr_diff_decoder_bb</block> @@ -217,12 +210,6 @@ <block>blks2_fm_deemph</block> <block>blks2_fm_preemph</block> - <block>blks2_dxpsk_mod</block> - <block>blks2_dxpsk_demod</block> - - <block>blks2_dxpsk2_mod</block> - <block>blks2_dxpsk2_demod</block> - <block>blks2_gmsk_mod</block> <block>blks2_gmsk_demod</block> diff --git a/grc/blocks/gr_cma_equalizer_cc.xml b/grc/blocks/gr_cma_equalizer_cc.xml deleted file mode 100644 index 142fb6d81..000000000 --- a/grc/blocks/gr_cma_equalizer_cc.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##CMA Equalizer -################################################### - --> -<block> - <name>CMA Equalizer</name> - <key>gr_cma_equalizer_cc</key> - <import>from gnuradio import gr</import> - <make>gr.cma_equalizer_cc($num_taps, $modulus, $mu)</make> - <param> - <name>Num Taps</name> - <key>num_taps</key> - <value>64</value> - <type>int</type> - </param> - <param> - <name>Modulus</name> - <key>modulus</key> - <type>real</type> - </param> - <param> - <name>Mu</name> - <key>mu</key> - <type>real</type> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/gr_costas_loop_cc.xml b/grc/blocks/gr_costas_loop_cc.xml deleted file mode 100644 index e0db8bc5d..000000000 --- a/grc/blocks/gr_costas_loop_cc.xml +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Costas Loop -################################################### - --> -<block> - <name>Costas Loop</name> - <key>gr_costas_loop_cc</key> - <import>from gnuradio import gr</import> - <make>gr.costas_loop_cc($alpha, $beta, $max_freq, $min_freq, $order)</make> - <callback>set_alpha($alpha)</callback> - <callback>set_beta($beta)</callback> - <param> - <name>Alpha</name> - <key>alpha</key> - <type>real</type> - </param> - <param> - <name>Beta</name> - <key>beta</key> - <type>real</type> - </param> - <param> - <name>Max Freq</name> - <key>max_freq</key> - <type>real</type> - </param> - <param> - <name>Min Freq</name> - <key>min_freq</key> - <type>real</type> - </param> - <param> - <name>Order</name> - <key>order</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> - <source> - <name>out</name> - <type>complex</type> - <optional>1</optional> - </source> -</block> diff --git a/grc/blocks/gr_cpmmod_bc.xml b/grc/blocks/gr_cpmmod_bc.xml new file mode 100644 index 000000000..da405534e --- /dev/null +++ b/grc/blocks/gr_cpmmod_bc.xml @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Continuous Phase Modulation +################################################### + --> +<block> + <name>Continuous Phase Modulation</name> + <key>gr_cpmmod_bc</key> + <import>from gnuradio import gr</import> + <make>gr.cpmmod_bc($type, $mod_index, $samples_per_symbol, $L, $beta)</make> + <param> + <name>CPM Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>L-REC (Rectangular phase response)</name> + <key>gr.cpm.LREC</key> + </option> + <option> + <name>L-RC (Raised Cosine)</name> + <key>gr.cpm.LRC</key> + </option> + <option> + <name>L-SRC (Spectral raised cosine)</name> + <key>gr.cpm.LSRC</key> + </option> + <option> + <name>TFM (Tamed frequency modulation)</name> + <key>gr.cpm.TFM</key> + </option> + <option> + <name>Gaussian</name> + <key>gr.cpm.GAUSSIAN</key> + </option> + </param> + <param> + <name>Modulation Index</name> + <key>mod_index</key> + <value>0.5</value> + <type>real</type> + </param> + <param> + <name>Samples/Symbol</name> + <key>samples_per_symbol</key> + <value>4</value> + <type>int</type> + </param> + <param> + <name>Pulse Duration (Symbols)</name> + <key>L</key> + <value>4</value> + <type>int</type> + </param> + <param> + <name>Phase Response Parameter (BT or Beta)</name> + <key>beta</key> + <value>0.3</value> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/grc/blocks/gr_gmskmod_bc.xml b/grc/blocks/gr_gmskmod_bc.xml new file mode 100644 index 000000000..82e47452b --- /dev/null +++ b/grc/blocks/gr_gmskmod_bc.xml @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<!-- +################################################### +## GMSK +################################################### + --> +<block> + <name>GMSK Modulator</name> + <key>gr_gmskmod_bc</key> + <import>from gnuradio import gr</import> + <make>gr.gmskmod_bc($samples_per_symbol, $bt, $L)</make> + <param> + <name>Samples/Symbol</name> + <key>samples_per_symbol</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>3 dB Time-Bandwith Product</name> + <key>bt</key> + <value>0.3</value> + <type>real</type> + </param> + <param> + <name>Pulse Duration (Symbols)</name> + <key>L</key> + <value>4</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/grc/blocks/gr_pll_carriertracking_cc.xml b/grc/blocks/gr_pll_carriertracking_cc.xml index 5b876b259..27e673248 100644 --- a/grc/blocks/gr_pll_carriertracking_cc.xml +++ b/grc/blocks/gr_pll_carriertracking_cc.xml @@ -8,15 +8,11 @@ <name>PLL Carrier Tracking</name> <key>gr_pll_carriertracking_cc</key> <import>from gnuradio import gr</import> - <make>gr.pll_carriertracking_cc($alpha, $beta, $max_freq, $min_freq)</make> + <make>gr.pll_carriertracking_cc($w, $max_freq, $min_freq)</make> + <callback>set_loop_bandwidth($w)</callback> <param> - <name>Alpha</name> - <key>alpha</key> - <type>real</type> - </param> - <param> - <name>Beta</name> - <key>beta</key> + <name>Loop Bandwidth</name> + <key>w</key> <type>real</type> </param> <param> diff --git a/grc/blocks/gr_pll_freqdet_cf.xml b/grc/blocks/gr_pll_freqdet_cf.xml index 8ec1fb3bb..d6e4694f0 100644 --- a/grc/blocks/gr_pll_freqdet_cf.xml +++ b/grc/blocks/gr_pll_freqdet_cf.xml @@ -8,15 +8,11 @@ <name>PLL Freq Det</name> <key>gr_pll_freqdet_cf</key> <import>from gnuradio import gr</import> - <make>gr.pll_freqdet_cf($alpha, $beta, $max_freq, $min_freq)</make> + <make>gr.pll_freqdet_cf($w, $max_freq, $min_freq)</make> + <callback>set_loop_bandwidth($w)</callback> <param> - <name>Alpha</name> - <key>alpha</key> - <type>real</type> - </param> - <param> - <name>Beta</name> - <key>beta</key> + <name>Loop Bandwidth</name> + <key>w</key> <type>real</type> </param> <param> diff --git a/grc/blocks/gr_pll_refout_cc.xml b/grc/blocks/gr_pll_refout_cc.xml index 64cf2bfb6..b231ddd19 100644 --- a/grc/blocks/gr_pll_refout_cc.xml +++ b/grc/blocks/gr_pll_refout_cc.xml @@ -8,15 +8,11 @@ <name>PLL Ref Out</name> <key>gr_pll_refout_cc</key> <import>from gnuradio import gr</import> - <make>gr.pll_refout_cc($alpha, $beta, $max_freq, $min_freq)</make> + <make>gr.pll_refout_cc($w, $max_freq, $min_freq)</make> + <callback>set_loop_bandwidth($w)</callback> <param> - <name>Alpha</name> - <key>alpha</key> - <type>real</type> - </param> - <param> - <name>Beta</name> - <key>beta</key> + <name>Loop Bandwidth</name> + <key>w</key> <type>real</type> </param> <param> |