diff options
Diffstat (limited to 'gnuradio-core/src/lib')
89 files changed, 2645 insertions, 5734 deletions
diff --git a/gnuradio-core/src/lib/Makefile.am b/gnuradio-core/src/lib/Makefile.am index 4db2ff167..979ac7f91 100644 --- a/gnuradio-core/src/lib/Makefile.am +++ b/gnuradio-core/src/lib/Makefile.am @@ -24,7 +24,7 @@ include $(top_srcdir)/Makefile.common ## Process this file with automake to produce Makefile.in # We've got to build . before swig -SUBDIRS = missing runtime filter viterbi general gengen g72x reed-solomon io hier . swig +SUBDIRS = missing runtime filter viterbi general gengen reed-solomon io hier . swig AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(WITH_INCLUDES) @@ -43,7 +43,6 @@ libgnuradio_core_qa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 \ libgnuradio_core_la_LIBADD = \ filter/libfilter.la \ - g72x/libccitt.la \ viterbi/libviterbi.la \ general/libgeneral.la \ gengen/libgengen.la \ diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 0314079a2..c314431bf 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 # @@ -188,8 +188,8 @@ EXTRA_DIST += \ # work around automake deficiency 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 \ @@ -215,6 +215,7 @@ libfilter_la_common_SOURCES = \ gr_pfb_decimator_ccf.cc \ gr_pfb_interpolator_ccf.cc \ gr_pfb_arb_resampler_ccf.cc \ + gr_pfb_arb_resampler_fff.cc \ gr_pfb_clock_sync_ccf.cc \ gr_pfb_clock_sync_fff.cc \ gr_dc_blocker_cc.cc \ @@ -272,9 +273,9 @@ grinclude_HEADERS = \ ccomplex_dotprod_x86.h \ float_dotprod_generic.h \ float_dotprod_x86.h \ + 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 \ @@ -307,6 +308,7 @@ grinclude_HEADERS = \ gr_pfb_decimator_ccf.h \ gr_pfb_interpolator_ccf.h \ gr_pfb_arb_resampler_ccf.h \ + gr_pfb_arb_resampler_fff.h \ gr_pfb_clock_sync_ccf.h \ gr_pfb_clock_sync_fff.h \ gr_dc_blocker_cc.h \ @@ -357,8 +359,8 @@ noinst_HEADERS = \ swiginclude_HEADERS = \ filter.i \ 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 \ @@ -374,6 +376,7 @@ swiginclude_HEADERS = \ gr_pfb_decimator_ccf.i \ gr_pfb_interpolator_ccf.i \ gr_pfb_arb_resampler_ccf.i \ + gr_pfb_arb_resampler_fff.i \ gr_pfb_clock_sync_ccf.i \ gr_pfb_clock_sync_fff.i \ gr_dc_blocker_cc.i \ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i index 58bb4f0d5..8c3bb9eb6 100644 --- a/gnuradio-core/src/lib/filter/filter.i +++ b/gnuradio-core/src/lib/filter/filter.i @@ -31,12 +31,12 @@ #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> #include <gr_pfb_interpolator_ccf.h> #include <gr_pfb_arb_resampler_ccf.h> +#include <gr_pfb_arb_resampler_fff.h> #include <gr_pfb_clock_sync_ccf.h> #include <gr_pfb_clock_sync_fff.h> #include <gr_dc_blocker_cc.h> @@ -53,12 +53,12 @@ %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" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" +%include "gr_pfb_arb_resampler_fff.i" %include "gr_pfb_decimator_ccf.i" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.cc b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.cc new file mode 100644 index 000000000..3fed74641 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.cc @@ -0,0 +1,88 @@ +/* -*- 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 <gr_adaptive_fir_ccc.h> +#include <gr_io_signature.h> + +gr_adaptive_fir_ccc::gr_adaptive_fir_ccc(const char *name, int decimation, + const std::vector<gr_complex> &taps) + : gr_sync_decimator (name, + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + decimation), + d_updated(false), d_taps(taps) +{ + set_history(d_taps.size()); +} + +void +gr_adaptive_fir_ccc::set_taps(const std::vector<gr_complex> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +gr_complex +gr_adaptive_fir_ccc::filter(gr_complex *x) +{ + // Generic dot product of d_taps[] and in[] + gr_complex acc(0.0, 0.0); + int l = d_taps.size(); + for (int k = 0; k < l; k++) + acc += d_taps[l-k-1] * x[k]; + return acc; +} + +int +gr_adaptive_fir_ccc::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + if (d_updated) { + d_taps = d_new_taps; + set_history(d_taps.size()); + d_updated = false; + return 0; // history requirements may have changed. + } + + int j = 0, k, l = d_taps.size(); + for (int i = 0; i < noutput_items; i++) { + out[i] = filter(&in[j]); + + // Adjust taps + d_error = error(out[i]); + for (k = 0; k < l; k++) { + update_tap(d_taps[l-k-1], in[j+k]); + } + + j += decimation(); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.h b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.h new file mode 100644 index 000000000..8678255b7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.h @@ -0,0 +1,61 @@ +/* -*- 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 INCLUDED_GR_ADAPTIVE_FIR_CCC_H +#define INCLUDED_GR_ADAPTIVE_FIR_CCC_H + +#include <gr_sync_decimator.h> + +/*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * \ingroup filter_blk + */ +class gr_adaptive_fir_ccc : public gr_sync_decimator +{ +private: + std::vector<gr_complex> d_new_taps; + bool d_updated; + +protected: + gr_complex d_error; + std::vector<gr_complex> d_taps; + + // Override to calculate error signal per output + virtual gr_complex error(const gr_complex &out) = 0; + + // Override to calculate new weight from old, corresponding input + virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0; + + gr_complex filter(gr_complex *x); + + gr_adaptive_fir_ccc(const char *name, int decimation, + const std::vector<gr_complex> &taps); + +public: + void set_taps(const std::vector<gr_complex> &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_binary_slicer_fb.i b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.i index b6f4e9312..7e9a3fac3 100644 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,14 +20,12 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,binary_slicer_fb); - -gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); - -class gr_binary_slicer_fb : public gr_sync_block +class gr_adaptive_fir_ccc : public gr_sync_decimator { - private: - gr_binary_slicer_fb (); +protected: + gr_adaptive_fir_ccc(char *name, int decimation, + const std::vector<gr_complex> &taps); - public: +public: + void set_taps(const std::vector<gr_complex> &taps); }; diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc deleted file mode 100644 index f80bfd518..000000000 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_cma_equalizer_cc.h> - -gr_cma_equalizer_cc_sptr -gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu) -{ - return gnuradio::get_initial_sptr(new gr_cma_equalizer_cc(num_taps, modulus, mu)); -} - -gr_cma_equalizer_cc::gr_cma_equalizer_cc(int num_taps, float modulus, float mu) - : gr_adaptive_fir_ccf("cma_equalizer_cc", 1, std::vector<float>(num_taps)), - d_modulus(modulus), d_mu(mu) -{ - if (num_taps > 0) - d_taps[0] = 1.0; -} - diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h deleted file mode 100644 index c78047c16..000000000 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h +++ /dev/null @@ -1,62 +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. - */ - -#ifndef INCLUDED_GR_CMA_EQUALIZER_CC_H -#define INCLUDED_GR_CMA_EQUALIZER_CC_H - -#include <gr_adaptive_fir_ccf.h> - -class gr_cma_equalizer_cc; -typedef boost::shared_ptr<gr_cma_equalizer_cc> gr_cma_equalizer_cc_sptr; - -gr_cma_equalizer_cc_sptr -gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); - -/*! - * \brief Implements constant modulus adaptive filter on complex stream - * \ingroup eq_blk - */ -class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf -{ -private: - float d_modulus; - float d_mu; - - friend gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); - gr_cma_equalizer_cc(int num_taps, float modulus, float mu); - -protected: - - virtual float error(const gr_complex &out) - { - return (d_modulus - norm(out)); - } - - virtual void update_tap(float &tap, const gr_complex &in) - { - tap += d_mu*d_error*abs(in); - } - -public: -}; - -#endif diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i deleted file mode 100644 index 30e2fb8bd..000000000 --- a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2009 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,cma_equalizer_cc) - -// retrieve info on the base class, without generating wrappers since -// the base class has a pure virual method. -%import "gr_adaptive_fir_ccf.i" - -gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); - -class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf -{ -private: - gr_cma_equalizer_cc(int num_taps, float modulus, float mu); - -public: -}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h index 2c36c95f9..806c33d92 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h @@ -41,6 +41,7 @@ class gr_fir_ccf; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs arbitrary * resampling. The resampling rate can be any real diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc new file mode 100644 index 000000000..9035e67f4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc @@ -0,0 +1,209 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pfb_arb_resampler_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <cstdio> + +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size) +{ + return gnuradio::get_initial_sptr(new gr_pfb_arb_resampler_fff (rate, taps, + filter_size)); +} + + +gr_pfb_arb_resampler_fff::gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size) + : gr_block ("pfb_arb_resampler_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(float))), + d_updated (false) +{ + d_acc = 0; // start accumulator at 0 + + /* The number of filters is specified by the user as the filter size; + this is also the interpolation rate of the filter. We use it and the + rate provided to determine the decimation rate. This acts as a + rational resampler. The flt_rate is calculated as the residual + between the integer decimation rate and the real decimation rate and + will be used to determine to interpolation point of the resampling + process. + */ + d_int_rate = filter_size; + set_rate(rate); + + // Store the last filter between calls to work + d_last_filter = 0; + + d_start_index = 0; + + d_filters = std::vector<gr_fir_fff*>(d_int_rate); + d_diff_filters = std::vector<gr_fir_fff*>(d_int_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_int_rate); + for(unsigned int i = 0; i < d_int_rate; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + create_taps(taps, d_taps, d_filters); + create_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_arb_resampler_fff::~gr_pfb_arb_resampler_fff () +{ + for(unsigned int i = 0; i < d_int_rate; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_arb_resampler_fff::create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter) +{ + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_int_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(unsigned int i = 0; i < d_int_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(unsigned int j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + 1); + + d_updated = true; +} + +void +gr_pfb_arb_resampler_fff::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + // Calculate the differential taps (derivative filter) by taking the difference + // between two taps. Duplicate the last one to make both filters the same length. + float tap; + difftaps.clear(); + for(unsigned int i = 0; i < newtaps.size()-1; i++) { + tap = newtaps[i+1] - newtaps[i]; + difftaps.push_back(tap); + } + difftaps.push_back(tap); +} + +void +gr_pfb_arb_resampler_fff::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_int_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n"); + } +} + +int +gr_pfb_arb_resampler_fff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + float *out = (float *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = d_start_index; + unsigned int j; + float o0, o1; + + // Restore the last filter position + j = d_last_filter; + + // produce output as long as we can and there are enough input samples + int max_input = ninput_items[0]-(int)d_taps_per_filter; + while((i < noutput_items) && (count < max_input)) { + // start j by wrapping around mod the number of channels + while((j < d_int_rate) && (i < noutput_items)) { + // Take the current filter and derivative filter output + o0 = d_filters[j]->filter(&in[count]); + o1 = d_diff_filters[j]->filter(&in[count]); + + out[i] = o0 + o1*d_acc; // linearly interpolate between samples + i++; + + // Adjust accumulator and index into filterbank + d_acc += d_flt_rate; + j += d_dec_rate + (int)floor(d_acc); + d_acc = fmodf(d_acc, 1.0); + } + if(i < noutput_items) { // keep state for next entry + float ss = (int)(j / d_int_rate); // number of items to skip ahead by + count += ss; // we have fully consumed another input + j = j % d_int_rate; // roll filter around + } + } + + // Store the current filter position and start of next sample + d_last_filter = j; + d_start_index = std::max(0, count - ninput_items[0]); + + // consume all we've processed but no more than we can + consume_each(std::min(count, ninput_items[0])); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h new file mode 100644 index 000000000..69331a2c6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h @@ -0,0 +1,177 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_GR_PFB_ARB_RESAMPLER_FFF_H +#define INCLUDED_GR_PFB_ARB_RESAMPLER_FFF_H + +#include <gr_block.h> + +class gr_pfb_arb_resampler_fff; +typedef boost::shared_ptr<gr_pfb_arb_resampler_fff> gr_pfb_arb_resampler_fff_sptr; +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_fir_fff; + +/*! + * \class gr_pfb_arb_resampler_fff + * + * \brief Polyphase filterbank arbitrary resampler with + * float input, float output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs arbitrary + * resampling. The resampling rate can be any real + * number <EM>r</EM>. The resampling is done by constructing + * <EM>N</EM> filters where <EM>N</EM> is the interpolation rate. We + * then calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. + * + * Using <EM>N</EM> and <EM>D</EM>, we can perform rational resampling + * where <EM>N/D</EM> is a rational number close to the input rate + * <EM>r</EM> where we have <EM>N</EM> filters and we cycle through + * them as a polyphase filterbank with a stride of <EM>D</EM> so that + * <EM>i+1 = (i + D) % N</EM>. + * + * To get the arbitrary rate, we want to interpolate between two + * points. For each value out, we take an output from the current + * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then + * linearly interpolate between the two based on the real resampling + * rate we want. + * + * The linear interpolation only provides us with an approximation to + * the real sampling rate specified. The error is a quantization error + * between the two filters we used as our interpolation points. To + * this end, the number of filters, <EM>N</EM>, used determines the + * quantization error; the larger <EM>N</EM>, the smaller the + * noise. You can design for a specified noise floor by setting the + * filter size (parameters <EM>filter_size</EM>). The size defaults to + * 32 filters, which is about as good as most implementations need. + * + * The trick with designing this filter is in how to specify the taps + * of the prototype filter. Like the PFB interpolator, the taps are + * specified using the interpolated filter rate. In this case, that + * rate is the input sample rate multiplied by the number of filters + * in the filterbank, which is also the interpolation rate. All other + * values should be relative to this rate. + * + * For example, for a 32-filter arbitrary resampler and using the + * GNU Radio's firdes utility to build the filter, we build a low-pass + * filter with a sampling rate of <EM>fs</EM>, a 3-dB bandwidth of + * <EM>BW</EM> and a transition bandwidth of <EM>TB</EM>. We can also + * specify the out-of-band attenuation to use, <EM>ATT</EM>, and the + * filter window function (a Blackman-harris window in this case). The + * first input is the gain of the filter, which we specify here as the + * interpolation rate (<EM>32</EM>). + * + * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The theory behind this block can be found in Chapter 7.5 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + +class gr_pfb_arb_resampler_fff : public gr_block +{ + private: + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + friend gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + std::vector<gr_fir_fff*> d_filters; + std::vector<gr_fir_fff*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + unsigned int d_int_rate; // the number of filters (interpolation rate) + unsigned int d_dec_rate; // the stride through the filters (decimation rate) + float d_flt_rate; // residual rate for the linear interpolation + float d_acc; + unsigned int d_last_filter; + int d_start_index; + unsigned int d_taps_per_filter; + bool d_updated; + + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param newtaps (vector of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. + * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. + */ + void create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + +public: + ~gr_pfb_arb_resampler_fff (); + + // FIXME: See about a set_taps function during runtime. + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + void set_rate (float rate) { + d_dec_rate = (unsigned int)floor(d_int_rate/rate); + d_flt_rate = (d_int_rate/rate) - d_dec_rate; + set_relative_rate(rate); + } + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.i b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i index c9c792c8a..8c1db22c3 100644 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.i +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,22 +20,23 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,fll_band_edge_cc); +GR_SWIG_BLOCK_MAGIC(gr,pfb_arb_resampler_fff); -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); +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); -class gr_fll_band_edge_cc : public gr_sync_block +class gr_pfb_arb_resampler_fff : public gr_block { private: - gr_fll_band_edge_cc (float samps_per_sym, float rolloff, - int filter_size, float alpha, float beta); + gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); public: - ~gr_fll_band_edge_cc (); + ~gr_pfb_arb_resampler_fff (); - void set_alpha (float alpha); - void set_beta (float beta); - void design_filter(float samps_per_sym, float rolloff, int filter_size); + //void set_taps (const std::vector<float> &taps); void print_taps(); + void set_rate (float rate); }; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h index 751673bc7..68476ed3c 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h @@ -43,6 +43,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in complex inputs and channelizes it to <EM>M</EM> * channels of equal bandwidth. Each of the resulting channels is 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 937899c0d..633c5be07 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,39 +33,47 @@ #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) + float max_rate_deviation, + int osps) { - return gnuradio::get_initial_sptr(new gr_pfb_clock_sync_ccf (sps, gain, taps, - filter_size, - init_phase, - max_rate_deviation)); + return gnuradio::get_initial_sptr(new gr_pfb_clock_sync_ccf (sps, loop_bw, taps, + filter_size, + init_phase, + max_rate_deviation, + osps)); } 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, - float max_rate_deviation) + float max_rate_deviation, + int osps) : gr_block ("pfb_clock_sync_ccf", gr_make_io_signature (1, 1, sizeof(gr_complex)), gr_make_io_signaturev (1, 4, iosig)), d_updated (false), d_nfilters(filter_size), - d_max_dev(max_rate_deviation) + d_max_dev(max_rate_deviation), + 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); @@ -103,6 +111,100 @@ 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; +} + +float +gr_pfb_clock_sync_ccf::get_clock_rate() const +{ + return d_rate_f; +} + +/******************************************************************* +*******************************************************************/ + +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, @@ -127,13 +229,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 @@ -146,58 +251,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++) { @@ -207,7 +338,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++) { @@ -226,7 +357,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]; @@ -239,50 +370,56 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items, } // We need this many to process one output - int nrequired = ninput_items[0] - d_taps_per_filter; + 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) && (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; + while((i < noutput_items-d_osps) && (count < nrequired)) { + 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; + } } - out[i] = d_filters[d_filtnum]->filter(&in[count]); + // 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); - i++; + i+=d_osps; count += (int)floor(d_sps); - - if(output_items.size() == 4) { - err[i] = error; - outrate[i] = d_rate_f; - outk[i] = d_k; - } } consume_each(count); 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 684ac85ce..674dee181 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 @@ -28,11 +28,12 @@ class gr_pfb_clock_sync_ccf; typedef boost::shared_ptr<gr_pfb_clock_sync_ccf> gr_pfb_clock_sync_ccf_sptr; -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, - float max_rate_deviation=1.5); + float max_rate_deviation=1.5, + int osps=1); class gr_fir_ccf; @@ -42,71 +43,85 @@ class gr_fir_ccf; * \brief Timing synchronizer using polyphase filterbanks * * \ingroup filter_blk + * \ingroup pfb_blk * - * This block performs timing synchronization for PAM signals by minimizing the - * derivative of the filtered signal, which in turn maximizes the SNR and - * minimizes ISI. + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. * - * This approach works by setting up two filterbanks; one filterbanke contains the - * signal's pulse shaping matched filter (such as a root raised cosine filter), - * where each branch of the filterbank contains a different phase of the filter. - * The second filterbank contains the derivatives of the filters in the first - * filterbank. Thinking of this in the time domain, the first filterbank contains - * filters that have a sinc shape to them. We want to align the output signal to - * be sampled at exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)' = 0). - * Furthermore, the region around the zero point is relatively linear. We make - * use of this fact to generate the error signal. + * This approach works by setting up two filterbanks; one filterbank + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. * - * If the signal out of the derivative filters is d_i[n] for the ith filter, and - * the output of the matched filter is x_i[n], we calculate the error as: - * e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 - * This equation averages the error in the real and imaginary parts. There are two - * reasons we multiply by the signal itself. First, if the symbol could be positive - * or negative going, but we want the error term to always tell us to go in the - * same direction depending on which side of the zero point we are on. The sign of - * x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales - * the error term depending on the symbol's amplitude, so larger signals give us - * a stronger error term because we have more confidence in that symbol's value. - * Using the magnitude of x_i[n] instead of just the sign is especially good for - * signals with low SNR. + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. * - * The error signal, e[n], gives us a value proportional to how far away from the zero - * point we are in the derivative signal. We want to drive this value to zero, so we - * set up a second order loop. We have two variables for this loop; d_k is the filter - * number in the filterbank we are on and d_rate is the rate which we travel through - * the filters in the steady state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference and would traverse - * the filter phase paths to keep the receiver locked. Thinking of this as a second-order - * PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, d_alpha and d_beta. - * We have these two values set based on each other for a critically damped system, so in - * the block constructor, we just ask for "gain," which is d_alpha while d_beta is - * equal to (gain^2)/4. + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. * - * The clock sync block needs to know the number of samples per symbol (sps), because it - * only returns a single point representing the sample. The sps can be any positive real - * number and does not need to be an integer. The filter taps must also be specified. The - * taps are generated by first conceiving of the prototype filter that would be the signal's - * matched filter. Then interpolate this by the number of filters in the filterbank. These - * are then distributed among all of the filters. So if the prototype filter was to have - * 45 taps in it, then each path of the filterbank will also have 45 taps. This is easily - * done by building the filter with the sample rate multiplied by the number of filters - * to use. + * The clock sync block needs to know the number of samples per symbol + * (sps), because it only returns a single point representing the + * symbol. The sps can be any positive real number and does not need + * to be an integer. The filter taps must also be specified. The taps + * are generated by first conceiving of the prototype filter that + * would be the signal's matched filter. Then interpolate this by the + * number of filters in the filterbank. These are then distributed + * among all of the filters. So if the prototype filter was to have 45 + * taps in it, then each path of the filterbank will also have 45 + * taps. This is easily done by building the filter with the sample + * rate multiplied by the number of filters to use. * - * The number of filters can also be set and defaults to 32. With 32 filters, you get a - * good enough resolution in the phase to produce very small, almost unnoticeable, ISI. - * Going to 64 filters can reduce this more, but after that there is very little gained - * for the extra complexity. + * The number of filters can also be set and defaults to 32. With 32 + * filters, you get a good enough resolution in the phase to produce + * very small, almost unnoticeable, ISI. Going to 64 filters can + * reduce this more, but after that there is very little gained for + * the extra complexity. * - * The initial phase is another settable parameter and refers to the filter path the - * algorithm initially looks at (i.e., d_k starts at init_phase). This value defaults - * to zero, but it might be useful to start at a different phase offset, such as the mid- - * point of the filters. + * The initial phase is another settable parameter and refers to the + * filter path the algorithm initially looks at (i.e., d_k starts at + * init_phase). This value defaults to zero, but it might be useful to + * start at a different phase offset, such as the mid- point of the + * filters. * - * The final parameter is the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from 0. Constraining the rate can help - * keep the algorithm from walking too far away to lock during times when there is no signal. + * The final parameter is the max_rate_devitation, which defaults to + * 1.5. This is how far we allow d_rate to swing, positive or + * negative, from 0. Constraining the rate can help keep the algorithm + * from walking too far away to lock during times when there is no + * signal. * */ @@ -116,52 +131,70 @@ class gr_pfb_clock_sync_ccf : public gr_block /*! * Build the polyphase filterbank timing synchronizer. * \param sps (double) The number of samples per symbol in the incoming signal - * \param gain (float) The alpha gain of the control loop; beta = (gain^2)/4 by default. + * \param loop_bw (float) The bandwidth of the control loop; set's alpha and beta. * \param taps (vector<int>) The filter taps. * \param filter_size (uint) The number of filters in the filterbank (default = 32). * \param init_phase (float) The initial phase to look at, or which filter to start * with (default = 0). * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). + * \param osps (int) The number of output samples per symbol (default=1). * */ - friend gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain, + friend 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); - - 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; + float max_rate_deviation, + int osps); + + 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; + + 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, - float max_rate_deviation); + float max_rate_deviation, + int osps); void create_diff_taps(const std::vector<float> &newtaps, std::vector<float> &difftaps); 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 @@ -171,40 +204,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 @@ -214,6 +304,38 @@ 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; + + /*! + * \brief Returns the current clock rate + */ + float get_clock_rate() 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 197984287..92ad1661a 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,20 +22,22 @@ 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, - float max_rate_deviation=1.5); + float max_rate_deviation=1.5, + int osps=1); 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, - float max_rate_deviation); + float max_rate_deviation, + int osps); public: ~gr_pfb_clock_sync_ccf (); @@ -44,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; + float get_clock_rate() const; }; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h index fa1279a7c..d7c646801 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h @@ -42,71 +42,85 @@ class gr_fir_fff; * \brief Timing synchronizer using polyphase filterbanks * * \ingroup filter_blk + * \ingroup pfb_blk * - * This block performs timing synchronization for PAM signals by minimizing the - * derivative of the filtered signal, which in turn maximizes the SNR and - * minimizes ISI. + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. * - * This approach works by setting up two filterbanks; one filterbanke contains the - * signal's pulse shaping matched filter (such as a root raised cosine filter), - * where each branch of the filterbank contains a different phase of the filter. - * The second filterbank contains the derivatives of the filters in the first - * filterbank. Thinking of this in the time domain, the first filterbank contains - * filters that have a sinc shape to them. We want to align the output signal to - * be sampled at exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)' = 0). - * Furthermore, the region around the zero point is relatively linear. We make - * use of this fact to generate the error signal. + * This approach works by setting up two filterbanks; one filterbanke + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. * - * If the signal out of the derivative filters is d_i[n] for the ith filter, and - * the output of the matched filter is x_i[n], we calculate the error as: - * e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 - * This equation averages the error in the real and imaginary parts. There are two - * reasons we multiply by the signal itself. First, if the symbol could be positive - * or negative going, but we want the error term to always tell us to go in the - * same direction depending on which side of the zero point we are on. The sign of - * x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales - * the error term depending on the symbol's amplitude, so larger signals give us - * a stronger error term because we have more confidence in that symbol's value. - * Using the magnitude of x_i[n] instead of just the sign is especially good for - * signals with low SNR. + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. * - * The error signal, e[n], gives us a value proportional to how far away from the zero - * point we are in the derivative signal. We want to drive this value to zero, so we - * set up a second order loop. We have two variables for this loop; d_k is the filter - * number in the filterbank we are on and d_rate is the rate which we travel through - * the filters in the steady state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference and would traverse - * the filter phase paths to keep the receiver locked. Thinking of this as a second-order - * PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, d_alpha and d_beta. - * We have these two values set based on each other for a critically damped system, so in - * the block constructor, we just ask for "gain," which is d_alpha while d_beta is - * equal to (gain^2)/4. + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. * - * The clock sync block needs to know the number of samples per second (sps), because it - * only returns a single point representing the sample. The sps can be any positive real - * number and does not need to be an integer. The filter taps must also be specified. The - * taps are generated by first conceiving of the prototype filter that would be the signal's - * matched filter. Then interpolate this by the number of filters in the filterbank. These - * are then distributed among all of the filters. So if the prototype filter was to have - * 45 taps in it, then each path of the filterbank will also have 45 taps. This is easily - * done by building the filter with the sample rate multiplied by the number of filters - * to use. + * The clock sync block needs to know the number of samples per second + * (sps), because it only returns a single point representing the + * sample. The sps can be any positive real number and does not need + * to be an integer. The filter taps must also be specified. The taps + * are generated by first conceiving of the prototype filter that + * would be the signal's matched filter. Then interpolate this by the + * number of filters in the filterbank. These are then distributed + * among all of the filters. So if the prototype filter was to have 45 + * taps in it, then each path of the filterbank will also have 45 + * taps. This is easily done by building the filter with the sample + * rate multiplied by the number of filters to use. * - * The number of filters can also be set and defaults to 32. With 32 filters, you get a - * good enough resolution in the phase to produce very small, almost unnoticeable, ISI. - * Going to 64 filters can reduce this more, but after that there is very little gained - * for the extra complexity. + * The number of filters can also be set and defaults to 32. With 32 + * filters, you get a good enough resolution in the phase to produce + * very small, almost unnoticeable, ISI. Going to 64 filters can + * reduce this more, but after that there is very little gained for + * the extra complexity. * - * The initial phase is another settable parameter and refers to the filter path the - * algorithm initially looks at (i.e., d_k starts at init_phase). This value defaults - * to zero, but it might be useful to start at a different phase offset, such as the mid- - * point of the filters. + * The initial phase is another settable parameter and refers to the + * filter path the algorithm initially looks at (i.e., d_k starts at + * init_phase). This value defaults to zero, but it might be useful to + * start at a different phase offset, such as the mid- point of the + * filters. * - * The final parameter is the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from 0. Constraining the rate can help - * keep the algorithm from walking too far away to lock during times when there is no signal. + * The final parameter is the max_rate_devitation, which defaults to + * 1.5. This is how far we allow d_rate to swing, positive or + * negative, from 0. Constraining the rate can help keep the algorithm + * from walking too far away to lock during times when there is no + * signal. * */ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h index 200adee3d..6b75c5859 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h @@ -41,6 +41,7 @@ class gri_fft_complex; * input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs interger down- * sampling (decimation) with a polyphase filterbank. The first input diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h index d2efc591a..3dc52938e 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h @@ -39,6 +39,7 @@ class gr_fir_ccf; * gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs interger up- * sampling (interpolation) with a polyphase filterbank. The first diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h index f5b1cbb94..7e3700921 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -42,6 +42,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk */ class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator diff --git a/gnuradio-core/src/lib/g72x/.gitignore b/gnuradio-core/src/lib/g72x/.gitignore deleted file mode 100644 index a02b6ff73..000000000 --- a/gnuradio-core/src/lib/g72x/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/Makefile -/Makefile.in -/.la -/.lo -/.deps -/.libs -/*.la -/*.lo diff --git a/gnuradio-core/src/lib/g72x/Makefile.am b/gnuradio-core/src/lib/g72x/Makefile.am deleted file mode 100644 index d2700376f..000000000 --- a/gnuradio-core/src/lib/g72x/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright 2001 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 - -noinst_LTLIBRARIES = libccitt.la -libccitt_la_SOURCES = g711.c g72x.c g721.c g723_24.c g723_40.c g72x.h - -EXTRA_DIST += encode.c decode.c diff --git a/gnuradio-core/src/lib/g72x/README b/gnuradio-core/src/lib/g72x/README deleted file mode 100644 index 23b0e7dd5..000000000 --- a/gnuradio-core/src/lib/g72x/README +++ /dev/null @@ -1,94 +0,0 @@ -The files in this directory comprise ANSI-C language reference implementations -of the CCITT (International Telegraph and Telephone Consultative Committee) -G.711, G.721 and G.723 voice compressions. They have been tested on Sun -SPARCstations and passed 82 out of 84 test vectors published by CCITT -(Dec. 20, 1988) for G.721 and G.723. [The two remaining test vectors, -which the G.721 decoder implementation for u-law samples did not pass, -may be in error because they are identical to two other vectors for G.723_40.] - -This source code is released by Sun Microsystems, Inc. to the public domain. -Please give your acknowledgement in product literature if this code is used -in your product implementation. - -Sun Microsystems supports some CCITT audio formats in Solaris 2.0 system -software. However, Sun's implementations have been optimized for higher -performance on SPARCstations. - - -The source files for CCITT conversion routines in this directory are: - - g72x.h header file for g721.c, g723_24.c and g723_40.c - g711.c CCITT G.711 u-law and A-law compression - g72x.c common denominator of G.721 and G.723 ADPCM codes - g721.c CCITT G.721 32Kbps ADPCM coder (with g72x.c) - g723_24.c CCITT G.723 24Kbps ADPCM coder (with g72x.c) - g723_40.c CCITT G.723 40Kbps ADPCM coder (with g72x.c) - - -Simple conversions between u-law, A-law, and 16-bit linear PCM are invoked -as follows: - - unsigned char ucode, acode; - short pcm_val; - - ucode = linear2ulaw(pcm_val); - ucode = alaw2ulaw(acode); - - acode = linear2alaw(pcm_val); - acode = ulaw2alaw(ucode); - - pcm_val = ulaw2linear(ucode); - pcm_val = alaw2linear(acode); - - -The other CCITT compression routines are invoked as follows: - - #include "g72x.h" - - struct g72x_state state; - int sample, code; - - g72x_init_state(&state); - code = {g721,g723_24,g723_40}_encoder(sample, coding, &state); - sample = {g721,g723_24,g723_40}_decoder(code, coding, &state); - -where - coding = AUDIO_ENCODING_ULAW for 8-bit u-law samples - AUDIO_ENCODING_ALAW for 8-bit A-law samples - AUDIO_ENCODING_LINEAR for 16-bit linear PCM samples - - - -This directory also includes the following sample programs: - - encode.c CCITT ADPCM encoder - decode.c CCITT ADPCM decoder - Makefile makefile for the sample programs - - -The sample programs contain examples of how to call the various compression -routines and pack/unpack the bits. The sample programs read byte streams from -stdin and write to stdout. The input/output data is raw data (no file header -or other identifying information is embedded). The sample programs are -invoked as follows: - - encode [-3|4|5] [-a|u|l] <infile >outfile - decode [-3|4|5] [-a|u|l] <infile >outfile -where: - -3 encode to (decode from) G.723 24kbps (3-bit) data - -4 encode to (decode from) G.721 32kbps (4-bit) data [the default] - -5 encode to (decode from) G.723 40kbps (5-bit) data - -a encode from (decode to) A-law data - -u encode from (decode to) u-law data [the default] - -l encode from (decode to) 16-bit linear data - -Examples: - # Read 16-bit linear and output G.721 - encode -4 -l <pcmfile >g721file - - # Read 40Kbps G.723 and output A-law - decode -5 -a <g723file >alawfile - - # Compress and then decompress u-law data using 24Kbps G.723 - encode -3 <ulawin | deoced -3 >ulawout - diff --git a/gnuradio-core/src/lib/g72x/decode.c b/gnuradio-core/src/lib/g72x/decode.c deleted file mode 100644 index cf8c739c5..000000000 --- a/gnuradio-core/src/lib/g72x/decode.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * decode.c - * - * CCITT ADPCM decoder - * - * Usage : decode [-3|4|5] [-a|u|l] < infile > outfile - */ -#include <stdio.h> -#include "g72x.h" - - -/* - * Unpack input codes and pass them back as bytes. - * Returns 1 if there is residual input, returns -1 if eof, else returns 0. - */ -int -unpack_input( - unsigned char *code, - int bits) -{ - static unsigned int in_buffer = 0; - static int in_bits = 0; - unsigned char in_byte; - - if (in_bits < bits) { - if (fread(&in_byte, sizeof (char), 1, stdin) != 1) { - *code = 0; - return (-1); - } - in_buffer |= (in_byte << in_bits); - in_bits += 8; - } - *code = in_buffer & ((1 << bits) - 1); - in_buffer >>= bits; - in_bits -= bits; - return (in_bits > 0); -} - - -main( - int argc, - char **argv) -{ - short sample; - unsigned char code; - int n; - struct g72x_state state; - int out_coding; - int out_size; - int (*dec_routine)(); - int dec_bits; - - g72x_init_state(&state); - out_coding = AUDIO_ENCODING_ULAW; - out_size = sizeof (char); - dec_routine = g721_decoder; - dec_bits = 4; - - /* Process encoding argument, if any */ - while ((argc > 1) && (argv[1][0] == '-')) { - switch (argv[1][1]) { - case '3': - dec_routine = g723_24_decoder; - dec_bits = 3; - break; - case '4': - dec_routine = g721_decoder; - dec_bits = 4; - break; - case '5': - dec_routine = g723_40_decoder; - dec_bits = 5; - break; - case 'u': - out_coding = AUDIO_ENCODING_ULAW; - out_size = sizeof (char); - break; - case 'a': - out_coding = AUDIO_ENCODING_ALAW; - out_size = sizeof (char); - break; - case 'l': - out_coding = AUDIO_ENCODING_LINEAR; - out_size = sizeof (short); - break; - default: -fprintf(stderr, "CCITT ADPCM Decoder -- usage:\n"); -fprintf(stderr, "\tdecode [-3|4|5] [-a|u|l] < infile > outfile\n"); -fprintf(stderr, "where:\n"); -fprintf(stderr, "\t-3\tProcess G.723 24kbps (3-bit) input data\n"); -fprintf(stderr, "\t-4\tProcess G.721 32kbps (4-bit) input data [default]\n"); -fprintf(stderr, "\t-5\tProcess G.723 40kbps (5-bit) input data\n"); -fprintf(stderr, "\t-a\tGenerate 8-bit A-law data\n"); -fprintf(stderr, "\t-u\tGenerate 8-bit u-law data [default]\n"); -fprintf(stderr, "\t-l\tGenerate 16-bit linear PCM data\n"); - exit(1); - } - argc--; - argv++; - } - - /* Read and unpack input codes and process them */ - while (unpack_input(&code, dec_bits) >= 0) { - sample = (*dec_routine)(code, out_coding, &state); - if (out_size == 2) { - fwrite(&sample, out_size, 1, stdout); - } else { - code = (unsigned char)sample; - fwrite(&code, out_size, 1, stdout); - } - } - fclose(stdout); -} diff --git a/gnuradio-core/src/lib/g72x/encode.c b/gnuradio-core/src/lib/g72x/encode.c deleted file mode 100644 index e74482869..000000000 --- a/gnuradio-core/src/lib/g72x/encode.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * encode.c - * - * CCITT ADPCM encoder - * - * Usage : encode [-3|4|5] [-a|u|l] < infile > outfile - */ -#include <stdio.h> -#include "g72x.h" - - -/* - * Pack output codes into bytes and write them to stdout. - * Returns 1 if there is residual output, else returns 0. - */ -int -pack_output( - unsigned code, - int bits) -{ - static unsigned int out_buffer = 0; - static int out_bits = 0; - unsigned char out_byte; - - out_buffer |= (code << out_bits); - out_bits += bits; - if (out_bits >= 8) { - out_byte = out_buffer & 0xff; - out_bits -= 8; - out_buffer >>= 8; - fwrite(&out_byte, sizeof (char), 1, stdout); - } - return (out_bits > 0); -} - - -main( - int argc, - char **argv) -{ - struct g72x_state state; - unsigned char sample_char; - short sample_short; - unsigned char code; - int resid; - int in_coding; - int in_size; - unsigned *in_buf; - int (*enc_routine)(); - int enc_bits; - - g72x_init_state(&state); - - /* Set defaults to u-law input, G.721 output */ - in_coding = AUDIO_ENCODING_ULAW; - in_size = sizeof (char); - in_buf = (unsigned *)&sample_char; - enc_routine = g721_encoder; - enc_bits = 4; - - /* Process encoding argument, if any */ - while ((argc > 1) && (argv[1][0] == '-')) { - switch (argv[1][1]) { - case '3': - enc_routine = g723_24_encoder; - enc_bits = 3; - break; - case '4': - enc_routine = g721_encoder; - enc_bits = 4; - break; - case '5': - enc_routine = g723_40_encoder; - enc_bits = 5; - break; - case 'u': - in_coding = AUDIO_ENCODING_ULAW; - in_size = sizeof (char); - in_buf = (unsigned *)&sample_char; - break; - case 'a': - in_coding = AUDIO_ENCODING_ALAW; - in_size = sizeof (char); - in_buf = (unsigned *)&sample_char; - break; - case 'l': - in_coding = AUDIO_ENCODING_LINEAR; - in_size = sizeof (short); - in_buf = (unsigned *)&sample_short; - break; - default: -fprintf(stderr, "CCITT ADPCM Encoder -- usage:\n"); -fprintf(stderr, "\tencode [-3|4|5] [-a|u|l] < infile > outfile\n"); -fprintf(stderr, "where:\n"); -fprintf(stderr, "\t-3\tGenerate G.723 24kbps (3-bit) data\n"); -fprintf(stderr, "\t-4\tGenerate G.721 32kbps (4-bit) data [default]\n"); -fprintf(stderr, "\t-5\tGenerate G.723 40kbps (5-bit) data\n"); -fprintf(stderr, "\t-a\tProcess 8-bit A-law input data\n"); -fprintf(stderr, "\t-u\tProcess 8-bit u-law input data [default]\n"); -fprintf(stderr, "\t-l\tProcess 16-bit linear PCM input data\n"); - exit(1); - } - argc--; - argv++; - } - - /* Read input file and process */ - while (fread(in_buf, in_size, 1, stdin) == 1) { - code = (*enc_routine)(in_size == 2 ? sample_short : sample_char, - in_coding, &state); - resid = pack_output(code, enc_bits); - } - - /* Write zero codes until all residual codes are written out */ - while (resid) { - resid = pack_output(0, enc_bits); - } - fclose(stdout); -} diff --git a/gnuradio-core/src/lib/g72x/g711.c b/gnuradio-core/src/lib/g72x/g711.c deleted file mode 100644 index d4d60a5c2..000000000 --- a/gnuradio-core/src/lib/g72x/g711.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g711.c - * - * u-law, A-law and linear PCM conversions. - */ -#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ -#define QUANT_MASK (0xf) /* Quantization field mask. */ -#define NSEGS (8) /* Number of A-law segments. */ -#define SEG_SHIFT (4) /* Left shift for segment number. */ -#define SEG_MASK (0x70) /* Segment field mask. */ - -static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, - 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; - -/* copy from CCITT G.711 specifications */ -unsigned char _u2a[128] = { /* u- to A-law conversions */ - 1, 1, 2, 2, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 27, 29, 31, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, - 46, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128}; - -unsigned char _a2u[128] = { /* A- to u-law conversions */ - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 48, 49, 49, - 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 64, - 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}; - -static int -search( - int val, - short *table, - int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (val <= *table++) - return (i); - } - return (size); -} - -/* - * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law - * - * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. - * - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -unsigned char -linear2alaw( - int pcm_val) /* 2's complement (16-bit range) */ -{ - int mask; - int seg; - unsigned char aval; - - if (pcm_val >= 0) { - mask = 0xD5; /* sign (7th) bit = 1 */ - } else { - mask = 0x55; /* sign bit = 0 */ - pcm_val = -pcm_val - 8; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_end, 8); - - /* Combine the sign, segment, and quantization bits. */ - - if (seg >= 8) /* out of range, return maximum value. */ - return (0x7F ^ mask); - else { - aval = seg << SEG_SHIFT; - if (seg < 2) - aval |= (pcm_val >> 4) & QUANT_MASK; - else - aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; - return (aval ^ mask); - } -} - -/* - * alaw2linear() - Convert an A-law value to 16-bit linear PCM - * - */ -int -alaw2linear( - unsigned char a_val) -{ - int t; - int seg; - - a_val ^= 0x55; - - t = (a_val & QUANT_MASK) << 4; - seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; - switch (seg) { - case 0: - t += 8; - break; - case 1: - t += 0x108; - break; - default: - t += 0x108; - t <<= seg - 1; - } - return ((a_val & SIGN_BIT) ? t : -t); -} - -#define BIAS (0x84) /* Bias for linear code. */ - -/* - * linear2ulaw() - Convert a linear PCM value to u-law - * - * In order to simplify the encoding process, the original linear magnitude - * is biased by adding 33 which shifts the encoding range from (0 - 8158) to - * (33 - 8191). The result can be seen in the following encoding table: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -unsigned char -linear2ulaw( - int pcm_val) /* 2's complement (16-bit range) */ -{ - int mask; - int seg; - unsigned char uval; - - /* Get the sign and the magnitude of the value. */ - if (pcm_val < 0) { - pcm_val = BIAS - pcm_val; - mask = 0x7F; - } else { - pcm_val += BIAS; - mask = 0xFF; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_end, 8); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - if (seg >= 8) /* out of range, return maximum value. */ - return (0x7F ^ mask); - else { - uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); - return (uval ^ mask); - } - -} - -/* - * ulaw2linear() - Convert a u-law value to 16-bit linear PCM - * - * First, a biased linear code is derived from the code word. An unbiased - * output can then be obtained by subtracting 33 from the biased code. - * - * Note that this function expects to be passed the complement of the - * original code word. This is in keeping with ISDN conventions. - */ -int -ulaw2linear( - unsigned char u_val) -{ - int t; - - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; - - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & QUANT_MASK) << 3) + BIAS; - t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; - - return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); -} - -/* A-law to u-law conversion */ -unsigned char -alaw2ulaw( - unsigned char aval) -{ - aval &= 0xff; - return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : - (0x7F ^ _a2u[aval ^ 0x55])); -} - -/* u-law to A-law conversion */ -unsigned char -ulaw2alaw( - unsigned char uval) -{ - uval &= 0xff; - return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : - (0x55 ^ (_u2a[0x7F ^ uval] - 1))); -} diff --git a/gnuradio-core/src/lib/g72x/g721.c b/gnuradio-core/src/lib/g72x/g721.c deleted file mode 100644 index 445f177e8..000000000 --- a/gnuradio-core/src/lib/g72x/g721.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g721.c - * - * Description: - * - * g721_encoder(), g721_decoder() - * - * These routines comprise an implementation of the CCITT G.721 ADPCM - * coding algorithm. Essentially, this implementation is identical to - * the bit level description except for a few deviations which - * take advantage of work station attributes, such as hardware 2's - * complement arithmetic and large memory. Specifically, certain time - * consuming operations such as multiplications are replaced - * with lookup tables and software 2's complement operations are - * replaced with hardware 2's complement. - * - * The deviation from the bit level specification (lookup tables) - * preserves the bit level performance specifications. - * - * As outlined in the G.721 Recommendation, the algorithm is broken - * down into modules. Each section of code below is preceded by - * the name of the module which it is implementing. - * - */ -#include "g72x.h" - -static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; -/* - * Maps G.721 code word to reconstructed scale factor normalized log - * magnitude values. - */ -static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, - 425, 373, 323, 273, 213, 135, 4, -2048}; - -/* Maps G.721 code word to log of scale factor multiplier. */ -static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, - 1122, 355, 198, 112, 64, 41, 18, -12}; -/* - * Maps G.721 code words to a set of values whose long and short - * term averages are computed and then compared to give an indication - * how stationary (steady state) the signal is. - */ -static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, - 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; - -/* - * g721_encoder() - * - * Encodes the input vale of linear PCM, A-law or u-law data sl and returns - * the resulting code. -1 is returned for unknown input coding value. - */ -int -g721_encoder( - int sl, - int in_coding, - struct g72x_state *state_ptr) -{ - short sezi, se, sez; /* ACCUM */ - short d; /* SUBTA */ - short sr; /* ADDB */ - short y; /* MIX */ - short dqsez; /* ADDC */ - short dq, i; - - switch (in_coding) { /* linearize input sample to 14-bit PCM */ - case AUDIO_ENCODING_ALAW: - sl = alaw2linear(sl) >> 2; - break; - case AUDIO_ENCODING_ULAW: - sl = ulaw2linear(sl) >> 2; - break; - case AUDIO_ENCODING_LINEAR: - sl >>= 2; /* 14-bit dynamic range */ - break; - default: - return (-1); - } - - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ - - d = sl - se; /* estimation difference */ - - /* quantize the prediction difference */ - y = step_size(state_ptr); /* quantizer step size */ - i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */ - - dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ - - sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ - - dqsez = sr + sez - se; /* pole prediction diff. */ - - update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); - - return (i); -} - -/* - * g721_decoder() - * - * Description: - * - * Decodes a 4-bit code of G.721 encoded data of i and - * returns the resulting linear PCM, A-law or u-law value. - * return -1 for unknown out_coding value. - */ -int -g721_decoder( - int i, - int out_coding, - struct g72x_state *state_ptr) -{ - short sezi, sei, sez, se; /* ACCUM */ - short y; /* MIX */ - short sr; /* ADDB */ - short dq; - short dqsez; - - i &= 0x0f; /* mask to get proper bits */ - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - y = step_size(state_ptr); /* dynamic quantizer step size */ - - dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ - - sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ - - dqsez = sr - se + sez; /* pole prediction diff. */ - - update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); - - switch (out_coding) { - case AUDIO_ENCODING_ALAW: - return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721)); - case AUDIO_ENCODING_ULAW: - return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721)); - case AUDIO_ENCODING_LINEAR: - return (sr << 2); /* sr was 14-bit dynamic range */ - default: - return (-1); - } -} diff --git a/gnuradio-core/src/lib/g72x/g723_24.c b/gnuradio-core/src/lib/g72x/g723_24.c deleted file mode 100644 index 452f4daeb..000000000 --- a/gnuradio-core/src/lib/g72x/g723_24.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g723_24.c - * - * Description: - * - * g723_24_encoder(), g723_24_decoder() - * - * These routines comprise an implementation of the CCITT G.723 24 Kbps - * ADPCM coding algorithm. Essentially, this implementation is identical to - * the bit level description except for a few deviations which take advantage - * of workstation attributes, such as hardware 2's complement arithmetic. - * - */ -#include "g72x.h" - -/* - * Maps G.723_24 code word to reconstructed scale factor normalized log - * magnitude values. - */ -static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048}; - -/* Maps G.723_24 code word to log of scale factor multiplier. */ -static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128}; - -/* - * Maps G.723_24 code words to a set of values whose long and short - * term averages are computed and then compared to give an indication - * how stationary (steady state) the signal is. - */ -static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; - -static short qtab_723_24[3] = {8, 218, 331}; - -/* - * g723_24_encoder() - * - * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. - * Returns -1 if invalid input coding value. - */ -int -g723_24_encoder( - int sl, - int in_coding, - struct g72x_state *state_ptr) -{ - short sei, sezi, se, sez; /* ACCUM */ - short d; /* SUBTA */ - short y; /* MIX */ - short sr; /* ADDB */ - short dqsez; /* ADDC */ - short dq, i; - - switch (in_coding) { /* linearize input sample to 14-bit PCM */ - case AUDIO_ENCODING_ALAW: - sl = alaw2linear(sl) >> 2; - break; - case AUDIO_ENCODING_ULAW: - sl = ulaw2linear(sl) >> 2; - break; - case AUDIO_ENCODING_LINEAR: - sl >>= 2; /* sl of 14-bit dynamic range */ - break; - default: - return (-1); - } - - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - d = sl - se; /* d = estimation diff. */ - - /* quantize prediction difference d */ - y = step_size(state_ptr); /* quantizer step size */ - i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */ - dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */ - - sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ - - dqsez = sr + sez - se; /* pole prediction diff. */ - - update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - return (i); -} - -/* - * g723_24_decoder() - * - * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns - * the resulting 16-bit linear PCM, A-law or u-law sample value. - * -1 is returned if the output coding is unknown. - */ -int -g723_24_decoder( - int i, - int out_coding, - struct g72x_state *state_ptr) -{ - short sezi, sei, sez, se; /* ACCUM */ - short y; /* MIX */ - short sr; /* ADDB */ - short dq; - short dqsez; - - i &= 0x07; /* mask to get proper bits */ - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - y = step_size(state_ptr); /* adaptive quantizer step size */ - dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */ - - sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ - - dqsez = sr - se + sez; /* pole prediction diff. */ - - update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - switch (out_coding) { - case AUDIO_ENCODING_ALAW: - return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24)); - case AUDIO_ENCODING_ULAW: - return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24)); - case AUDIO_ENCODING_LINEAR: - return (sr << 2); /* sr was of 14-bit dynamic range */ - default: - return (-1); - } -} diff --git a/gnuradio-core/src/lib/g72x/g723_40.c b/gnuradio-core/src/lib/g72x/g723_40.c deleted file mode 100644 index 4858baf40..000000000 --- a/gnuradio-core/src/lib/g72x/g723_40.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g723_40.c - * - * Description: - * - * g723_40_encoder(), g723_40_decoder() - * - * These routines comprise an implementation of the CCITT G.723 40Kbps - * ADPCM coding algorithm. Essentially, this implementation is identical to - * the bit level description except for a few deviations which - * take advantage of workstation attributes, such as hardware 2's - * complement arithmetic. - * - * The deviation from the bit level specification (lookup tables), - * preserves the bit level performance specifications. - * - * As outlined in the G.723 Recommendation, the algorithm is broken - * down into modules. Each section of code below is preceded by - * the name of the module which it is implementing. - * - */ -#include "g72x.h" - -/* - * Maps G.723_40 code word to ructeconstructed scale factor normalized log - * magnitude values. - */ -static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318, - 358, 395, 429, 459, 488, 514, 539, 566, - 566, 539, 514, 488, 459, 429, 395, 358, - 318, 274, 224, 169, 104, 28, -66, -2048}; - -/* Maps G.723_40 code word to log of scale factor multiplier. */ -static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200, - 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, - 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, - 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; - -/* - * Maps G.723_40 code words to a set of values whose long and short - * term averages are computed and then compared to give an indication - * how stationary (steady state) the signal is. - */ -static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200, - 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, - 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, - 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; - -static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339, - 378, 413, 445, 475, 502, 528, 553}; - -/* - * g723_40_encoder() - * - * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens - * the resulting 5-bit CCITT G.723 40Kbps code. - * Returns -1 if the input coding value is invalid. - */ -int -g723_40_encoder( - int sl, - int in_coding, - struct g72x_state *state_ptr) -{ - short sei, sezi, se, sez; /* ACCUM */ - short d; /* SUBTA */ - short y; /* MIX */ - short sr; /* ADDB */ - short dqsez; /* ADDC */ - short dq, i; - - switch (in_coding) { /* linearize input sample to 14-bit PCM */ - case AUDIO_ENCODING_ALAW: - sl = alaw2linear(sl) >> 2; - break; - case AUDIO_ENCODING_ULAW: - sl = ulaw2linear(sl) >> 2; - break; - case AUDIO_ENCODING_LINEAR: - sl >>= 2; /* sl of 14-bit dynamic range */ - break; - default: - return (-1); - } - - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - d = sl - se; /* d = estimation difference */ - - /* quantize prediction difference */ - y = step_size(state_ptr); /* adaptive quantizer step size */ - i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */ - - dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */ - - sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */ - - dqsez = sr + sez - se; /* dqsez = pole prediction diff. */ - - update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - return (i); -} - -/* - * g723_40_decoder() - * - * Decodes a 5-bit CCITT G.723 40Kbps code and returns - * the resulting 16-bit linear PCM, A-law or u-law sample value. - * -1 is returned if the output coding is unknown. - */ -int -g723_40_decoder( - int i, - int out_coding, - struct g72x_state *state_ptr) -{ - short sezi, sei, sez, se; /* ACCUM */ - short y; /* MIX */ - short sr; /* ADDB */ - short dq; - short dqsez; - - i &= 0x1f; /* mask to get proper bits */ - sezi = predictor_zero(state_ptr); - sez = sezi >> 1; - sei = sezi + predictor_pole(state_ptr); - se = sei >> 1; /* se = estimated signal */ - - y = step_size(state_ptr); /* adaptive quantizer step size */ - dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */ - - sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */ - - dqsez = sr - se + sez; /* pole prediction diff. */ - - update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); - - switch (out_coding) { - case AUDIO_ENCODING_ALAW: - return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40)); - case AUDIO_ENCODING_ULAW: - return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40)); - case AUDIO_ENCODING_LINEAR: - return (sr << 2); /* sr was of 14-bit dynamic range */ - default: - return (-1); - } -} diff --git a/gnuradio-core/src/lib/g72x/g72x.c b/gnuradio-core/src/lib/g72x/g72x.c deleted file mode 100644 index 9a823c755..000000000 --- a/gnuradio-core/src/lib/g72x/g72x.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ -#include <stdlib.h> -/* - * g72x.c - * - * Common routines for G.721 and G.723 conversions. - */ - -#include "g72x.h" - -static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, - 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000}; - -/* - * quan() - * - * quantizes the input val against the table of size short integers. - * It returns i if table[i - 1] <= val < table[i]. - * - * Using linear search for simple coding. - */ -static int -quan( - int val, - short *table, - int size) -{ - int i; - - for (i = 0; i < size; i++) - if (val < *table++) - break; - return (i); -} - -/* - * fmult() - * - * returns the integer product of the 14-bit integer "an" and - * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". - */ -static int -fmult( - int an, - int srn) -{ - short anmag, anexp, anmant; - short wanexp, wanmant; - short retval; - - anmag = (an > 0) ? an : ((-an) & 0x1FFF); - anexp = quan(anmag, power2, 15) - 6; - anmant = (anmag == 0) ? 32 : - (anexp >= 0) ? anmag >> anexp : anmag << -anexp; - wanexp = anexp + ((srn >> 6) & 0xF) - 13; - - wanmant = (anmant * (srn & 077) + 0x30) >> 4; - retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : - (wanmant >> -wanexp); - - return (((an ^ srn) < 0) ? -retval : retval); -} - -/* - * g72x_init_state() - * - * This routine initializes and/or resets the g72x_state structure - * pointed to by 'state_ptr'. - * All the initial state values are specified in the CCITT G.721 document. - */ -void -g72x_init_state( - struct g72x_state *state_ptr) -{ - int cnta; - - state_ptr->yl = 34816; - state_ptr->yu = 544; - state_ptr->dms = 0; - state_ptr->dml = 0; - state_ptr->ap = 0; - for (cnta = 0; cnta < 2; cnta++) { - state_ptr->a[cnta] = 0; - state_ptr->pk[cnta] = 0; - state_ptr->sr[cnta] = 32; - } - for (cnta = 0; cnta < 6; cnta++) { - state_ptr->b[cnta] = 0; - state_ptr->dq[cnta] = 32; - } - state_ptr->td = 0; -} - -/* - * predictor_zero() - * - * computes the estimated signal from 6-zero predictor. - * - */ -int -predictor_zero( - struct g72x_state *state_ptr) -{ - int i; - int sezi; - - sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); - for (i = 1; i < 6; i++) /* ACCUM */ - sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); - return (sezi); -} -/* - * predictor_pole() - * - * computes the estimated signal from 2-pole predictor. - * - */ -int -predictor_pole( - struct g72x_state *state_ptr) -{ - return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + - fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); -} -/* - * step_size() - * - * computes the quantization step size of the adaptive quantizer. - * - */ -int -step_size( - struct g72x_state *state_ptr) -{ - int y; - int dif; - int al; - - if (state_ptr->ap >= 256) - return (state_ptr->yu); - else { - y = state_ptr->yl >> 6; - dif = state_ptr->yu - y; - al = state_ptr->ap >> 2; - if (dif > 0) - y += (dif * al) >> 6; - else if (dif < 0) - y += (dif * al + 0x3F) >> 6; - return (y); - } -} - -/* - * quantize() - * - * Given a raw sample, 'd', of the difference signal and a - * quantization step size scale factor, 'y', this routine returns the - * ADPCM codeword to which that sample gets quantized. The step - * size scale factor division operation is done in the log base 2 domain - * as a subtraction. - */ -int -quantize( - int d, /* Raw difference signal sample */ - int y, /* Step size multiplier */ - short *table, /* quantization table */ - int size) /* table size of short integers */ -{ - short dqm; /* Magnitude of 'd' */ - short exp; /* Integer part of base 2 log of 'd' */ - short mant; /* Fractional part of base 2 log */ - short dl; /* Log of magnitude of 'd' */ - short dln; /* Step size scale factor normalized log */ - int i; - - /* - * LOG - * - * Compute base 2 log of 'd', and store in 'dl'. - */ - dqm = abs(d); - exp = quan(dqm >> 1, power2, 15); - mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */ - dl = (exp << 7) + mant; - - /* - * SUBTB - * - * "Divide" by step size multiplier. - */ - dln = dl - (y >> 2); - - /* - * QUAN - * - * Obtain codword i for 'd'. - */ - i = quan(dln, table, size); - if (d < 0) /* take 1's complement of i */ - return ((size << 1) + 1 - i); - else if (i == 0) /* take 1's complement of 0 */ - return ((size << 1) + 1); /* new in 1988 */ - else - return (i); -} -/* - * reconstruct() - * - * Returns reconstructed difference signal 'dq' obtained from - * codeword 'i' and quantization step size scale factor 'y'. - * Multiplication is performed in log base 2 domain as addition. - */ -int -reconstruct( - int sign, /* 0 for non-negative value */ - int dqln, /* G.72x codeword */ - int y) /* Step size multiplier */ -{ - short dql; /* Log of 'dq' magnitude */ - short dex; /* Integer part of log */ - short dqt; - short dq; /* Reconstructed difference signal sample */ - - dql = dqln + (y >> 2); /* ADDA */ - - if (dql < 0) { - return ((sign) ? -0x8000 : 0); - } else { /* ANTILOG */ - dex = (dql >> 7) & 15; - dqt = 128 + (dql & 127); - dq = (dqt << 7) >> (14 - dex); - return ((sign) ? (dq - 0x8000) : dq); - } -} - - -/* - * update() - * - * updates the state variables for each output code - */ -void -update( - int code_size, /* distinguish 723_40 with others */ - int y, /* quantizer step size */ - int wi, /* scale factor multiplier */ - int fi, /* for long/short term energies */ - int dq, /* quantized prediction difference */ - int sr, /* reconstructed signal */ - int dqsez, /* difference from 2-pole predictor */ - struct g72x_state *state_ptr) /* coder state pointer */ -{ - int cnt; - short mag, exp; /* Adaptive predictor, FLOAT A */ - short a2p = 0; /* LIMC */ - short a1ul; /* UPA1 */ - short pks1; /* UPA2 */ - short fa1; - char tr; /* tone/transition detector */ - short ylint, thr2, dqthr; - short ylfrac, thr1; - short pk0; - - pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ - - mag = dq & 0x7FFF; /* prediction difference magnitude */ - /* TRANS */ - ylint = state_ptr->yl >> 15; /* exponent part of yl */ - ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ - thr1 = (32 + ylfrac) << ylint; /* threshold */ - thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ - dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ - if (state_ptr->td == 0) /* signal supposed voice */ - tr = 0; - else if (mag <= dqthr) /* supposed data, but small mag */ - tr = 0; /* treated as voice */ - else /* signal is data (modem) */ - tr = 1; - - /* - * Quantizer scale factor adaptation. - */ - - /* FUNCTW & FILTD & DELAY */ - /* update non-steady state step size multiplier */ - state_ptr->yu = y + ((wi - y) >> 5); - - /* LIMB */ - if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ - state_ptr->yu = 544; - else if (state_ptr->yu > 5120) - state_ptr->yu = 5120; - - /* FILTE & DELAY */ - /* update steady state step size multiplier */ - state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); - - /* - * Adaptive predictor coefficients. - */ - if (tr == 1) { /* reset a's and b's for modem signal */ - state_ptr->a[0] = 0; - state_ptr->a[1] = 0; - state_ptr->b[0] = 0; - state_ptr->b[1] = 0; - state_ptr->b[2] = 0; - state_ptr->b[3] = 0; - state_ptr->b[4] = 0; - state_ptr->b[5] = 0; - } else { /* update a's and b's */ - pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ - - /* update predictor pole a[1] */ - a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); - if (dqsez != 0) { - fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; - if (fa1 < -8191) /* a2p = function of fa1 */ - a2p -= 0x100; - else if (fa1 > 8191) - a2p += 0xFF; - else - a2p += fa1 >> 5; - - if (pk0 ^ state_ptr->pk[1]) - /* LIMC */ - if (a2p <= -12160) - a2p = -12288; - else if (a2p >= 12416) - a2p = 12288; - else - a2p -= 0x80; - else if (a2p <= -12416) - a2p = -12288; - else if (a2p >= 12160) - a2p = 12288; - else - a2p += 0x80; - } - - /* TRIGB & DELAY */ - state_ptr->a[1] = a2p; - - /* UPA1 */ - /* update predictor pole a[0] */ - state_ptr->a[0] -= state_ptr->a[0] >> 8; - if (dqsez != 0){ - if (pks1 == 0) - state_ptr->a[0] += 192; - else - state_ptr->a[0] -= 192; - } - - /* LIMD */ - a1ul = 15360 - a2p; - if (state_ptr->a[0] < -a1ul) - state_ptr->a[0] = -a1ul; - else if (state_ptr->a[0] > a1ul) - state_ptr->a[0] = a1ul; - - /* UPB : update predictor zeros b[6] */ - for (cnt = 0; cnt < 6; cnt++) { - if (code_size == 5) /* for 40Kbps G.723 */ - state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; - else /* for G.721 and 24Kbps G.723 */ - state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; - if (dq & 0x7FFF) { /* XOR */ - if ((dq ^ state_ptr->dq[cnt]) >= 0) - state_ptr->b[cnt] += 128; - else - state_ptr->b[cnt] -= 128; - } - } - } - - for (cnt = 5; cnt > 0; cnt--) - state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; - /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ - if (mag == 0) { - state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; - } else { - exp = quan(mag, power2, 15); - state_ptr->dq[0] = (dq >= 0) ? - (exp << 6) + ((mag << 6) >> exp) : - (exp << 6) + ((mag << 6) >> exp) - 0x400; - } - - state_ptr->sr[1] = state_ptr->sr[0]; - /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ - if (sr == 0) { - state_ptr->sr[0] = 0x20; - } else if (sr > 0) { - exp = quan(sr, power2, 15); - state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp); - } else if (sr > -32768) { - mag = -sr; - exp = quan(mag, power2, 15); - state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400; - } else - state_ptr->sr[0] = 0xFC20; - - /* DELAY A */ - state_ptr->pk[1] = state_ptr->pk[0]; - state_ptr->pk[0] = pk0; - - /* TONE */ - if (tr == 1) /* this sample has been treated as data */ - state_ptr->td = 0; /* next one will be treated as voice */ - else if (a2p < -11776) /* small sample-to-sample correlation */ - state_ptr->td = 1; /* signal may be data */ - else /* signal is voice */ - state_ptr->td = 0; - - /* - * Adaptation speed control. - */ - state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ - state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ - - if (tr == 1) - state_ptr->ap = 256; - else if (y < 1536) /* SUBTC */ - state_ptr->ap += (0x200 - state_ptr->ap) >> 4; - else if (state_ptr->td == 1) - state_ptr->ap += (0x200 - state_ptr->ap) >> 4; - else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= - (state_ptr->dml >> 3)) - state_ptr->ap += (0x200 - state_ptr->ap) >> 4; - else - state_ptr->ap += (-state_ptr->ap) >> 4; -} - -/* - * tandem_adjust(sr, se, y, i, sign) - * - * At the end of ADPCM decoding, it simulates an encoder which may be receiving - * the output of this decoder as a tandem process. If the output of the - * simulated encoder differs from the input to this decoder, the decoder output - * is adjusted by one level of A-law or u-law codes. - * - * Input: - * sr decoder output linear PCM sample, - * se predictor estimate sample, - * y quantizer step size, - * i decoder input code, - * sign sign bit of code i - * - * Return: - * adjusted A-law or u-law compressed sample. - */ -int -tandem_adjust_alaw( - int sr, /* decoder output linear PCM sample */ - int se, /* predictor estimate sample */ - int y, /* quantizer step size */ - int i, /* decoder input code */ - int sign, - short *qtab) -{ - unsigned char sp; /* A-law compressed 8-bit code */ - short dx; /* prediction error */ - char id; /* quantized prediction error */ - int sd; /* adjusted A-law decoded sample value */ - int im; /* biased magnitude of i */ - int imx; /* biased magnitude of id */ - - if (sr <= -32768) - sr = -1; - sp = linear2alaw((sr >> 1) << 3); /* short to A-law compression */ - dx = (alaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ - id = quantize(dx, y, qtab, sign - 1); - - if (id == i) { /* no adjustment on sp */ - return (sp); - } else { /* sp adjustment needed */ - /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ - im = i ^ sign; /* 2's complement to biased unsigned */ - imx = id ^ sign; - - if (imx > im) { /* sp adjusted to next lower value */ - if (sp & 0x80) { - sd = (sp == 0xD5) ? 0x55 : - ((sp ^ 0x55) - 1) ^ 0x55; - } else { - sd = (sp == 0x2A) ? 0x2A : - ((sp ^ 0x55) + 1) ^ 0x55; - } - } else { /* sp adjusted to next higher value */ - if (sp & 0x80) - sd = (sp == 0xAA) ? 0xAA : - ((sp ^ 0x55) + 1) ^ 0x55; - else - sd = (sp == 0x55) ? 0xD5 : - ((sp ^ 0x55) - 1) ^ 0x55; - } - return (sd); - } -} - -int -tandem_adjust_ulaw( - int sr, /* decoder output linear PCM sample */ - int se, /* predictor estimate sample */ - int y, /* quantizer step size */ - int i, /* decoder input code */ - int sign, - short *qtab) -{ - unsigned char sp; /* u-law compressed 8-bit code */ - short dx; /* prediction error */ - char id; /* quantized prediction error */ - int sd; /* adjusted u-law decoded sample value */ - int im; /* biased magnitude of i */ - int imx; /* biased magnitude of id */ - - if (sr <= -32768) - sr = 0; - sp = linear2ulaw(sr << 2); /* short to u-law compression */ - dx = (ulaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ - id = quantize(dx, y, qtab, sign - 1); - if (id == i) { - return (sp); - } else { - /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ - im = i ^ sign; /* 2's complement to biased unsigned */ - imx = id ^ sign; - if (imx > im) { /* sp adjusted to next lower value */ - if (sp & 0x80) - sd = (sp == 0xFF) ? 0x7E : sp + 1; - else - sd = (sp == 0) ? 0 : sp - 1; - - } else { /* sp adjusted to next higher value */ - if (sp & 0x80) - sd = (sp == 0x80) ? 0x80 : sp - 1; - else - sd = (sp == 0x7F) ? 0xFE : sp + 1; - } - return (sd); - } -} - - - - - - - - - - - - diff --git a/gnuradio-core/src/lib/g72x/g72x.h b/gnuradio-core/src/lib/g72x/g72x.h deleted file mode 100644 index 33807171a..000000000 --- a/gnuradio-core/src/lib/g72x/g72x.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g72x.h - * - * Header file for CCITT conversion routines. - * - */ -#ifndef _G72X_H -#define _G72X_H - -#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */ -#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */ -#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */ - -/* - * The following is the definition of the state structure - * used by the G.721/G.723 encoder and decoder to preserve their internal - * state between successive calls. The meanings of the majority - * of the state structure fields are explained in detail in the - * CCITT Recommendation G.721. The field names are essentially indentical - * to variable names in the bit level description of the coding algorithm - * included in this Recommendation. - */ -struct g72x_state { - long yl; /* Locked or steady state step size multiplier. */ - short yu; /* Unlocked or non-steady state step size multiplier. */ - short dms; /* Short term energy estimate. */ - short dml; /* Long term energy estimate. */ - short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ - - short a[2]; /* Coefficients of pole portion of prediction filter. */ - short b[6]; /* Coefficients of zero portion of prediction filter. */ - short pk[2]; /* - * Signs of previous two samples of a partially - * reconstructed signal. - */ - short dq[6]; /* - * Previous 6 samples of the quantized difference - * signal represented in an internal floating point - * format. - */ - short sr[2]; /* - * Previous 2 samples of the quantized difference - * signal represented in an internal floating point - * format. - */ - char td; /* delayed tone detect, new in 1988 version */ -}; - -/* External function definitions. */ - -extern void g72x_init_state(struct g72x_state *); -extern int g721_encoder( - int sample, - int in_coding, - struct g72x_state *state_ptr); -extern int g721_decoder( - int code, - int out_coding, - struct g72x_state *state_ptr); -extern int g723_24_encoder( - int sample, - int in_coding, - struct g72x_state *state_ptr); -extern int g723_24_decoder( - int code, - int out_coding, - struct g72x_state *state_ptr); -extern int g723_40_encoder( - int sample, - int in_coding, - struct g72x_state *state_ptr); -extern int g723_40_decoder( - int code, - int out_coding, - struct g72x_state *state_ptr); - - -extern int -quantize( - int d, - int y, - short *table, - int size); -extern int reconstruct(int,int,int);void - -extern update( - int code_size, - int y, - int wi, - int fi, - int dq, - int sr, - int dqsez, - struct g72x_state *state_ptr); -extern int -tandem_adjust_alaw( - int sr, - int se, - int y, - int i, - int sign, - short *qtab); - -extern int -tandem_adjust_ulaw( - int sr, - int se, - int y, - int i, - int sign, - short *qtab); - -extern unsigned char -linear2alaw( - int pcm_val); - -extern int -alaw2linear( - unsigned char a_val); - -extern unsigned char -linear2ulaw(int pcm_val); - -extern int ulaw2linear( unsigned char u_val); - -extern int predictor_zero(struct g72x_state *state_ptr); - -extern int predictor_pole( struct g72x_state *state_ptr); -extern int step_size( struct g72x_state *state_ptr); -#endif /* !_G72X_H */ diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am index 15272dd5c..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,13 +243,10 @@ 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_mpsk_receiver_cc.h \ gr_nco.h \ gr_nlog10_ff.h \ gr_nop.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 fd158cd1f..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> @@ -98,10 +93,10 @@ #include <gr_ofdm_cyclic_prefixer.h> #include <gr_ofdm_mapper_bcv.h> #include <gr_ofdm_frame_sink.h> + //#include <gr_ofdm_frame_sink2.h> #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> @@ -109,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> @@ -140,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" @@ -196,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" @@ -204,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" @@ -225,10 +212,10 @@ %include "gr_ofdm_cyclic_prefixer.i" %include "gr_ofdm_mapper_bcv.i" %include "gr_ofdm_frame_sink.i" + //%include "gr_ofdm_frame_sink2.i" %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" @@ -236,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" @@ -267,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_binary_slicer_fb.cc b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc deleted file mode 100644 index ae8903abb..000000000 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_binary_slicer_fb.h> -#include <gr_io_signature.h> -#include <stdexcept> - -gr_binary_slicer_fb_sptr -gr_make_binary_slicer_fb () -{ - return gnuradio::get_initial_sptr(new gr_binary_slicer_fb ()); -} - -gr_binary_slicer_fb::gr_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) -{ - 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]); - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h deleted file mode 100644 index 2aa4a0828..000000000 --- a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h +++ /dev/null @@ -1,51 +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. - */ - -#ifndef INCLUDED_GR_BINARY_SLICER_FB_H -#define INCLUDED_GR_BINARY_SLICER_FB_H - -#include <gr_sync_block.h> - -class gr_binary_slicer_fb; -typedef boost::shared_ptr<gr_binary_slicer_fb> gr_binary_slicer_fb_sptr; - -gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); - -/*! - * \brief slice float binary symbol outputting 1 bit output - * \ingroup converter_blk - * - * x < 0 --> 0 - * x >= 0 --> 1 - */ -class gr_binary_slicer_fb : public gr_sync_block -{ - friend gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); - gr_binary_slicer_fb (); - - public: - 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_clock_recovery_mm_cc.cc b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc deleted file mode 100644 index 7c20f7fd9..000000000 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc +++ /dev/null @@ -1,215 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_io_signature.h> -#include <gr_prefs.h> -#include <gr_clock_recovery_mm_cc.h> -#include <gri_mmse_fir_interpolator_cc.h> -#include <stdexcept> -#include <cstdio> - - -// 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) -{ - return gnuradio::get_initial_sptr(new gr_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) - : gr_block ("clock_recovery_mm_cc", - gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 2, sizeof (gr_complex))), - 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()), - d_verbose(gr_prefs::singleton()->get_bool("clock_recovery_mm_cc", "verbose", false)), - d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0) -{ - if (omega <= 0.0) - throw std::out_of_range ("clock rate must be > 0"); - if (gain_mu < 0 || gain_omega < 0) - throw std::out_of_range ("Gains must be non-negative"); - - set_omega(omega); // also sets min and max omega - set_relative_rate (1.0 / omega); - set_history(3); // ensure 2 extra input sample is available -} - -gr_clock_recovery_mm_cc::~gr_clock_recovery_mm_cc () -{ - delete d_interp; -} - -void -gr_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++) - ninput_items_required[i] = - (int) ceil((noutput_items * d_omega) + d_interp->ntaps()) + FUDGE; -} - -gr_complex -gr_clock_recovery_mm_cc::slicer_0deg (gr_complex sample) -{ - float real=0, imag=0; - - if(sample.real() > 0) - real = 1; - if(sample.imag() > 0) - imag = 1; - return gr_complex(real,imag); -} - -gr_complex -gr_clock_recovery_mm_cc::slicer_45deg (gr_complex sample) -{ - float real= -1, imag = -1; - if(sample.real() > 0) - real=1; - if(sample.imag() > 0) - imag = 1; - return gr_complex(real,imag); -} - -/* - Modified Mueller and Muller clock recovery circuit - Based: - 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. -*/ - -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) -{ - 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]; - - bool write_foptr = output_items.size() >= 2; - - int ii = 0; // input index - int oo = 0; // output index - int ni = ninput_items[0] - d_interp->ntaps() - FUDGE; // don't use more input than this - - assert(d_mu >= 0.0); - assert(d_mu <= 1.0); - - float mm_val=0; - gr_complex u, x, y; - - // This loop writes the error to the second output, if it exists - if (write_foptr) { - while(oo < noutput_items && ii < ni) { - d_p_2T = d_p_1T; - d_p_1T = d_p_0T; - d_p_0T = d_interp->interpolate (&in[ii], d_mu); - - d_c_2T = d_c_1T; - d_c_1T = d_c_0T; - d_c_0T = slicer_0deg(d_p_0T); - - x = (d_c_0T - d_c_2T) * conj(d_p_1T); - y = (d_p_0T - d_p_2T) * conj(d_c_1T); - u = y - x; - mm_val = u.real(); - out[oo++] = d_p_0T; - - // limit mm_val - mm_val = gr_branchless_clip(mm_val,1.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 - - d_mu = d_mu + d_omega + d_gain_mu * mm_val; - ii += (int)floor(d_mu); - d_mu -= floor(d_mu); - - // write the error signal to the second output - foptr[oo-1] = gr_complex(d_mu,0); - - if (ii < 0) // clamp it. This should only happen with bogus input - ii = 0; - } - } - // This loop does not write to the second output (ugly, but faster) - else { - while(oo < noutput_items && ii < ni) { - d_p_2T = d_p_1T; - d_p_1T = d_p_0T; - d_p_0T = d_interp->interpolate (&in[ii], d_mu); - - d_c_2T = d_c_1T; - d_c_1T = d_c_0T; - d_c_0T = slicer_0deg(d_p_0T); - - x = (d_c_0T - d_c_2T) * conj(d_p_1T); - y = (d_p_0T - d_p_2T) * conj(d_c_1T); - u = y - x; - mm_val = u.real(); - out[oo++] = d_p_0T; - - // limit mm_val - mm_val = gr_branchless_clip(mm_val,1.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 - - d_mu = d_mu + d_omega + d_gain_mu * mm_val; - ii += (int)floor(d_mu); - d_mu -= floor(d_mu); - - if(d_verbose) { - printf("%f\t%f\n", d_omega, d_mu); - } - - if (ii < 0) // clamp it. This should only happen with bogus input - ii = 0; - } - } - - if (ii > 0){ - if (ii > ninput_items[0]){ - fprintf(stderr, "gr_clock_recovery_mm_cc: ii > ninput_items[0] (%d > %d)\n", - ii, ninput_items[0]); - assert(0); - } - consume_each (ii); - } - - return oo; -} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h deleted file mode 100644 index 04227a145..000000000 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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_CLOCK_RECOVERY_MM_CC_H -#define INCLUDED_GR_CLOCK_RECOVERY_MM_CC_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; - -// public constructor -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); - -/*! - * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output. - * \ingroup sync_blk - * - * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. - * The complex version here is based on: - * Modified Mueller and Muller clock recovery circuit - * Based: - * 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_clock_recovery_mm_cc : public gr_block -{ - public: - ~gr_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, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - float mu() const { return d_mu;} - float omega() const { return d_omega;} - float gain_mu() const { return d_gain_mu;} - float gain_omega() const { return d_gain_omega;} - void set_verbose (bool verbose) { d_verbose = verbose; } - - void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } - void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } - void set_mu (float mu) { d_mu = mu; } - void set_omega (float omega) { - d_omega = omega; - d_min_omega = omega*(1.0 - d_omega_relative_limit); - d_max_omega = omega*(1.0 + d_omega_relative_limit); - d_omega_mid = 0.5*(d_min_omega+d_max_omega); - } - -protected: - gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limi); - - private: - float d_mu; - float d_omega; - float d_gain_omega; - float d_min_omega; // minimum allowed omega - float d_max_omega; // maximum allowed omeg - float d_omega_relative_limit; // used to compute min and max omega - float d_omega_mid; - float d_gain_mu; - gr_complex d_last_sample; - gri_mmse_fir_interpolator_cc *d_interp; - bool d_verbose; - - gr_complex d_p_2T; - gr_complex d_p_1T; - gr_complex d_p_0T; - - gr_complex d_c_2T; - gr_complex d_c_1T; - gr_complex d_c_0T; - - gr_complex slicer_0deg (gr_complex sample); - gr_complex slicer_45deg (gr_complex sample); - - friend 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); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i deleted file mode 100644 index 27eb70b95..000000000 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,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); - -class gr_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); - -public: - float mu() const { return d_mu;} - float omega() const { return d_omega;} - float gain_mu() const { return d_gain_mu;} - float gain_omega() const { return d_gain_omega;} - - void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } - void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } - void set_mu (float omega) { d_mu = mu; } - void set_omega (float omega) { d_omega = omega; - d_min_omega = omega*(1.0 - d_omega_relative_limit); - d_max_omega = omega*(1.0 + d_omega_relative_limit); - } - void set_verbose (bool verbose) { d_verbose = verbose; } -}; diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc deleted file mode 100644 index bb5a27071..000000000 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,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_io_signature.h> -#include <gr_clock_recovery_mm_ff.h> -#include <gri_mmse_fir_interpolator.h> -#include <stdexcept> - -#define DEBUG_CR_MM_FF 0 // must be defined as 0 or 1 - -// 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) -{ - return gnuradio::get_initial_sptr(new gr_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) - : gr_block ("clock_recovery_mm_ff", - gr_make_io_signature (1, 1, sizeof (float)), - gr_make_io_signature (1, 1, sizeof (float))), - d_mu (mu), d_gain_omega(gain_omega), d_gain_mu(gain_mu), - d_last_sample(0), d_interp(new gri_mmse_fir_interpolator()), - d_logfile(0), d_omega_relative_limit(omega_relative_limit) -{ - if (omega < 1) - throw std::out_of_range ("clock rate must be > 0"); - if (gain_mu < 0 || gain_omega < 0) - throw std::out_of_range ("Gains must be non-negative"); - - set_omega(omega); // also sets min and max omega - set_relative_rate (1.0 / omega); - - if (DEBUG_CR_MM_FF) - d_logfile = fopen("cr_mm_ff.dat", "wb"); -} - -gr_clock_recovery_mm_ff::~gr_clock_recovery_mm_ff () -{ - delete d_interp; - - if (DEBUG_CR_MM_FF && d_logfile){ - fclose(d_logfile); - d_logfile = 0; - } -} - -void -gr_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++) - ninput_items_required[i] = - (int) ceil((noutput_items * d_omega) + d_interp->ntaps()); -} - -static inline float -slice(float x) -{ - return x < 0 ? -1.0F : 1.0F; -} - -/* - * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. - * - * See "Digital Communication Receivers: Synchronization, Channel - * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. - * 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) -{ - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - int ii = 0; // input index - int oo = 0; // output index - int ni = ninput_items[0] - d_interp->ntaps(); // don't use more input than this - float mm_val; - - while (oo < noutput_items && ii < ni ){ - - // produce output sample - out[oo] = d_interp->interpolate (&in[ii], d_mu); - mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample; - d_last_sample = out[oo]; - - 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 - d_mu = d_mu + d_omega + d_gain_mu * mm_val; - - ii += (int) floor(d_mu); - d_mu = d_mu - floor(d_mu); - oo++; - - if (DEBUG_CR_MM_FF && d_logfile){ - fwrite(&d_omega, sizeof(d_omega), 1, d_logfile); - } - } - - consume_each (ii); - - return oo; -} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h deleted file mode 100644 index d2ec6d3e6..000000000 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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_CLOCK_RECOVERY_MM_FF_H -#define INCLUDED_GR_CLOCK_RECOVERY_MM_FF_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; - -// 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=0.001); - -/*! - * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output. - * \ingroup sync_blk - * - * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. - * - * See "Digital Communication Receivers: Synchronization, Channel - * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. - * ISBN 0-471-50275-8. - */ -class gr_clock_recovery_mm_ff : public gr_block -{ - public: - ~gr_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, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - float mu() const { return d_mu;} - float omega() const { return d_omega;} - float gain_mu() const { return d_gain_mu;} - float gain_omega() const { return d_gain_omega;} - - void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } - void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } - void set_mu (float mu) { d_mu = mu; } - void set_omega (float omega){ - d_omega = omega; - d_min_omega = omega*(1.0 - d_omega_relative_limit); - d_max_omega = omega*(1.0 + d_omega_relative_limit); - d_omega_mid = 0.5*(d_min_omega+d_max_omega); - } - -protected: - gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, - float omega_relative_limit); - - private: - float d_mu; // fractional sample position [0.0, 1.0] - float d_omega; // nominal frequency - float d_min_omega; // minimum allowed omega - float d_omega_mid; // average omega - float d_max_omega; // maximum allowed omega - float d_gain_omega; // gain for adjusting omega - float d_gain_mu; // gain for adjusting mu - float d_last_sample; - gri_mmse_fir_interpolator *d_interp; - FILE *d_logfile; - float d_omega_relative_limit; // used to compute min and max omega - - friend 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); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i deleted file mode 100644 index 1b2437000..000000000 --- a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,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); - -class gr_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); - -public: - float mu() const; - float omega() const; - float gain_mu() const; - float gain_omega() const; - - void set_gain_mu (float gain_mu); - void set_gain_omega (float gain_omega); - void set_mu (float omega); - void set_omega (float omega); -}; 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.h b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h deleted file mode 100644 index fd7079c12..000000000 --- a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h +++ /dev/null @@ -1,65 +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. - */ - -#ifndef INCLUDED_GR_CONSTELLATION_DECODER_CB_H -#define INCLUDED_GR_CONSTELLATION_DECODER_CB_H - -#include <gr_sync_block.h> -#include <vector> - -class gr_constellation_decoder_cb; -typedef boost::shared_ptr<gr_constellation_decoder_cb> gr_constellation_decoder_cb_sptr; - -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); - -/*! - * \brief Constellation Decoder - * \ingroup coding_blk - * - */ -class gr_constellation_decoder_cb : public gr_sync_block -{ - - private: - std::vector<gr_complex> d_sym_position; - std::vector<unsigned char> d_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); - - gr_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out); //constructor - - public: - bool set_constellation(const std::vector<gr_complex> &sym_position, - const std::vector<unsigned char> &sym_value_out); - - ~gr_constellation_decoder_cb(); //destructor - - 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_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_correlate_access_code_bb.cc b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc deleted file mode 100644 index 15f673411..000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_correlate_access_code_bb.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <gr_count_bits.h> -#include <cstdio> - - -#define VERBOSE 0 - - -gr_correlate_access_code_bb_sptr -gr_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)); -} - - -gr_correlate_access_code_bb::gr_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)), - gr_make_io_signature (1, 1, sizeof(char))), - d_data_reg(0), d_flag_reg(0), d_flag_bit(0), d_mask(0), - d_threshold(threshold) - -{ - if (!set_access_code(access_code)){ - fprintf(stderr, "gr_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 () -{ -} - -bool -gr_correlate_access_code_bb::set_access_code( - const std::string &access_code) -{ - unsigned len = access_code.length(); // # of bytes in string - if (len > 64) - return false; - - // set len top bits to 1. - d_mask = ((~0ULL) >> (64 - len)) << (64 - len); - - d_flag_bit = 1LL << (64 - len); // Where we or-in new flag values. - // new data always goes in 0x0000000000000001 - d_access_code = 0; - for (unsigned i=0; i < 64; i++){ - d_access_code <<= 1; - if (i < len) - d_access_code |= access_code[i] & 1; // look at LSB only - } - - return true; -} - -int -gr_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]; - - for (int i = 0; i < noutput_items; i++){ - - // compute output value - unsigned int t = 0; - - t |= ((d_data_reg >> 63) & 0x1) << 0; - t |= ((d_flag_reg >> 63) & 0x1) << 1; // flag bit - out[i] = t; - - // compute hamming distance between desired access code and current data - unsigned long long wrong_bits = 0; - unsigned int nwrong = d_threshold+1; - int new_flag = 0; - - wrong_bits = (d_data_reg ^ d_access_code) & d_mask; - nwrong = gr_count_bits64(wrong_bits); - - // test for access code with up to threshold errors - new_flag = (nwrong <= d_threshold); - -#if VERBOSE - if(new_flag) { - fprintf(stderr, "access code found: %llx\n", d_access_code); - } - else { - fprintf(stderr, "%llx ==> %llx\n", d_access_code, d_data_reg); - } -#endif - - // shift in new data and new flag - d_data_reg = (d_data_reg << 1) | (in[i] & 0x1); - d_flag_reg = (d_flag_reg << 1); - if (new_flag) { - d_flag_reg |= d_flag_bit; - } - } - - return noutput_items; -} - diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h deleted file mode 100644 index 581713c14..000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h +++ /dev/null @@ -1,83 +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. - */ - -#ifndef INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H -#define INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_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; - -/*! - * \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); - -/*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup sync_blk - * - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) - * - * Each output byte contains two valid bits, the data bit, and the - * flag bit. The LSB (bit 0) is the data bit, and is the original - * input data, delayed 64 bits. Bit 1 is the - * 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 -{ - friend gr_correlate_access_code_bb_sptr - gr_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 - unsigned long long d_data_reg; // used to look for access_code - unsigned long long d_flag_reg; // keep track of decisions - unsigned long long d_flag_bit; // mask containing 1 bit which is location of new flag - unsigned long long d_mask; // masks access_code bits (top N bits are set where - // N is the number of bits in the access code) - 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); - - public: - ~gr_correlate_access_code_bb(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - - /*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - */ - bool set_access_code (const std::string &access_code); -}; - -#endif /* INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i deleted file mode 100644 index bec4282f1..000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i +++ /dev/null @@ -1,60 +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,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) - throw(std::out_of_range); - -/*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup block - * - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) - * - * Each output byte contains two valid bits, the data bit, and the - * flag bit. The LSB (bit 0) is the data bit, and is the original - * input data, delayed 64 bits. Bit 1 is the - * 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 -{ - friend gr_correlate_access_code_bb_sptr - gr_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); - - public: - ~gr_correlate_access_code_bb(); - - /*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - */ - bool set_access_code (const std::string &access_code); -}; 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 f3bfd0951..000000000 --- a/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_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; - - default: - throw std::invalid_argument("order must be 2 or 4"); - break; - } -} - - -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.h b/gnuradio-core/src/lib/general/gr_costas_loop_cc.h deleted file mode 100644 index 3b4aab86c..000000000 --- a/gnuradio-core/src/lib/general/gr_costas_loop_cc.h +++ /dev/null @@ -1,139 +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. - */ - - -#ifndef INCLUDED_GR_COSTAS_LOOP_CC_H -#define INCLUDED_GR_COSTAS_LOOP_CC_H - -#include <gr_sync_block.h> -#include <stdexcept> -#include <fstream> - - -/*! \brief A Costas loop carrier recovery module. - * \ingroup sync_blk - * - * The Costas loop locks to the center frequency of a signal and - * downconverts it to baseband. The second (order=2) order loop is - * used for BPSK where the real part of the output signal is the - * baseband BPSK signal and the imaginary part is the error - * signal. When order=4, it can be used for quadrature modulations - * where both I and Q (real and imaginary) are outputted. - * - * More details can be found online: - * - * J. Feigin, "Practical Costas loop design: Designing a simple and inexpensive - * BPSK Costas loop carrier recovery circuit," RF signal processing, pp. 20-36, - * 2002. - * - * http://rfdesign.com/images/archive/0102Feigin20.pdf - * - * \param alpha the loop gain used for phase adjustment - * \param beta the loop gain for frequency adjustments - * \param max_freq the maximum frequency deviation (radians/sample) the loop can handle - * \param min_freq the minimum frequency deviation (radians/sample) the loop can handle - * \param order the loop order, either 2 or 4 - */ -class gr_costas_loop_cc; -typedef boost::shared_ptr<gr_costas_loop_cc> gr_costas_loop_cc_sptr; - - -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); - - -/*! - * \brief Carrier tracking PLL for QPSK - * \ingroup sync_blk - * input: complex; output: complex - * <br>The Costas loop can have two output streams: - * stream 1 is the baseband I and Q; - * stream 2 is the normalized frequency of the loop - * - * \p order must be 2 or 4. - */ -class gr_costas_loop_cc : public gr_sync_block -{ - friend 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); - - float d_alpha, d_beta, d_max_freq, d_min_freq, d_phase, d_freq; - int d_order; - - gr_costas_loop_cc (float alpha, float beta, - float max_freq, float min_freq, - int order - ) throw (std::invalid_argument); - - /*! \brief the phase detector circuit for fourth-order loops - * \param sample complex sample - * \return the phase error - */ - float phase_detector_4(gr_complex sample) const; // for QPSK - - /*! \brief the phase detector circuit for second-order loops - * \param sample a complex sample - * \return the phase error - */ - float phase_detector_2(gr_complex sample) const; // for BPSK - - - float (gr_costas_loop_cc::*d_phase_detector)(gr_complex sample) const; - -public: - - /*! \brief set the first order gain - * \param alpha - */ - void set_alpha(float alpha); - - /*! \brief get the first order gain - * - */ - float alpha() const { return d_alpha; } - - /*! \brief set the second order gain - * \param beta - */ - void set_beta(float beta); - - /*! \brief get the second order gain - * - */ - float beta() const { return d_beta; } - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - /*! \brief returns the current NCO frequency in radians/sample - * - */ - float freq() const { return d_freq; } -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_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..cae6fe313 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.h @@ -0,0 +1,80 @@ +/* -*- 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 <vector> + +class 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_crc32.i b/gnuradio-core/src/lib/general/gr_cpm.i index 7dca5c6a1..f01aba34e 100644 --- a/gnuradio-core/src/lib/general/gr_crc32.i +++ b/gnuradio-core/src/lib/general/gr_cpm.i @@ -1,6 +1,6 @@ -/* -*- c++ -*- */ +/* -*- C++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,8 +20,21 @@ * Boston, MA 02110-1301, USA. */ -%rename(update_crc32) gr_update_crc32; -%rename(crc32) gr_crc32; +%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); +}; -unsigned int gr_update_crc32(unsigned int crc, const std::string buf); -unsigned int gr_crc32(const std::string buf); diff --git a/gnuradio-core/src/lib/general/gr_crc32.cc b/gnuradio-core/src/lib/general/gr_crc32.cc deleted file mode 100644 index d4e843528..000000000 --- a/gnuradio-core/src/lib/general/gr_crc32.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * See also ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-V42] for a formal specification. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <gr_crc32.h> - - -// Automatically generated CRC function -// polynomial: 0x104C11DB7 -unsigned int -gr_update_crc32(unsigned int crc, const unsigned char *data, size_t len) -{ - static const unsigned int table[256] = { - 0x00000000U,0x04C11DB7U,0x09823B6EU,0x0D4326D9U, - 0x130476DCU,0x17C56B6BU,0x1A864DB2U,0x1E475005U, - 0x2608EDB8U,0x22C9F00FU,0x2F8AD6D6U,0x2B4BCB61U, - 0x350C9B64U,0x31CD86D3U,0x3C8EA00AU,0x384FBDBDU, - 0x4C11DB70U,0x48D0C6C7U,0x4593E01EU,0x4152FDA9U, - 0x5F15ADACU,0x5BD4B01BU,0x569796C2U,0x52568B75U, - 0x6A1936C8U,0x6ED82B7FU,0x639B0DA6U,0x675A1011U, - 0x791D4014U,0x7DDC5DA3U,0x709F7B7AU,0x745E66CDU, - 0x9823B6E0U,0x9CE2AB57U,0x91A18D8EU,0x95609039U, - 0x8B27C03CU,0x8FE6DD8BU,0x82A5FB52U,0x8664E6E5U, - 0xBE2B5B58U,0xBAEA46EFU,0xB7A96036U,0xB3687D81U, - 0xAD2F2D84U,0xA9EE3033U,0xA4AD16EAU,0xA06C0B5DU, - 0xD4326D90U,0xD0F37027U,0xDDB056FEU,0xD9714B49U, - 0xC7361B4CU,0xC3F706FBU,0xCEB42022U,0xCA753D95U, - 0xF23A8028U,0xF6FB9D9FU,0xFBB8BB46U,0xFF79A6F1U, - 0xE13EF6F4U,0xE5FFEB43U,0xE8BCCD9AU,0xEC7DD02DU, - 0x34867077U,0x30476DC0U,0x3D044B19U,0x39C556AEU, - 0x278206ABU,0x23431B1CU,0x2E003DC5U,0x2AC12072U, - 0x128E9DCFU,0x164F8078U,0x1B0CA6A1U,0x1FCDBB16U, - 0x018AEB13U,0x054BF6A4U,0x0808D07DU,0x0CC9CDCAU, - 0x7897AB07U,0x7C56B6B0U,0x71159069U,0x75D48DDEU, - 0x6B93DDDBU,0x6F52C06CU,0x6211E6B5U,0x66D0FB02U, - 0x5E9F46BFU,0x5A5E5B08U,0x571D7DD1U,0x53DC6066U, - 0x4D9B3063U,0x495A2DD4U,0x44190B0DU,0x40D816BAU, - 0xACA5C697U,0xA864DB20U,0xA527FDF9U,0xA1E6E04EU, - 0xBFA1B04BU,0xBB60ADFCU,0xB6238B25U,0xB2E29692U, - 0x8AAD2B2FU,0x8E6C3698U,0x832F1041U,0x87EE0DF6U, - 0x99A95DF3U,0x9D684044U,0x902B669DU,0x94EA7B2AU, - 0xE0B41DE7U,0xE4750050U,0xE9362689U,0xEDF73B3EU, - 0xF3B06B3BU,0xF771768CU,0xFA325055U,0xFEF34DE2U, - 0xC6BCF05FU,0xC27DEDE8U,0xCF3ECB31U,0xCBFFD686U, - 0xD5B88683U,0xD1799B34U,0xDC3ABDEDU,0xD8FBA05AU, - 0x690CE0EEU,0x6DCDFD59U,0x608EDB80U,0x644FC637U, - 0x7A089632U,0x7EC98B85U,0x738AAD5CU,0x774BB0EBU, - 0x4F040D56U,0x4BC510E1U,0x46863638U,0x42472B8FU, - 0x5C007B8AU,0x58C1663DU,0x558240E4U,0x51435D53U, - 0x251D3B9EU,0x21DC2629U,0x2C9F00F0U,0x285E1D47U, - 0x36194D42U,0x32D850F5U,0x3F9B762CU,0x3B5A6B9BU, - 0x0315D626U,0x07D4CB91U,0x0A97ED48U,0x0E56F0FFU, - 0x1011A0FAU,0x14D0BD4DU,0x19939B94U,0x1D528623U, - 0xF12F560EU,0xF5EE4BB9U,0xF8AD6D60U,0xFC6C70D7U, - 0xE22B20D2U,0xE6EA3D65U,0xEBA91BBCU,0xEF68060BU, - 0xD727BBB6U,0xD3E6A601U,0xDEA580D8U,0xDA649D6FU, - 0xC423CD6AU,0xC0E2D0DDU,0xCDA1F604U,0xC960EBB3U, - 0xBD3E8D7EU,0xB9FF90C9U,0xB4BCB610U,0xB07DABA7U, - 0xAE3AFBA2U,0xAAFBE615U,0xA7B8C0CCU,0xA379DD7BU, - 0x9B3660C6U,0x9FF77D71U,0x92B45BA8U,0x9675461FU, - 0x8832161AU,0x8CF30BADU,0x81B02D74U,0x857130C3U, - 0x5D8A9099U,0x594B8D2EU,0x5408ABF7U,0x50C9B640U, - 0x4E8EE645U,0x4A4FFBF2U,0x470CDD2BU,0x43CDC09CU, - 0x7B827D21U,0x7F436096U,0x7200464FU,0x76C15BF8U, - 0x68860BFDU,0x6C47164AU,0x61043093U,0x65C52D24U, - 0x119B4BE9U,0x155A565EU,0x18197087U,0x1CD86D30U, - 0x029F3D35U,0x065E2082U,0x0B1D065BU,0x0FDC1BECU, - 0x3793A651U,0x3352BBE6U,0x3E119D3FU,0x3AD08088U, - 0x2497D08DU,0x2056CD3AU,0x2D15EBE3U,0x29D4F654U, - 0xC5A92679U,0xC1683BCEU,0xCC2B1D17U,0xC8EA00A0U, - 0xD6AD50A5U,0xD26C4D12U,0xDF2F6BCBU,0xDBEE767CU, - 0xE3A1CBC1U,0xE760D676U,0xEA23F0AFU,0xEEE2ED18U, - 0xF0A5BD1DU,0xF464A0AAU,0xF9278673U,0xFDE69BC4U, - 0x89B8FD09U,0x8D79E0BEU,0x803AC667U,0x84FBDBD0U, - 0x9ABC8BD5U,0x9E7D9662U,0x933EB0BBU,0x97FFAD0CU, - 0xAFB010B1U,0xAB710D06U,0xA6322BDFU,0xA2F33668U, - 0xBCB4666DU,0xB8757BDAU,0xB5365D03U,0xB1F740B4U, - }; - - while (len > 0) - { - crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8); - data++; - len--; - } - return crc; -} - -unsigned int -gr_update_crc32(unsigned int crc, const std::string s) -{ - return gr_update_crc32(crc, (const unsigned char *) s.data(), s.size()); -} - -unsigned int -gr_crc32(const unsigned char *buf, size_t len) -{ - return gr_update_crc32(0xffffffff, buf, len) ^ 0xffffffff; -} - -unsigned int -gr_crc32(const std::string s) -{ - return gr_crc32((const unsigned char *) s.data(), s.size()); -} diff --git a/gnuradio-core/src/lib/general/gr_crc32.h b/gnuradio-core/src/lib/general/gr_crc32.h deleted file mode 100644 index 87a8d15f2..000000000 --- a/gnuradio-core/src/lib/general/gr_crc32.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_CRC32_H -#define INCLUDED_GR_CRC32_H - -#include <string> -#include <gr_types.h> - -/*! - * \brief update running CRC-32 - * \ingroup misc - * - * Update a running CRC with the bytes buf[0..len-1] The CRC should be - * initialized to all 1's, and the transmitted value is the 1's - * complement of the final running CRC. The resulting CRC should be - * transmitted in big endian order. - */ -unsigned int -gr_update_crc32(unsigned int crc, const unsigned char *buf, size_t len); - -unsigned int -gr_update_crc32(unsigned int crc, const std::string buf); - -unsigned int -gr_crc32(const unsigned char *buf, size_t len); - -unsigned int -gr_crc32(const std::string buf); - -#endif /* INCLUDED_CRC32_H */ 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 db060793e..000000000 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h +++ /dev/null @@ -1,139 +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_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_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_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_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_frequency_modulator_fc.h b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h index 55f8412ce..385f447b7 100644 --- a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h @@ -48,7 +48,7 @@ class gr_frequency_modulator_fc : public gr_sync_block public: void set_sensitivity(float sens) { d_sensitivity = sens; } - float get_sensitivity() { return d_sensitivity; } + float sensitivity() const { return d_sensitivity; } int work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i index 04d9a41ba..7dfb82f1f 100644 --- a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i @@ -30,5 +30,5 @@ class gr_frequency_modulator_fc : public gr_sync_block gr_frequency_modulator_fc (double sensitivity); public: void set_sensitivity(float sens) { d_sensitivity = sens; } - float get_sensitivity() { return d_sensitivity; } + float sensitivity() const { return d_sensitivity; } }; 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_cc.h b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.h deleted file mode 100644 index 7b3a2c84e..000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_LMS_DFE_CC_H -#define INCLUDED_GR_LMS_DFE_CC_H - -#include <gr_sync_block.h> - -class gr_lms_dfe_cc; -typedef boost::shared_ptr<gr_lms_dfe_cc> gr_lms_dfe_cc_sptr; - -gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - -/*! - * \brief Least-Mean-Square Decision Feedback Equalizer (complex in/out) - * \ingroup eq_blk - */ -class gr_lms_dfe_cc : public gr_sync_block -{ - friend gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - - float d_lambda_ff; - float d_lambda_fb; - std::vector<gr_complex> d_ff_delayline; - std::vector<gr_complex> d_fb_delayline; - std::vector<gr_complex> d_ff_taps; - std::vector<gr_complex> d_fb_taps; - unsigned int d_ff_index; - unsigned int d_fb_index; - - 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); - - public: - - 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_lms_dfe_cc.i b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i deleted file mode 100644 index 9a9f22b6e..000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_cc) - -gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - -class gr_lms_dfe_cc : public gr_sync_block -{ - private: - gr_lms_dfe_cc (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - gr_complex slicer_0deg(gr_complex baud); - gr_complex slicer_45deg(gr_complex baud); - gr_complex conjg(gr_complex val); -}; diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc deleted file mode 100644 index 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_lms_dfe_ff.h b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.h deleted file mode 100644 index dd610c470..000000000 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_LMS_DFE_FF_H -#define INCLUDED_GR_LMS_DFE_FF_H - -#include <gr_sync_block.h> - -class gr_lms_dfe_ff; -typedef boost::shared_ptr<gr_lms_dfe_ff> gr_lms_dfe_ff_sptr; - -gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - -/*! - * \brief Least-Mean-Square Decision Feedback Equalizer (float in/out) - * \ingroup eq_blk - */ -class gr_lms_dfe_ff : public gr_sync_block -{ - friend gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - - float d_lambda_ff; - float d_lambda_fb; - std::vector<float> d_ff_delayline; - std::vector<float> d_fb_delayline; - std::vector<float> d_ff_taps; - std::vector<float> d_fb_taps; - unsigned int d_ff_index; - unsigned int d_fb_index; - - gr_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); - - public: - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc deleted file mode 100644 index bc51c6769..000000000 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc +++ /dev/null @@ -1,322 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006,2007,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_io_signature.h> -#include <gr_prefs.h> -#include <gr_mpsk_receiver_cc.h> -#include <stdexcept> -#include <gr_math.h> -#include <gr_expj.h> -#include <gri_mmse_fir_interpolator_cc.h> - - -#define M_TWOPI (2*M_PI) -#define VERBOSE_MM 0 // Used for debugging symbol timing loop -#define VERBOSE_COSTAS 0 // Used for debugging phase and frequency tracking - -// Public constructor - -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) -{ - return gnuradio::get_initial_sptr(new gr_mpsk_receiver_cc (M, theta, - alpha, beta, - fmin, fmax, - mu, gain_mu, - omega, gain_omega, omega_rel)); -} - -gr_mpsk_receiver_cc::gr_mpsk_receiver_cc (unsigned int M, float theta, - float alpha, float beta, - 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))), - 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), - d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0) -{ - d_interp = new gri_mmse_fir_interpolator_cc(); - d_dl_idx = 0; - - set_omega(omega); - - if (omega <= 0.0) - throw std::out_of_range ("clock rate must be > 0"); - if (gain_mu < 0 || gain_omega < 0) - throw std::out_of_range ("Gains must be non-negative"); - - assert(d_interp->ntaps() <= DLLEN); - - // zero double length delay line. - for (unsigned int i = 0; i < 2 * DLLEN; i++) - d_dl[i] = gr_complex(0.0,0.0); - - // build the constellation vector from M - make_constellation(); - - // 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; - 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; - 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; - break; - } -} - -gr_mpsk_receiver_cc::~gr_mpsk_receiver_cc () -{ - delete d_interp; -} - -void -gr_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++) - ninput_items_required[i] = (int) ceil((noutput_items * d_omega) + d_interp->ntaps()); -} - -// FIXME add these back in an test difference in performance -float -gr_mpsk_receiver_cc::phase_error_detector_qpsk(gr_complex sample) const -{ - float phase_error = 0; - if(fabsf(sample.real()) > fabsf(sample.imag())) { - if(sample.real() > 0) - phase_error = -sample.imag(); - else - phase_error = sample.imag(); - } - else { - if(sample.imag() > 0) - phase_error = sample.real(); - else - phase_error = -sample.real(); - } - - return phase_error; -} - -float -gr_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 -{ - //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 -{ - 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 -{ - unsigned int index; - - //index = gr_branchless_quad_0deg_slicer(sample); - index = gr_quad_0deg_slicer(sample); - return index; -} - -unsigned int -gr_mpsk_receiver_cc::decision_generic(gr_complex sample) const -{ - unsigned int min_m = 0; - float min_s = 65535; - - // Develop all possible constellation points and find the one that minimizes - // the Euclidean distance (error) with the sample - for(unsigned int m=0; m < d_M; m++) { - gr_complex diff = norm(d_constellation[m] - sample); - - if(fabs(diff.real()) < min_s) { - min_s = fabs(diff.real()); - min_m = m; - } - } - // Return the index of the constellation point that minimizes the error - return min_m; -} - - -void -gr_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)); - } -} - -void -gr_mpsk_receiver_cc::mm_sampler(const gr_complex symbol) -{ - gr_complex sample, nco; - - d_mu--; // skip a number of symbols between sampling - d_phase += d_freq; // increment the phase based on the frequency of the rotation - - // Keep phase clamped and not walk to infinity - while(d_phase > M_TWOPI) - d_phase -= M_TWOPI; - while(d_phase < -M_TWOPI) - d_phase += M_TWOPI; - - nco = gr_expj(d_phase+d_theta); // get the NCO value for derotating the current sample - sample = nco*symbol; // get the downconverted symbol - - // Fill up the delay line for the interpolator - d_dl[d_dl_idx] = sample; - d_dl[(d_dl_idx + DLLEN)] = sample; // put this in the second half of the buffer for overflows - d_dl_idx = (d_dl_idx+1) % DLLEN; // Keep the delay line index in bounds -} - -void -gr_mpsk_receiver_cc::mm_error_tracking(gr_complex sample) -{ - gr_complex u, x, y; - float mm_error = 0; - - // Make sample timing corrections - - // set the delayed samples - d_p_2T = d_p_1T; - d_p_1T = d_p_0T; - d_p_0T = sample; - d_c_2T = d_c_1T; - d_c_1T = d_c_0T; - - d_current_const_point = (*this.*d_decision)(d_p_0T); // make a decision on the sample value - d_c_0T = d_constellation[d_current_const_point]; - - x = (d_c_0T - d_c_2T) * conj(d_p_1T); - y = (d_p_0T - d_p_2T) * conj(d_c_1T); - u = y - x; - mm_error = u.real(); // the error signal is in the real part - mm_error = gr_branchless_clip(mm_error, 1.0); // limit mm_val - - d_omega = d_omega + d_gain_omega * mm_error; // update omega based on loop error - d_omega = d_omega_mid + gr_branchless_clip(d_omega-d_omega_mid, d_omega_rel); // make sure we don't walk away - - d_mu += d_omega + d_gain_mu * mm_error; // update mu based on loop error - -#if VERBOSE_MM - printf("mm: mu: %f omega: %f mm_error: %f sample: %f+j%f constellation: %f+j%f\n", - d_mu, d_omega, mm_error, sample.real(), sample.imag(), - d_constellation[d_current_const_point].real(), d_constellation[d_current_const_point].imag()); -#endif -} - - -void -gr_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); - -#if VERBOSE_COSTAS - printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n", - phase_error, d_phase, d_freq, sample.real(), sample.imag(), - d_constellation[d_current_const_point].real(), d_constellation[d_current_const_point].imag()); -#endif -} - -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) -{ - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - - int i=0, o=0; - - while((o < noutput_items) && (i < ninput_items[0])) { - while((d_mu > 1) && (i < ninput_items[0])) { - mm_sampler(in[i]); // puts symbols into a buffer and adjusts d_mu - i++; - } - - if(i < ninput_items[0]) { - gr_complex interp_sample = d_interp->interpolate(&d_dl[d_dl_idx], d_mu); - - mm_error_tracking(interp_sample); // corrects M&M sample time - phase_error_tracking(interp_sample); // corrects phase and frequency offsets - - out[o++] = interp_sample; - } - } - - #if 0 - printf("ninput_items: %d noutput_items: %d consuming: %d returning: %d\n", - ninput_items[0], noutput_items, i, o); - #endif - - consume_each(i); - return o; -} diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h deleted file mode 100644 index f17b68aa0..000000000 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.h +++ /dev/null @@ -1,316 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_MPSK_RECEIVER_CC_H -#define INCLUDED_GR_MPSK_RECEIVER_CC_H - -#include <gruel/attributes.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; - -// public constructor -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); - -/*! - * \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. - * - * 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: - * - * 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. - * - */ - -class gr_mpsk_receiver_cc : public gr_block -{ - public: - ~gr_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, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - - // Member functions related to the symbol tracking portion of the receiver - //! (M&M) Returns current value of mu - float mu() const { return d_mu;} - - //! (M&M) Returns current value of omega - float omega() const { return d_omega;} - - //! (M&M) Returns mu gain factor - float gain_mu() const { return d_gain_mu;} - - //! (M&M) Returns omega gain factor - float gain_omega() const { return d_gain_omega;} - - //! (M&M) Sets value of mu - void set_mu (float mu) { d_mu = mu; } - - //! (M&M) Sets value of omega and its min and max values - void set_omega (float omega) { - d_omega = omega; - d_min_omega = omega*(1.0 - d_omega_rel); - d_max_omega = omega*(1.0 + d_omega_rel); - d_omega_mid = 0.5*(d_min_omega+d_max_omega); - } - - //! (M&M) Sets value for mu gain factor - void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } - - //! (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 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] - * \param gain_mu gain parameter of the M&M error signal to adjust mu (~0.05) - * \param omega initial value for the number of symbols between samples (~number of samples/symbol) - * \param gain_omega gain parameter to adjust omega based on the error (~omega^2/4) - * \param omega_rel sets the maximum (omega*(1+omega_rel)) and minimum (omega*(1+omega_rel)) omega (~0.005) - * - * 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); - - void make_constellation(); - void mm_sampler(const gr_complex symbol); - void mm_error_tracking(gr_complex sample); - 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 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. - * - * \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 - * - * \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. - * - * \returns the index to d_constellation that minimizes the error/ - */ - unsigned int decision_generic(gr_complex sample) const; - - - /*! - * \brief Decision maker for BPSK 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 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. - * - * \returns the index to d_constellation that minimizes the error/ - */ - unsigned int decision_qpsk(gr_complex sample) const; - - 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. - * - * \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 - - - std::vector<gr_complex> d_constellation; - unsigned int d_current_const_point; - - // Members related to symbol timing - float d_mu, d_gain_mu; - float d_omega, d_gain_omega, d_omega_rel, d_max_omega, d_min_omega, d_omega_mid; - 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; - - - //! get interpolated value - gri_mmse_fir_interpolator_cc *d_interp; - - //! delay line length. - static const unsigned int DLLEN = 8; - - //! delay line plus some length for overflow protection - __GR_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN]; - - //! index to delay line - unsigned int d_dl_idx; - - friend 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); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i deleted file mode 100644 index 88cb43e04..000000000 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.i +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 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,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 -{ - 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); -public: - float mu() const { return d_mu;} - float omega() const { return d_omega;} - float gain_mu() const { return d_gain_mu;} - float gain_omega() const { return d_gain_omega;} - void set_mu (float mu) { d_mu = mu; } - void set_omega (float omega) { - d_omega = omega; - d_min_omega = omega*(1.0 - d_omega_rel); - d_max_omega = omega*(1.0 + d_omega_rel); - } - 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/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc new file mode 100644 index 000000000..40574b4e9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc @@ -0,0 +1,374 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,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_ofdm_frame_sink2.h> +#include <gr_io_signature.h> +#include <gr_expj.h> +#include <gr_math.h> +#include <math.h> +#include <cstdio> +#include <stdexcept> +#include <iostream> +#include <string.h> +#include <gr_constellation.h> + +#define VERBOSE 0 + +inline void +gr_ofdm_frame_sink2::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; + +} + +inline void +gr_ofdm_frame_sink2::enter_have_sync() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_sync\n"); + + d_state = STATE_HAVE_SYNC; + + // clear state of demapper + d_byte_offset = 0; + d_partial_byte = 0; + + d_header = 0; + d_headerbytelen_cnt = 0; + + // Resetting PLL + d_freq = 0.0; + d_phase = 0.0; + fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0)); +} + +inline void +gr_ofdm_frame_sink2::enter_have_header() +{ + d_state = STATE_HAVE_HEADER; + + // header consists of two 16-bit shorts in network byte order + // payload length is lower 12 bits + // whitener offset is upper 4 bits + d_packetlen = (d_header >> 16) & 0x0fff; + d_packet_whitener_offset = (d_header >> 28) & 0x000f; + d_packetlen_cnt = 0; + + if (VERBOSE) + fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", + d_packetlen, d_packet_whitener_offset); +} + + +unsigned int gr_ofdm_frame_sink2::demapper(const gr_complex *in, + unsigned char *out) +{ + unsigned int i=0, bytes_produced=0; + gr_complex carrier; + + carrier=gr_expj(d_phase); + + gr_complex accum_error = 0.0; + //while(i < d_occupied_carriers) { + while(i < d_subcarrier_map.size()) { + if(d_nresid > 0) { + d_partial_byte |= d_resid; + d_byte_offset += d_nresid; + d_nresid = 0; + d_resid = 0; + } + + //while((d_byte_offset < 8) && (i < d_occupied_carriers)) { + while((d_byte_offset < 8) && (i < d_subcarrier_map.size())) { + //gr_complex sigrot = in[i]*carrier*d_dfe[i]; + gr_complex sigrot = in[d_subcarrier_map[i]]*carrier*d_dfe[i]; + + if(d_derotated_output != NULL){ + d_derotated_output[i] = sigrot; + } + + unsigned char bits = d_constell->decision_maker(&sigrot); + + gr_complex closest_sym = d_constell->points()[bits]; + + accum_error += sigrot * conj(closest_sym); + + // FIX THE FOLLOWING STATEMENT + if (norm(sigrot)> 0.001) d_dfe[i] += d_eq_gain*(closest_sym/sigrot-d_dfe[i]); + + i++; + + if((8 - d_byte_offset) >= d_nbits) { + d_partial_byte |= bits << (d_byte_offset); + d_byte_offset += d_nbits; + } + else { + d_nresid = d_nbits-(8-d_byte_offset); + int mask = ((1<<(8-d_byte_offset))-1); + d_partial_byte |= (bits & mask) << d_byte_offset; + d_resid = bits >> (8-d_byte_offset); + d_byte_offset += (d_nbits - d_nresid); + } + //printf("demod symbol: %.4f + j%.4f bits: %x partial_byte: %x byte_offset: %d resid: %x nresid: %d\n", + // in[i-1].real(), in[i-1].imag(), bits, d_partial_byte, d_byte_offset, d_resid, d_nresid); + } + + if(d_byte_offset == 8) { + //printf("demod byte: %x \n\n", d_partial_byte); + out[bytes_produced++] = d_partial_byte; + d_byte_offset = 0; + d_partial_byte = 0; + } + } + //std::cerr << "accum_error " << accum_error << std::endl; + + float angle = arg(accum_error); + + d_freq = d_freq - d_freq_gain*angle; + d_phase = d_phase + d_freq - d_phase_gain*angle; + if (d_phase >= 2*M_PI) d_phase -= 2*M_PI; + if (d_phase <0) d_phase += 2*M_PI; + + //if(VERBOSE) + // std::cerr << angle << "\t" << d_freq << "\t" << d_phase << "\t" << std::endl; + + return bytes_produced; +} + + +gr_ofdm_frame_sink2_sptr +gr_make_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_carriers, + float phase_gain, float freq_gain) +{ + return gnuradio::get_initial_sptr(new gr_ofdm_frame_sink2(constell, + target_queue, occupied_carriers, + phase_gain, freq_gain)); +} + + +gr_ofdm_frame_sink2::gr_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_carriers, + float phase_gain, float freq_gain) + : gr_sync_block ("ofdm_frame_sink2", + gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)), + gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers)), + d_constell(constell), + d_target_queue(target_queue), d_occupied_carriers(occupied_carriers), + d_byte_offset(0), d_partial_byte(0), + d_resid(0), d_nresid(0),d_phase(0),d_freq(0),d_phase_gain(phase_gain),d_freq_gain(freq_gain), + d_eq_gain(0.05) +{ + if (d_constell->dimensionality() != 1) + throw std::runtime_error ("This receiver only works with constellations of dimension 1."); + + std::string carriers = "FE7F"; + + // A bit hacky to fill out carriers to occupied_carriers length + int diff = (d_occupied_carriers - 4*carriers.length()); + while(diff > 7) { + carriers.insert(0, "f"); + carriers.insert(carriers.length(), "f"); + diff -= 8; + } + + // if there's extras left to be processed + // divide remaining to put on either side of current map + // all of this is done to stick with the concept of a carrier map string that + // can be later passed by the user, even though it'd be cleaner to just do this + // on the carrier map itself + int diff_left=0; + int diff_right=0; + + // dictionary to convert from integers to ascii hex representation + char abc[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + if(diff > 0) { + char c[2] = {0,0}; + + diff_left = (int)ceil((float)diff/2.0f); // number of carriers to put on the left side + c[0] = abc[(1 << diff_left) - 1]; // convert to bits and move to ASCI integer + carriers.insert(0, c); + + diff_right = diff - diff_left; // number of carriers to put on the right side + c[0] = abc[0xF^((1 << diff_right) - 1)]; // convert to bits and move to ASCI integer + carriers.insert(carriers.length(), c); + } + + // It seemed like such a good idea at the time... + // because we are only dealing with the occupied_carriers + // at this point, the diff_left in the following compensates + // for any offset from the 0th carrier introduced + unsigned int i,j,k; + for(i = 0; i < (d_occupied_carriers/4)+diff_left; i++) { + char c = carriers[i]; + for(j = 0; j < 4; j++) { + k = (strtol(&c, NULL, 16) >> (3-j)) & 0x1; + if(k) { + d_subcarrier_map.push_back(4*i + j - diff_left); + } + } + } + + // make sure we stay in the limit currently imposed by the occupied_carriers + if(d_subcarrier_map.size() > d_occupied_carriers) { + throw std::invalid_argument("gr_ofdm_mapper_bcv: subcarriers allocated exceeds size of occupied carriers"); + } + + d_bytes_out = new unsigned char[d_occupied_carriers]; + d_dfe.resize(occupied_carriers); + fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0)); + + d_nbits = d_constell->bits_per_symbol(); + + enter_search(); +} + +gr_ofdm_frame_sink2::~gr_ofdm_frame_sink2 () +{ + delete [] d_bytes_out; +} + + +int +gr_ofdm_frame_sink2::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]; + const char *sig = (const char *) input_items[1]; + unsigned int j = 0; + unsigned int bytes=0; + + // If the output is connected, send it the derotated symbols + if(output_items.size() >= 1) + d_derotated_output = (gr_complex *)output_items[0]; + else + d_derotated_output = NULL; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"); + + switch(d_state) { + + case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt + if (VERBOSE) + fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items); + + if (sig[0]) { // Found it, set up for header decode + enter_have_sync(); + } + break; + + case STATE_HAVE_SYNC: + // only demod after getting the preamble signal; otherwise, the + // equalizer taps will screw with the PLL performance + bytes = demapper(&in[0], d_bytes_out); + + if (VERBOSE) { + if(sig[0]) + printf("ERROR -- Found SYNC in HAVE_SYNC\n"); + fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", + d_headerbytelen_cnt, d_header); + } + + j = 0; + while(j < bytes) { + d_header = (d_header << 8) | (d_bytes_out[j] & 0xFF); + j++; + + if (++d_headerbytelen_cnt == HEADERBYTELEN) { + + if (VERBOSE) + fprintf(stderr, "got header: 0x%08x\n", d_header); + + // we have a full header, check to see if it has been received properly + if (header_ok()){ + enter_have_header(); + + if (VERBOSE) + printf("\nPacket Length: %d\n", d_packetlen); + + while((j < bytes) && (d_packetlen_cnt < d_packetlen)) { + d_packet[d_packetlen_cnt++] = d_bytes_out[j++]; + } + + if(d_packetlen_cnt == d_packetlen) { + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + } + } + else { + enter_search(); // bad header + } + } + } + break; + + case STATE_HAVE_HEADER: + bytes = demapper(&in[0], d_bytes_out); + + if (VERBOSE) { + if(sig[0]) + printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen); + fprintf(stderr,"Packet Build\n"); + } + + j = 0; + while(j < bytes) { + d_packet[d_packetlen_cnt++] = d_bytes_out[j++]; + + if (d_packetlen_cnt == d_packetlen){ // packet is filled + // build a message + // NOTE: passing header field as arg1 is not scalable + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + break; + } + } + break; + + default: + assert(0); + + } // switch + + return 1; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h new file mode 100644 index 000000000..de8c6a37e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +#ifndef INCLUDED_GR_OFDM_FRAME_SINK2_H +#define INCLUDED_GR_OFDM_FRAME_SINK2_H + +#include <gr_sync_block.h> +#include <gr_msg_queue.h> +#include <gr_constellation.h> + +class gr_ofdm_frame_sink2; +typedef boost::shared_ptr<gr_ofdm_frame_sink2> gr_ofdm_frame_sink2_sptr; + +gr_ofdm_frame_sink2_sptr +gr_make_ofdm_frame_sink2 (gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain=0.25, float freq_gain=0.25*0.25/4.0); + +/*! + * \brief Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs + * them into packets, and sends to to a message queue sink. + * \ingroup sink_blk + * \ingroup ofdm_blk + * + * NOTE: The mod input parameter simply chooses a pre-defined demapper/slicer. Eventually, + * we want to be able to pass in a reference to an object to do the demapping and slicing + * for a given modulation type. + */ +class gr_ofdm_frame_sink2 : public gr_sync_block +{ + friend gr_ofdm_frame_sink2_sptr + gr_make_ofdm_frame_sink2 (gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain, float freq_gain); + + private: + enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; + + static const int MAX_PKT_LEN = 4096; + static const int HEADERBYTELEN = 4; + + gr_msg_queue_sptr d_target_queue; // where to send the packet when received + state_t d_state; + unsigned int d_header; // header bits + int d_headerbytelen_cnt; // how many so far + + unsigned char *d_bytes_out; // hold the current bytes produced by the demapper + + unsigned int d_occupied_carriers; + unsigned int d_byte_offset; + unsigned int d_partial_byte; + + unsigned char d_packet[MAX_PKT_LEN]; // assembled payload + int d_packetlen; // length of packet + int d_packet_whitener_offset; // offset into whitener string to use + int d_packetlen_cnt; // how many so far + + gr_complex * d_derotated_output; // Pointer to output stream to send deroated symbols out + + gr_constellation_sptr d_constell; + std::vector<gr_complex> d_dfe; + unsigned int d_nbits; + + unsigned char d_resid; + unsigned int d_nresid; + float d_phase; + float d_freq; + float d_phase_gain; + float d_freq_gain; + float d_eq_gain; + + std::vector<int> d_subcarrier_map; + + protected: + gr_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain, float freq_gain); + + void enter_search(); + void enter_have_sync(); + void enter_have_header(); + + bool header_ok() + { + // confirm that two copies of header info are identical + return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; + } + + unsigned char slicer(const gr_complex x); + unsigned int demapper(const gr_complex *in, + unsigned char *out); + + public: + ~gr_ofdm_frame_sink2(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_OFDM_FRAME_SINK2_H */ diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i index 488cab370..8fa320089 100644 --- a/gnuradio-core/src/lib/general/gr_costas_loop_cc.i +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2006 Free Software Foundation, Inc. + * Copyright 2007,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,25 +20,20 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,costas_loop_cc); +GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_sink2); -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); +gr_ofdm_frame_sink2_sptr +gr_make_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain=0.25, float freq_gain=0.25*0.25/4); - -class gr_costas_loop_cc : public gr_sync_block +class gr_ofdm_frame_sink2 : public gr_sync_block { - private: - gr_costas_loop_cc (float alpha, float beta, - float max_freq, float min_freq, int order); + protected: + gr_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain, float freq_gain); public: - void set_alpha(float alpha); - float alpha(); - void set_beta(float beta); - float beta(); - float freq(); + ~gr_ofdm_frame_sink2(); }; 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 195f06016..bcdf543a4 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 * @@ -24,12 +24,14 @@ #define INCLUDED_GR_PLL_CARRIERTRACKING_CC_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_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); +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. @@ -41,19 +43,20 @@ gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, floa * 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_pll_carriertracking_cc : public gr_sync_block +class gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop { - friend gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); + friend 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 0581c8724..0da9fc5c7 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 * @@ -24,12 +24,14 @@ #define INCLUDED_GR_PLL_FREQDET_CF_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_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); /*! * \brief Implements a PLL which locks to the input frequency and outputs * an estimate of that frequency. Useful for FM Demod. @@ -40,24 +42,24 @@ gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, * 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_pll_freqdet_cf : public gr_sync_block +class gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop { - friend gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, - float max_freq, float min_freq); + friend 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 3263c957f..d3e45882b 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,18 +20,17 @@ * Boston, MA 02110-1301, USA. */ - - #ifndef INCLUDED_GR_PLL_REFOUT_CC_H #define INCLUDED_GR_PLL_REFOUT_CC_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_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); /*! * \brief Implements a PLL which locks to the input frequency and outputs a carrier * \ingroup sync_blk @@ -43,24 +42,23 @@ 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_pll_refout_cc : public gr_sync_block +class gr_pll_refout_cc : public gr_sync_block, public gri_control_loop { - friend gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, - float max_freq, float min_freq); + friend 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..affdeefc9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.cc @@ -0,0 +1,183 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gri_control_loop.h> +#include <gr_math.h> +#include <stdexcept> + +#define M_TWOPI (2.0f*M_PI) + +gri_control_loop::gri_control_loop(float loop_bw, + float max_freq, float min_freq) + : d_phase(0), d_freq(0), d_max_freq(max_freq), d_min_freq(min_freq) +{ + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); +} + +gri_control_loop::~gri_control_loop() +{ +} + +void +gri_control_loop::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + +void +gri_control_loop::advance_loop(float error) +{ + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_freq + d_alpha * error; +} + + +void +gri_control_loop::phase_wrap() +{ + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + +void +gri_control_loop::frequency_limit() +{ + if (d_freq > d_max_freq) + d_freq = d_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..a85625bbd --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.h @@ -0,0 +1,201 @@ +/* -*- 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 + +class 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_ff.i b/gnuradio-core/src/lib/general/qa_gr_cpm.h index 3ca488b52..741cb2860 100644 --- a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.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,16 +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_ff) +class qa_gr_cpm : public CppUnit::TestCase { -gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (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_ff : public gr_sync_block -{ private: - gr_lms_dfe_ff (float lambda_ff, float lambda_fb, - unsigned int num_fftaps, unsigned int num_fbtaps); + 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/lib/swig/Makefile.am b/gnuradio-core/src/lib/swig/Makefile.am index f8e7640ae..d304a2123 100644 --- a/gnuradio-core/src/lib/swig/Makefile.am +++ b/gnuradio-core/src/lib/swig/Makefile.am @@ -45,7 +45,7 @@ TOP_SWIG_IFILES = \ swiginclude_HEADERS = \ gnuradio.i \ gr_swig_block_magic.i \ - gr_shared_ptr.i + gr_shared_ptr.i # SWIG headers that get installed in ${prefix}/include/gnuradio/swig/... nobase_swiginclude_HEADERS = \ diff --git a/gnuradio-core/src/lib/swig/Makefile.swig.gen b/gnuradio-core/src/lib/swig/Makefile.swig.gen index 0c3247565..cede68817 100644 --- a/gnuradio-core/src/lib/swig/Makefile.swig.gen +++ b/gnuradio-core/src/lib/swig/Makefile.swig.gen @@ -105,7 +105,7 @@ _gnuradio_core_runtime_la_CXXFLAGS = \ $(gnuradio_core_runtime_la_swig_cxxflags) python/gnuradio_core_runtime.cc: gnuradio_core_runtime.py -gnuradio_core_runtime.py: gnuradio_core_runtime.i +gnuradio_core_runtime.py: gnuradio_core_runtime.i # Include the python dependencies for this file -include python/gnuradio_core_runtime.d @@ -250,7 +250,7 @@ _gnuradio_core_general_la_CXXFLAGS = \ $(gnuradio_core_general_la_swig_cxxflags) python/gnuradio_core_general.cc: gnuradio_core_general.py -gnuradio_core_general.py: gnuradio_core_general.i +gnuradio_core_general.py: gnuradio_core_general.i # Include the python dependencies for this file -include python/gnuradio_core_general.d @@ -395,7 +395,7 @@ _gnuradio_core_gengen_la_CXXFLAGS = \ $(gnuradio_core_gengen_la_swig_cxxflags) python/gnuradio_core_gengen.cc: gnuradio_core_gengen.py -gnuradio_core_gengen.py: gnuradio_core_gengen.i +gnuradio_core_gengen.py: gnuradio_core_gengen.i # Include the python dependencies for this file -include python/gnuradio_core_gengen.d @@ -540,7 +540,7 @@ _gnuradio_core_filter_la_CXXFLAGS = \ $(gnuradio_core_filter_la_swig_cxxflags) python/gnuradio_core_filter.cc: gnuradio_core_filter.py -gnuradio_core_filter.py: gnuradio_core_filter.i +gnuradio_core_filter.py: gnuradio_core_filter.i # Include the python dependencies for this file -include python/gnuradio_core_filter.d @@ -685,7 +685,7 @@ _gnuradio_core_io_la_CXXFLAGS = \ $(gnuradio_core_io_la_swig_cxxflags) python/gnuradio_core_io.cc: gnuradio_core_io.py -gnuradio_core_io.py: gnuradio_core_io.i +gnuradio_core_io.py: gnuradio_core_io.i # Include the python dependencies for this file -include python/gnuradio_core_io.d @@ -830,7 +830,7 @@ _gnuradio_core_hier_la_CXXFLAGS = \ $(gnuradio_core_hier_la_swig_cxxflags) python/gnuradio_core_hier.cc: gnuradio_core_hier.py -gnuradio_core_hier.py: gnuradio_core_hier.i +gnuradio_core_hier.py: gnuradio_core_hier.i # Include the python dependencies for this file -include python/gnuradio_core_hier.d |