diff options
author | Tom Rondeau | 2012-06-18 15:42:14 -0400 |
---|---|---|
committer | Tom Rondeau | 2012-06-18 15:42:14 -0400 |
commit | 5365daf7ae85c9df88f0b8f3667ece022d93f637 (patch) | |
tree | cf0573714bc346bdacb0916fc140db608bbfe899 /gr-filter | |
parent | 622464a324abc90f2724d3f846f0b1bdb38b97fc (diff) | |
download | gnuradio-5365daf7ae85c9df88f0b8f3667ece022d93f637.tar.gz gnuradio-5365daf7ae85c9df88f0b8f3667ece022d93f637.tar.bz2 gnuradio-5365daf7ae85c9df88f0b8f3667ece022d93f637.zip |
filter: adding PFB interpolator with GRC and QA.
Diffstat (limited to 'gr-filter')
-rw-r--r-- | gr-filter/grc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-filter/grc/filter_block_tree.xml | 1 | ||||
-rw-r--r-- | gr-filter/grc/pfb_decimator.xml | 2 | ||||
-rw-r--r-- | gr-filter/grc/pfb_interpolator.xml | 36 | ||||
-rw-r--r-- | gr-filter/include/filter/CMakeLists.txt | 5 | ||||
-rw-r--r-- | gr-filter/include/filter/pfb_decimator_ccf.h | 1 | ||||
-rw-r--r-- | gr-filter/include/filter/pfb_interpolator_ccf.h | 118 | ||||
-rw-r--r-- | gr-filter/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-filter/lib/pfb_decimator_ccf_impl.cc | 4 | ||||
-rw-r--r-- | gr-filter/lib/pfb_interpolator_ccf_impl.cc | 107 | ||||
-rw-r--r-- | gr-filter/lib/pfb_interpolator_ccf_impl.h | 61 | ||||
-rwxr-xr-x | gr-filter/python/qa_pfb_interpolator.py | 71 | ||||
-rw-r--r-- | gr-filter/swig/filter_swig.i | 3 |
13 files changed, 405 insertions, 6 deletions
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt index a160b00bb..7fc129d8a 100644 --- a/gr-filter/grc/CMakeLists.txt +++ b/gr-filter/grc/CMakeLists.txt @@ -30,6 +30,7 @@ install(FILES interp_fir_filter_xxx.xml pfb_channelizer.xml pfb_decimator.xml + pfb_interpolator.xml single_pole_iir_filter_xx.xml DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "filter_python" diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml index 2a0d02346..0ec9e5dd0 100644 --- a/gr-filter/grc/filter_block_tree.xml +++ b/gr-filter/grc/filter_block_tree.xml @@ -41,6 +41,7 @@ <block>interp_fir_filter_xxx</block> <block>pfb_channelizer_ccf</block> <block>pfb_decimator_ccf</block> + <block>pfb_interpolator_ccf</block> <block>single_pole_iir_filter_xx</block> </cat> </cat> diff --git a/gr-filter/grc/pfb_decimator.xml b/gr-filter/grc/pfb_decimator.xml index dea5bdb43..329d59c3d 100644 --- a/gr-filter/grc/pfb_decimator.xml +++ b/gr-filter/grc/pfb_decimator.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- ################################################### -##Polyphase Channelizer +##Polyphase Decimator ################################################### --> <block> diff --git a/gr-filter/grc/pfb_interpolator.xml b/gr-filter/grc/pfb_interpolator.xml new file mode 100644 index 000000000..600493123 --- /dev/null +++ b/gr-filter/grc/pfb_interpolator.xml @@ -0,0 +1,36 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Polyphase Interpolator +################################################### + --> +<block> + <name>Polyphase Interpolator</name> + <key>pfb_interpolator_ccf</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.pfb.interpolator_ccf( + $interp, + $taps) + </make> + <callback>set_taps($taps)</callback> + <param> + <name>Interpolation</name> + <key>interp</key> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <value>None</value> + <type>real_vector</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt index 77ae78e35..3d8e0c932 100644 --- a/gr-filter/include/filter/CMakeLists.txt +++ b/gr-filter/include/filter/CMakeLists.txt @@ -64,7 +64,7 @@ endmacro(expand_h) ######################################################################## # Invoke macro to generate various sources ####################################################################### -expand_h(fir_filter_XXX fff ccc ccf fcc fff fsf scc) +expand_h(fir_filter_XXX ccc ccf fcc fff fsf scc) expand_h(freq_xlating_fir_filter_XXX ccc ccf fcc fcf scf scc) expand_h(interp_fir_filter_XXX ccc ccf fcc fff fsf scc) @@ -102,9 +102,10 @@ install(FILES iir_filter_ffd.h pfb_channelizer_ccf.h pfb_decimator_ccf.h + pfb_interpolator_ccf.h single_pole_iir_filter_cc.h single_pole_iir_filter_ff.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter - COMPONENT "fft_devel" + COMPONENT "filter_devel" ) diff --git a/gr-filter/include/filter/pfb_decimator_ccf.h b/gr-filter/include/filter/pfb_decimator_ccf.h index a933fbb5b..e0b8dce15 100644 --- a/gr-filter/include/filter/pfb_decimator_ccf.h +++ b/gr-filter/include/filter/pfb_decimator_ccf.h @@ -26,7 +26,6 @@ #include <filter/api.h> #include <gr_sync_block.h> -#include <gruel/thread.h> namespace gr { namespace filter { diff --git a/gr-filter/include/filter/pfb_interpolator_ccf.h b/gr-filter/include/filter/pfb_interpolator_ccf.h new file mode 100644 index 000000000..d32b8b688 --- /dev/null +++ b/gr-filter/include/filter/pfb_interpolator_ccf.h @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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. + */ + + +#ifndef INCLUDED_PFB_INTERPOLATOR_CCF_H +#define INCLUDED_PFB_INTERPOLATOR_CCF_H + +#include <filter/api.h> +#include <gr_sync_interpolator.h> + +namespace gr { + namespace filter { + + /*! + * \class gr_pfb_interpolator_ccf + * + * \brief Polyphase filterbank interpolator with gr_complex input, + * 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 + * input is the integer specifying how much to interpolate by. The + * second input is a vector (Python list) of floating-point taps + * of the prototype filter. + * + * The filter's taps should be based on the interpolation rate + * specified. That is, the bandwidth specified is relative to the + * bandwidth after interpolation. + * + * For example, using the GNU Radio's firdes utility to building + * filters, 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, ATT, and the filter window function (a + * Blackman-harris window in this case). The first input is the + * gain, which is also specified as the interpolation rate so that + * the output levels are the same as the input (this creates an + * overall increase in power). + * + * <B><EM>self._taps = gr.firdes.low_pass_2(interp, interp*fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The PFB interpolator code takes the taps generated above and + * builds a set of filters. The set contains <EM>interp</EM> + * number of filters and each filter contains + * ceil(taps.size()/interp) number of taps. Each tap from the + * filter prototype is sequentially inserted into the next + * filter. When all of the input taps are used, the remaining + * filters in the filterbank are filled out with 0's to make sure + * each filter has the same number of taps. + * + * The theory behind this block can be found in Chapter 7.1 of the + * following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems</EM>," Upper Saddle River, NJ: Prentice Hall, + * Inc. 2004.</EM></B> + */ + + class FILTER_API pfb_interpolator_ccf : virtual public gr_sync_interpolator + { + public: + // gr::filter::pfb_interpolator_ccf::sptr + typedef boost::shared_ptr<pfb_interpolator_ccf> sptr; + + /*! + * Build the polyphase filterbank interpolator. + * \param interp (unsigned integer) Specifies the interpolation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the interpolated sampling rate. + */ + static FILTER_API sptr make(unsigned int interp, + const std::vector<float> &taps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_PFB_INTERPOLATOR_CCF_H */ diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt index 40faa8f0e..d1ddd2a92 100644 --- a/gr-filter/lib/CMakeLists.txt +++ b/gr-filter/lib/CMakeLists.txt @@ -129,6 +129,7 @@ list(APPEND filter_sources iir_filter_ffd_impl.cc pfb_channelizer_ccf_impl.cc pfb_decimator_ccf_impl.cc + pfb_interpolator_ccf_impl.cc single_pole_iir_filter_cc_impl.cc single_pole_iir_filter_ff_impl.cc ) diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc index 139cd9bec..f9a60cb28 100644 --- a/gr-filter/lib/pfb_decimator_ccf_impl.cc +++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc @@ -31,12 +31,12 @@ namespace gr { namespace filter { pfb_decimator_ccf::sptr - pfb_decimator_ccf::make(unsigned int nfilts, + pfb_decimator_ccf::make(unsigned int decim, const std::vector<float> &taps, unsigned int channel) { return gnuradio::get_initial_sptr - (new pfb_decimator_ccf_impl(nfilts, taps, channel)); + (new pfb_decimator_ccf_impl(decim, taps, channel)); } diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.cc b/gr-filter/lib/pfb_interpolator_ccf_impl.cc new file mode 100644 index 000000000..572db728b --- /dev/null +++ b/gr-filter/lib/pfb_interpolator_ccf_impl.cc @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,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 "pfb_interpolator_ccf_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + pfb_interpolator_ccf::sptr + pfb_interpolator_ccf::make(unsigned int interp, + const std::vector<float> &taps) + { + return gnuradio::get_initial_sptr + (new pfb_interpolator_ccf_impl(interp, taps)); + } + + + pfb_interpolator_ccf_impl::pfb_interpolator_ccf_impl(unsigned int interp, + const std::vector<float> &taps) + : gr_sync_interpolator("pfb_interpolator_ccf", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex)), + interp), + polyphase_filterbank(interp, taps), + d_updated (false), d_rate(interp) + { + set_history(d_taps_per_filter+1); + } + + pfb_interpolator_ccf_impl::~pfb_interpolator_ccf_impl() + { + } + + void + pfb_interpolator_ccf_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + + polyphase_filterbank::set_taps(taps); + set_history(d_taps_per_filter+1); + d_updated = true; + } + + void + pfb_interpolator_ccf_impl::print_taps() + { + polyphase_filterbank::print_taps(); + } + + std::vector<std::vector<float> > + pfb_interpolator_ccf_impl::taps() const + { + return polyphase_filterbank::taps(); + } + + int + pfb_interpolator_ccf_impl::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_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = 0; + + while(i < noutput_items) { + for(unsigned int j = 0; j < d_rate; j++) { + out[i] = d_filters[j]->filter(&in[count]); + i++; + } + count++; + } + + return i; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.h b/gr-filter/lib/pfb_interpolator_ccf_impl.h new file mode 100644 index 000000000..7e1fe2ca1 --- /dev/null +++ b/gr-filter/lib/pfb_interpolator_ccf_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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. + */ + + +#ifndef INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H +#define INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H + +#include <filter/pfb_interpolator_ccf.h> +#include <filter/polyphase_filterbank.h> +#include <filter/fir_filter.h> +#include <fft/fft.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + class FILTER_API pfb_interpolator_ccf_impl : public pfb_interpolator_ccf, kernel::polyphase_filterbank + { + private: + bool d_updated; + unsigned int d_rate; + gruel::mutex d_mutex; // mutex to protect set/work access + + public: + pfb_interpolator_ccf_impl(unsigned int interp, + const std::vector<float> &taps); + + ~pfb_interpolator_ccf_impl(); + + void set_taps(const std::vector<float> &taps); + void print_taps(); + std::vector<std::vector<float> > taps() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H */ diff --git a/gr-filter/python/qa_pfb_interpolator.py b/gr-filter/python/qa_pfb_interpolator.py new file mode 100755 index 000000000..f83c57d60 --- /dev/null +++ b/gr-filter/python/qa_pfb_interpolator.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_pfb_interpolator(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + N = 1000 # number of samples to use + M = 5 # Number of channels + fs = 1000 # baseband sampling rate + ifs = M*fs # input samp rate to decimator + + taps = gr.firdes.low_pass_2(M, ifs, fs/2, fs/10, + attenuation_dB=80, + window=gr.firdes.WIN_BLACKMAN_hARRIS) + + freq = 100 + signal = gr.sig_source_c(fs, gr.GR_COS_WAVE, freq, 1) + head = gr.head(gr.sizeof_gr_complex, N) + pfb = filter.pfb_interpolator_ccf(M, taps) + snk = gr.vector_sink_c() + + self.tb.connect(signal, head, pfb) + self.tb.connect(pfb, snk) + + self.tb.run() + + Ntest = 50 + L = len(snk.data()) + t = map(lambda x: float(x)/ifs, xrange(L)) + + # Create known data as complex sinusoids at freq + # of the channel at the interpolated rate. + phase = 0.62833 + expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase), t) + + dst_data = snk.data() + + self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4) + +if __name__ == '__main__': + gr_unittest.run(test_pfb_interpolator, "test_pfb_interpolator.xml") diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i index 0f814f955..cc2e51d96 100644 --- a/gr-filter/swig/filter_swig.i +++ b/gr-filter/swig/filter_swig.i @@ -61,6 +61,7 @@ #include "filter/interp_fir_filter_scc.h" #include "filter/pfb_channelizer_ccf.h" #include "filter/pfb_decimator_ccf.h" +#include "filter/pfb_interpolator_ccf.h" #include "filter/single_pole_iir_filter_cc.h" #include "filter/single_pole_iir_filter_ff.h" %} @@ -98,6 +99,7 @@ %include "filter/interp_fir_filter_scc.h" %include "filter/pfb_channelizer_ccf.h" %include "filter/pfb_decimator_ccf.h" +%include "filter/pfb_interpolator_ccf.h" %include "filter/single_pole_iir_filter_cc.h" %include "filter/single_pole_iir_filter_ff.h" @@ -132,5 +134,6 @@ GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fsf); GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_scc); GR_SWIG_BLOCK_MAGIC2(filter, pfb_channelizer_ccf); GR_SWIG_BLOCK_MAGIC2(filter, pfb_decimator_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_interpolator_ccf); GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_cc); GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_ff); |