From 8ab7688ba545c153bcdebe6e273570df569b133c Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 30 Aug 2009 20:32:23 -0400 Subject: Adding clock sync algorithm using PFB. This works, but needs a bit more work. --- gnuradio-core/src/lib/filter/Makefile.am | 7 +- gnuradio-core/src/lib/filter/filter.i | 2 + .../src/lib/filter/gr_pfb_clock_sync_ccf.cc | 259 +++++++++++++++++++++ .../src/lib/filter/gr_pfb_clock_sync_ccf.h | 106 +++++++++ .../src/lib/filter/gr_pfb_clock_sync_ccf.i | 49 ++++ 5 files changed, 421 insertions(+), 2 deletions(-) create mode 100644 gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h create mode 100644 gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i (limited to 'gnuradio-core/src') diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 838f69b92..d5afd571b 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -205,7 +205,8 @@ libfilter_la_common_SOURCES = \ gr_pfb_channelizer_ccf.cc \ gr_pfb_decimator_ccf.cc \ gr_pfb_interpolator_ccf.cc \ - gr_pfb_arb_resampler_ccf.cc + gr_pfb_arb_resampler_ccf.cc \ + gr_pfb_clock_sync_ccf.cc libfilter_qa_la_common_SOURCES = \ qa_filter.cc \ @@ -284,7 +285,8 @@ grinclude_HEADERS = \ gr_pfb_channelizer_ccf.h \ gr_pfb_decimator_ccf.h \ gr_pfb_interpolator_ccf.h \ - gr_pfb_arb_resampler_ccf.h + gr_pfb_arb_resampler_ccf.h \ + gr_pfb_clock_sync_ccf.h noinst_HEADERS = \ assembly.h \ @@ -339,6 +341,7 @@ swiginclude_HEADERS = \ gr_pfb_decimator_ccf.i \ gr_pfb_interpolator_ccf.i \ gr_pfb_arb_resampler_ccf.i \ + gr_pfb_clock_sync_ccf.i \ $(GENERATED_I) endif diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i index 16b8005be..91f55c514 100644 --- a/gnuradio-core/src/lib/filter/filter.i +++ b/gnuradio-core/src/lib/filter/filter.i @@ -36,6 +36,7 @@ #include #include #include +#include %} %include "gr_iir_filter_ffd.i" @@ -56,5 +57,6 @@ %include "gr_pfb_decimator_ccf.i" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" +%include "gr_pfb_clock_sync_ccf.i" %include "filter_generated.i" diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc new file mode 100644 index 000000000..0efbc8a51 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc @@ -0,0 +1,259 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include +#include + +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size, + float init_phase) +{ + return gr_pfb_clock_sync_ccf_sptr (new gr_pfb_clock_sync_ccf (sps, gain, taps, + filter_size, + init_phase)); +} + + +gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size, + float init_phase) + : gr_block ("pfb_clock_sync_ccf", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature2 (2, 2, sizeof(gr_complex), sizeof(float))), + d_updated (false), d_sps(sps), d_alpha(gain) +{ + d_nfilters = filter_size; + + // 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 + // assert(init_phase <= 2*M_PI); + float x = init_phase / (2*M_PI); //normalize initial phase + d_acc = x*(d_nfilters-1); + d_last_filter = (int)floor(d_acc); + d_acc = fmodf(d_acc, 1); + d_start_count = 0; + + + d_filters = std::vector(d_nfilters); + d_diff_filters = std::vector(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector vtaps(0, d_nfilters); + for(unsigned int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + } + + // Now, actually set the filters' taps + std::vector dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_clock_sync_ccf::~gr_pfb_clock_sync_ccf () +{ + for(unsigned int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_clock_sync_ccf::set_taps (const std::vector &newtaps, + std::vector< std::vector > &ourtaps, + std::vector &ourfilter) +{ + unsigned int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // 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 tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // 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[i] = std::vector(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + d_updated = true; +} + +void +gr_pfb_clock_sync_ccf::create_diff_taps(const std::vector &newtaps, + std::vector &difftaps) +{ + difftaps.clear(); + difftaps.push_back(0); //newtaps[0]); + for(unsigned int i = 1; i < newtaps.size()-1; i++) { + difftaps.push_back(newtaps[i+1] - newtaps[i-1]); + } + difftaps.push_back(0);//-newtaps[newtaps.size()-1]); +} + +void +gr_pfb_clock_sync_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_nfilters; i++) { + printf("filter[%d]: [%.4e, ", i, d_taps[i][0]); + for(j = 1; j < d_taps_per_filter-1; j++) { + printf("%.4e,", d_taps[i][j]); + } + printf("%.4e]\n", d_taps[i][j]); + } +} + +void +gr_pfb_clock_sync_ccf::print_diff_taps() +{ + unsigned int i, j; + for(i = 0; i < d_nfilters; i++) { + printf("filter[%d]: [%.4e, ", i, d_dtaps[i][0]); + for(j = 1; j < d_taps_per_filter-1; j++) { + printf("%.4e,", d_dtaps[i][j]); + } + printf("%.4e]\n", d_dtaps[i][j]); + } +} + + +std::vector +gr_pfb_clock_sync_ccf::channel_taps(int channel) +{ + std::vector taps; + unsigned int i; + for(i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector +gr_pfb_clock_sync_ccf::diff_channel_taps(int channel) +{ + std::vector taps; + unsigned int i; + for(i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + + +int +gr_pfb_clock_sync_ccf::general_work (int noutput_items, + gr_vector_int &ninput_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]; + float *err = (float *) output_items[1]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter; + + int i = 0, count = d_start_count; + float error = 0; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + out[i] = d_filters[d_last_filter]->filter(&in[count]); + error = (out[i] * d_diff_filters[d_last_filter]->filter(&in[count])).real(); + err[i] = error; + + d_acc += d_alpha*error; + gr_branchless_clip(d_acc, 1); + + int newfilter; + newfilter = (int)((float)d_last_filter + d_acc); + if(newfilter != (int)d_last_filter) + d_acc = 0.5; + + d_last_filter = newfilter % d_nfilters; + if(newfilter >= (int)d_nfilters) { + d_last_filter = newfilter - d_nfilters; + count++; + } + else if(newfilter < 0) { + d_last_filter = d_nfilters + newfilter; + count--; + } + else { + d_last_filter = newfilter; + } + + i++; + count += d_sps; + } + + // Set the start index at the next entrance to the work function + // if we stop because we run out of input items, jump ahead in the + // next call to work. Otherwise, we can start at zero. + if(count > nrequired) { + d_start_count = count - (nrequired); + consume_each(ninput_items[0]-d_taps_per_filter); + } + else { + d_start_count = 0; + consume_each(count); + } + + return i; +} 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 new file mode 100644 index 000000000..1a04e55c7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h @@ -0,0 +1,106 @@ +/* -*- 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_PFB_CLOCK_SYNC_CCF_H +#define INCLUDED_GR_PFB_CLOCK_SYNC_CCF_H + +#include + +class gr_pfb_clock_sync_ccf; +typedef boost::shared_ptr gr_pfb_clock_sync_ccf_sptr; +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size=32, + float init_phase=0); + +class gr_fir_ccf; + +/*! + * \class gr_pfb_clock_sync_ccf + * + * \brief Timing synchronizer using polyphase filterbanks + * + * \ingroup filter_blk + * + */ + +class gr_pfb_clock_sync_ccf : public gr_block +{ + private: + /*! + * Build the polyphase filterbank timing synchronizer. + */ + friend gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size, + float init_phase); + + bool d_updated; + unsigned int d_sps; + float d_alpha; + unsigned int d_nfilters; + std::vector d_filters; + std::vector d_diff_filters; + std::vector< std::vector > d_taps; + std::vector< std::vector > d_dtaps; + float d_acc; + unsigned int d_last_filter; + unsigned int d_start_count; + unsigned int d_taps_per_filter; + + /*! + * Build the polyphase filterbank timing synchronizer. + */ + gr_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size, + float init_phase); + + void create_diff_taps(const std::vector &newtaps, + std::vector &difftaps); + +public: + ~gr_pfb_clock_sync_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + */ + void set_taps (const std::vector &taps, + std::vector< std::vector > &ourtaps, + std::vector &ourfilter); + std::vector channel_taps(int channel); + std::vector diff_channel_taps(int channel); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + void print_diff_taps(); + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i new file mode 100644 index 000000000..729d4a1aa --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pfb_clock_sync_ccf); + +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size=32, + float init_phase=0); + +class gr_pfb_clock_sync_ccf : public gr_block +{ + private: + gr_pfb_clock_sync_ccf (float sps, float gain, + const std::vector &taps, + unsigned int filter_size, + float init_phase); + + public: + ~gr_pfb_clock_sync_ccf (); + + void set_taps (const std::vector &taps, + std::vector< std::vector > &ourtaps, + std::vector &ourfilter); + + std::vector channel_taps(int channel); + std::vector diff_channel_taps(int channel); + void print_taps(); + void print_diff_taps(); +}; -- cgit From 0c68c486ec09da471c27b6f4d658ae0ba8f861b7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 31 Aug 2009 18:18:22 -0700 Subject: Modified log power fft block so ref scale is peak to peak. Tweaked fft sink autoscale routine to come up with better numbers. Modified scope sink ac couple block to use constant tap. The previous tap calculation would cause failure for very small sample rates. --- gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gnuradio-core/src') diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py b/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py index cf8eb1be7..7ef40be40 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py @@ -55,9 +55,9 @@ class _logpwrfft_base(gr.hier_block2): c2mag = gr.complex_to_mag(fft_size) self._avg = gr.single_pole_iir_filter_ff(1.0, fft_size) self._log = gr.nlog10_ff(20, fft_size, - -10*math.log10(fft_size) # Adjust for number of bins + -20*math.log10(fft_size) # Adjust for number of bins -10*math.log10(window_power/fft_size) # Adjust for windowing loss - -20*math.log10(ref_scale/2)) # Adjust for reference scale + -20*math.log10(ref_scale/2)+3.0) # Adjust for reference scale self.connect(self, self._sd, fft, c2mag, self._avg, self._log, self) self._average = average -- cgit From 6fb2acc3c49e3bb7b8845d517c4bff4a8f5b0fa8 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Wed, 2 Sep 2009 10:14:02 -0700 Subject: Removed subversion related configuration info. * Don't call GR_SUBVERSION in configure.ac * Remove --svn* options from gnuradio-config-info --- gnuradio-core/src/lib/general/gr_constants.cc.in | 12 ------------ gnuradio-core/src/lib/general/gr_constants.h | 10 ---------- gnuradio-core/src/lib/general/gr_constants.i | 4 ---- gnuradio-core/src/lib/gnuradio-config-info.cc | 8 -------- 4 files changed, 34 deletions(-) (limited to 'gnuradio-core/src') diff --git a/gnuradio-core/src/lib/general/gr_constants.cc.in b/gnuradio-core/src/lib/general/gr_constants.cc.in index efb0f1c77..71a47eb51 100644 --- a/gnuradio-core/src/lib/general/gr_constants.cc.in +++ b/gnuradio-core/src/lib/general/gr_constants.cc.in @@ -50,18 +50,6 @@ gr_build_date() return "@BUILD_DATE@"; } -const std::string -gr_svn_date() -{ - return "@SVNDATE@"; -} - -const std::string -gr_svn_version() -{ - return "@SVNVERSION@"; -} - const std::string gr_version() { diff --git a/gnuradio-core/src/lib/general/gr_constants.h b/gnuradio-core/src/lib/general/gr_constants.h index e44890be0..449d41c17 100644 --- a/gnuradio-core/src/lib/general/gr_constants.h +++ b/gnuradio-core/src/lib/general/gr_constants.h @@ -44,16 +44,6 @@ const std::string gr_prefsdir(); */ const std::string gr_build_date(); -/*! - * \brief return repository date as set when 'bootstrap' is run - */ -const std::string gr_svn_date(); - -/*! - * \brief return repository version as set when 'bootstrap' is run - */ -const std::string gr_svn_version(); - /*! * \brief return version string defined in configure.ac */ diff --git a/gnuradio-core/src/lib/general/gr_constants.i b/gnuradio-core/src/lib/general/gr_constants.i index 156af4a36..a5aef1492 100644 --- a/gnuradio-core/src/lib/general/gr_constants.i +++ b/gnuradio-core/src/lib/general/gr_constants.i @@ -4,14 +4,10 @@ %rename(sysconfdir) gr_sysconfdir; %rename(prefsdir) gr_prefsdir; %rename(build_date) gr_build_date; -%rename(svn_date) gr_svn_date; -%rename(svn_version) gr_svn_version; %rename(version) gr_version; const std::string gr_prefix(); const std::string gr_sysconfdir(); const std::string gr_prefsdir(); const std::string gr_build_date(); -const std::string gr_svn_date(); -const std::string gr_svn_version(); const std::string gr_version(); diff --git a/gnuradio-core/src/lib/gnuradio-config-info.cc b/gnuradio-core/src/lib/gnuradio-config-info.cc index df78ea2dd..6fa53b877 100644 --- a/gnuradio-core/src/lib/gnuradio-config-info.cc +++ b/gnuradio-core/src/lib/gnuradio-config-info.cc @@ -43,8 +43,6 @@ main(int argc, char **argv) ("prefsdir", "print gnuradio preferences directory") ("builddate", "print gnuradio build date (RFC2822 format)") ("version,v", "print gnuradio version") - ("svnversion", "print SVN repository version (SVN format)") - ("svndate", "print SVN repository date") ; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -70,11 +68,5 @@ main(int argc, char **argv) if (vm.count("version")) std::cout << gr_version() << std::endl; - if (vm.count("svnversion")) - std::cout << gr_svn_version() << std::endl; - - if (vm.count("svndate")) - std::cout << gr_svn_date() << std::endl; - return 0; } -- cgit From 302686ace014d7be82812c218121f00f5b28cdd1 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 3 Sep 2009 22:50:43 -0400 Subject: Fixing a line in the clock recovery algorithm. This works with a bit larger error than there proably should be. --- gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'gnuradio-core/src') 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 0efbc8a51..91cbf74c6 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 @@ -226,7 +226,6 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items, if(newfilter != (int)d_last_filter) d_acc = 0.5; - d_last_filter = newfilter % d_nfilters; if(newfilter >= (int)d_nfilters) { d_last_filter = newfilter - d_nfilters; count++; -- cgit