diff options
author | Tom Rondeau | 2012-05-08 22:43:48 -0400 |
---|---|---|
committer | Tom Rondeau | 2012-05-08 22:43:48 -0400 |
commit | 274bc141208ac8209c6b3342ff5ddc3755b321de (patch) | |
tree | aa9666a189d72fb23524a138034f0ff3d660c8c3 /gr-filter/lib | |
parent | 4f08cb7eb6e3ac4b7315b4b78dbc7d812b6c3dd1 (diff) | |
download | gnuradio-274bc141208ac8209c6b3342ff5ddc3755b321de.tar.gz gnuradio-274bc141208ac8209c6b3342ff5ddc3755b321de.tar.bz2 gnuradio-274bc141208ac8209c6b3342ff5ddc3755b321de.zip |
filter: created polyphase_filterbank parent class to handle some initialization and setting taps of PFB blocks.
Converted pfb_channelizer_ccf over to new parent class. Passes QA.
Diffstat (limited to 'gr-filter/lib')
-rw-r--r-- | gr-filter/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-filter/lib/pfb_channelizer_ccf_impl.cc | 102 | ||||
-rw-r--r-- | gr-filter/lib/pfb_channelizer_ccf_impl.h | 24 | ||||
-rw-r--r-- | gr-filter/lib/polyphase_filterbank.cc | 114 |
4 files changed, 152 insertions, 89 deletions
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt index 5930ec9bb..b7577ad5e 100644 --- a/gr-filter/lib/CMakeLists.txt +++ b/gr-filter/lib/CMakeLists.txt @@ -110,6 +110,7 @@ list(APPEND filter_sources fft_filter.cc firdes.cc pm_remez.cc + polyphase_filterbank.cc ${generated_sources} dc_blocker_cc_impl.cc dc_blocker_ff_impl.cc diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.cc b/gr-filter/lib/pfb_channelizer_ccf_impl.cc index 4006db789..4e06cbc5f 100644 --- a/gr-filter/lib/pfb_channelizer_ccf_impl.cc +++ b/gr-filter/lib/pfb_channelizer_ccf_impl.cc @@ -26,26 +26,26 @@ #include "pfb_channelizer_ccf_impl.h" #include <gr_io_signature.h> -#include <cstdio> namespace gr { namespace filter { - pfb_channelizer_ccf::sptr pfb_channelizer_ccf::make(unsigned int numchans, + pfb_channelizer_ccf::sptr pfb_channelizer_ccf::make(unsigned int nfilts, const std::vector<float> &taps, float oversample_rate) { - return gnuradio::get_initial_sptr(new pfb_channelizer_ccf_impl(numchans, taps, + return gnuradio::get_initial_sptr(new pfb_channelizer_ccf_impl(nfilts, taps, oversample_rate)); } - pfb_channelizer_ccf_impl::pfb_channelizer_ccf_impl(unsigned int numchans, + pfb_channelizer_ccf_impl::pfb_channelizer_ccf_impl(unsigned int nfilts, const std::vector<float> &taps, float oversample_rate) : gr_block("pfb_channelizer_ccf", - gr_make_io_signature(numchans, numchans, sizeof(gr_complex)), - gr_make_io_signature(1, numchans, sizeof(gr_complex))), - d_updated(false), d_numchans(numchans), d_oversample_rate(oversample_rate) + gr_make_io_signature(nfilts, nfilts, sizeof(gr_complex)), + gr_make_io_signature(1, nfilts, sizeof(gr_complex))), + polyphase_filterbank(nfilts, taps), + d_updated(false), d_oversample_rate(oversample_rate) { // The over sampling rate must be rationally related to the number of channels // in that it must be N/i for i in [1,N], which gives an outputsample rate @@ -53,110 +53,62 @@ namespace gr { // This tests the specified input sample rate to see if it conforms to this // requirement within a few significant figures. double intp = 0; - double fltp = modf(numchans / oversample_rate, &intp); + double fltp = modf(nfilts / oversample_rate, &intp); if(fltp != 0.0) throw std::invalid_argument("pfb_channelizer: oversample rate must be N/i for i in [1, N]"); set_relative_rate(1.0/intp); - d_filters = std::vector<kernel::fir_filter_ccf*>(d_numchans); - d_channel_map.resize(d_numchans); - - // Create an FIR filter for each channel and zero out the taps - std::vector<float> vtaps(0, d_numchans); - for(unsigned int i = 0; i < d_numchans; i++) { - d_filters[i] = new kernel::fir_filter_ccf(1, vtaps); + // Default channel map + d_channel_map.resize(d_nfilts); + for(unsigned int i = 0; i < d_nfilts; i++) { d_channel_map[i] = i; } - // Now, actually set the filters' taps - set_taps(taps); - - // Create the FFT to handle the output de-spinning of the channels - d_fft = new fft::fft_complex(d_numchans, false); - // Although the filters change, we use this look up table // to set the index of the FFT input buffer, which equivalently // performs the FFT shift operation on every other turn. - d_rate_ratio = (int)rintf(d_numchans / d_oversample_rate); - d_idxlut = new int[d_numchans]; - for(unsigned int i = 0; i < d_numchans; i++) { - d_idxlut[i] = d_numchans - ((i + d_rate_ratio) % d_numchans) - 1; + d_rate_ratio = (int)rintf(d_nfilts / d_oversample_rate); + d_idxlut = new int[d_nfilts]; + for(unsigned int i = 0; i < d_nfilts; i++) { + d_idxlut[i] = d_nfilts - ((i + d_rate_ratio) % d_nfilts) - 1; } // Calculate the number of filtering rounds to do to evenly // align the input vectors with the output channels d_output_multiple = 1; - while((d_output_multiple * d_rate_ratio) % d_numchans != 0) + while((d_output_multiple * d_rate_ratio) % d_nfilts != 0) d_output_multiple++; set_output_multiple(d_output_multiple); + + set_history (d_taps_per_filter+1); } pfb_channelizer_ccf_impl::~pfb_channelizer_ccf_impl() { delete [] d_idxlut; - delete d_fft; - - for(unsigned int i = 0; i < d_numchans; i++) { - delete d_filters[i]; - } } void - pfb_channelizer_ccf_impl::set_taps (const std::vector<float> &taps) + pfb_channelizer_ccf_impl::set_taps(const std::vector<float> &taps) { gruel::scoped_lock guard(d_mutex); - unsigned int i,j; - - unsigned int ntaps = taps.size(); - d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); - - // Create d_numchan vectors to store each channel's taps - d_taps.resize(d_numchans); - // 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 = taps; - while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { - tmp_taps.push_back(0.0); - } - - // Partition the filter - for(i = 0; i < d_numchans; i++) { - // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out - d_taps[i] = std::vector<float>(d_taps_per_filter, 0); - for(j = 0; j < d_taps_per_filter; j++) { - d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order - } - - // Build a filter for each channel and add it's taps to it - d_filters[i]->set_taps(d_taps[i]); - } - - // Set the history to ensure enough input items for each filter + polyphase_filterbank::set_taps(taps); set_history (d_taps_per_filter+1); - d_updated = true; } void pfb_channelizer_ccf_impl::print_taps() { - unsigned int i, j; - for(i = 0; i < d_numchans; i++) { - printf("filter[%d]: [", i); - for(j = 0; j < d_taps_per_filter; j++) { - printf(" %.4e", d_taps[i][j]); - } - printf("]\n\n"); - } + polyphase_filterbank::print_taps(); } - std::vector< std::vector<float> > + std::vector<std::vector<float> > pfb_channelizer_ccf_impl::taps() const { - return d_taps; + return polyphase_filterbank::taps(); } void @@ -167,7 +119,7 @@ namespace gr { if(map.size() > 0) { unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end()); unsigned int min = (unsigned int)*std::min_element(map.begin(), map.end()); - if((max >= d_numchans) || (min < 0)) { + if((max >= d_nfilts) || (min < 0)) { throw std::invalid_argument("pfb_channelizer_ccf_impl::set_channel_map: map range out of bounds.\n"); } d_channel_map = map; @@ -202,7 +154,7 @@ namespace gr { int toconsume = (int)rintf(noutput_items/d_oversample_rate); while(n <= toconsume) { j = 0; - i = (i + d_rate_ratio) % d_numchans; + i = (i + d_rate_ratio) % d_nfilts; last = i; while(i >= 0) { in = (gr_complex*)input_items[j]; @@ -211,7 +163,7 @@ namespace gr { i--; } - i = d_numchans-1; + i = d_nfilts-1; while(i > last) { in = (gr_complex*)input_items[j]; d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n-1]); @@ -219,7 +171,7 @@ namespace gr { i--; } - n += (i+d_rate_ratio) >= (int)d_numchans; + n += (i+d_rate_ratio) >= (int)d_nfilts; // despin through FFT d_fft->execute(); diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.h b/gr-filter/lib/pfb_channelizer_ccf_impl.h index ee9327663..8cabc4e34 100644 --- a/gr-filter/lib/pfb_channelizer_ccf_impl.h +++ b/gr-filter/lib/pfb_channelizer_ccf_impl.h @@ -24,30 +24,26 @@ #define INCLUDED_FILTER_PFB_CHANNELIZER_CCF_IMPL_H #include <filter/pfb_channelizer_ccf.h> +#include <filter/polyphase_filterbank.h> #include <filter/fir_filter.h> #include <fft/fft.h> namespace gr { namespace filter { - class FILTER_API pfb_channelizer_ccf_impl : public pfb_channelizer_ccf + class FILTER_API pfb_channelizer_ccf_impl : public pfb_channelizer_ccf, kernel::polyphase_filterbank { private: - bool d_updated; - unsigned int d_numchans; - float d_oversample_rate; - std::vector<kernel::fir_filter_ccf*> d_filters; - std::vector< std::vector<float> > d_taps; - unsigned int d_taps_per_filter; - fft::fft_complex *d_fft; - int *d_idxlut; - int d_rate_ratio; - int d_output_multiple; - std::vector<int> d_channel_map; - gruel::mutex d_mutex; // mutex to protect set/work access + bool d_updated; + float d_oversample_rate; + int *d_idxlut; + int d_rate_ratio; + int d_output_multiple; + std::vector<int> d_channel_map; + gruel::mutex d_mutex; // mutex to protect set/work access public: - pfb_channelizer_ccf_impl(unsigned int numchans, + pfb_channelizer_ccf_impl(unsigned int nfilts, const std::vector<float> &taps, float oversample_rate); diff --git a/gr-filter/lib/polyphase_filterbank.cc b/gr-filter/lib/polyphase_filterbank.cc new file mode 100644 index 000000000..9d881d76e --- /dev/null +++ b/gr-filter/lib/polyphase_filterbank.cc @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 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 <filter/polyphase_filterbank.h> +#include <cstdio> + +namespace gr { + namespace filter { + namespace kernel { + + polyphase_filterbank::polyphase_filterbank(unsigned int nfilts, + const std::vector<float> &taps) + : d_nfilts(nfilts) + { + d_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilts); + for(unsigned int i = 0; i < d_nfilts; i++) { + d_filters[i] = new kernel::fir_filter_ccf(1, vtaps); + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the FFT to handle the output de-spinning of the channels + d_fft = new fft::fft_complex(d_nfilts, false); + } + + polyphase_filterbank::~polyphase_filterbank() + { + delete d_fft; + for(unsigned int i = 0; i < d_nfilts; i++) { + delete d_filters[i]; + } + } + + void + polyphase_filterbank::set_taps (const std::vector<float> &taps) + { + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilts); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_nfilts); + + // 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 = taps; + while((float)(tmp_taps.size()) < d_nfilts*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilts; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_nfilts]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + } + + void + polyphase_filterbank::print_taps() + { + unsigned int i, j; + for(i = 0; i < d_nfilts; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } + } + + std::vector< std::vector<float> > + polyphase_filterbank::taps() const + { + return d_taps; + } + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ |