summaryrefslogtreecommitdiff
path: root/gr-filter
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2012-06-15 15:58:28 -0400
committerTom Rondeau <trondeau@vt.edu>2012-06-15 16:05:51 -0400
commit76a6a4c668579ff2e17f8fa44ceb0db381b9053f (patch)
tree7327b7ffb742d9cadf25c2303a03a378cd45c8ca /gr-filter
parent05c117f359b831513bbf6c4f43dca9cb181e5920 (diff)
filter: adding single_pole_iir_filter blocks.
QA, docs, and GRC.
Diffstat (limited to 'gr-filter')
-rw-r--r--gr-filter/grc/CMakeLists.txt1
-rw-r--r--gr-filter/grc/filter_block_tree.xml1
-rw-r--r--gr-filter/grc/single_pole_iir_filter_xx.xml51
-rw-r--r--gr-filter/include/filter/CMakeLists.txt3
-rw-r--r--gr-filter/include/filter/single_pole_iir.h200
-rw-r--r--gr-filter/include/filter/single_pole_iir_filter_cc.h78
-rw-r--r--gr-filter/include/filter/single_pole_iir_filter_ff.h78
-rw-r--r--gr-filter/lib/CMakeLists.txt2
-rw-r--r--gr-filter/lib/single_pole_iir_filter_cc_impl.cc89
-rw-r--r--gr-filter/lib/single_pole_iir_filter_cc_impl.h55
-rw-r--r--gr-filter/lib/single_pole_iir_filter_ff_impl.cc87
-rw-r--r--gr-filter/lib/single_pole_iir_filter_ff_impl.h54
-rwxr-xr-xgr-filter/python/qa_single_pole_iir.py114
-rw-r--r--gr-filter/swig/filter_swig.i6
14 files changed, 819 insertions, 0 deletions
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
index 663cc0b004..83036a0b3e 100644
--- a/gr-filter/grc/CMakeLists.txt
+++ b/gr-filter/grc/CMakeLists.txt
@@ -25,6 +25,7 @@ install(FILES
filter_delay_fc.xml
hilbert_fc.xml
pfb_channelizer.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 988897fcf8..6711e809fc 100644
--- a/gr-filter/grc/filter_block_tree.xml
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -36,5 +36,6 @@
<block>filter_delay_fc</block>
<block>hilbert_fc</block>
<block>pfb_channelizer_ccf</block>
+ <block>single_pole_iir_filter_xx</block>
</cat>
</cat>
diff --git a/gr-filter/grc/single_pole_iir_filter_xx.xml b/gr-filter/grc/single_pole_iir_filter_xx.xml
new file mode 100644
index 0000000000..3eaf52625f
--- /dev/null
+++ b/gr-filter/grc/single_pole_iir_filter_xx.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Single Pole IIR Filter
+###################################################
+ -->
+<block>
+ <name>Single Pole IIR Filter</name>
+ <key>single_pole_iir_filter_xx</key>
+ <import>from gnuradio import filter</import>
+ <make>filter.single_pole_iir_filter_$(type.fcn)($alpha, $vlen)</make>
+ <callback>set_taps($alpha)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index 24e63dc0ca..49e946536d 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -81,6 +81,7 @@ install(FILES
fft_filter.h
pm_remez.h
polyphase_filterbank.h
+ single_pole_iir.h
${generated_includes}
adaptive_fir_ccc.h
adaptive_fir_ccf.h
@@ -91,6 +92,8 @@ install(FILES
fft_filter_fff.h
hilbert_fc.h
pfb_channelizer_ccf.h
+ single_pole_iir_filter_cc.h
+ single_pole_iir_filter_ff.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter
COMPONENT "fft_devel"
)
diff --git a/gr-filter/include/filter/single_pole_iir.h b/gr-filter/include/filter/single_pole_iir.h
new file mode 100644
index 0000000000..10d1b4791b
--- /dev/null
+++ b/gr-filter/include/filter/single_pole_iir.h
@@ -0,0 +1,200 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2006,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_SINGLE_POLE_IIR_H
+#define INCLUDED_SINGLE_POLE_IIR_H
+
+#include <filter/api.h>
+#include <stdexcept>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief class template for single pole IIR filter
+ */
+ template<class o_type, class i_type, class tap_type>
+ class single_pole_iir
+ {
+ public:
+ /*!
+ * \brief construct new single pole IIR with given alpha
+ *
+ * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i)
+ */
+ single_pole_iir(tap_type alpha = 1.0)
+ {
+ d_prev_output = 0;
+ set_taps(alpha);
+ }
+
+ /*!
+ * \brief compute a single output value.
+ * \returns the filtered input value.
+ */
+ o_type filter(const i_type input);
+
+ /*!
+ * \brief compute an array of N output values.
+ * \p input must have n valid entries.
+ */
+ void filterN(o_type output[], const i_type input[], unsigned long n);
+
+ /*!
+ * \brief install \p alpha as the current taps.
+ */
+ void set_taps(tap_type alpha)
+ {
+ if(alpha < 0 || alpha > 1)
+ throw std::out_of_range("Alpha must be in [0, 1]\n");
+
+ d_alpha = alpha;
+ d_one_minus_alpha = 1.0 - alpha;
+ }
+
+ //! reset state to zero
+ void reset()
+ {
+ d_prev_output = 0;
+ }
+
+ o_type prev_output() const { return d_prev_output; }
+
+ protected:
+ tap_type d_alpha;
+ tap_type d_one_minus_alpha;
+ o_type d_prev_output;
+ };
+
+ //
+ // general case. We may want to specialize this
+ //
+ template<class o_type, class i_type, class tap_type>
+ o_type
+ single_pole_iir<o_type, i_type, tap_type>::filter(const i_type input)
+ {
+ o_type output;
+
+ output = d_alpha * input + d_one_minus_alpha * d_prev_output;
+ d_prev_output = output;
+
+ return (o_type) output;
+ }
+
+
+ template<class o_type, class i_type, class tap_type>
+ void
+ single_pole_iir<o_type, i_type, tap_type>::filterN(o_type output[],
+ const i_type input[],
+ unsigned long n)
+ {
+ for(unsigned i = 0; i < n; i++)
+ output[i] = filter(input[i]);
+ }
+
+
+ //
+ // Specialized case for gr_complex output and double taps
+ // We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double)
+
+ template<class i_type>
+ class single_pole_iir<gr_complex, i_type, double>
+ {
+ public:
+ /*!
+ * \brief construct new single pole IIR with given alpha
+ *
+ * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i)
+ */
+ single_pole_iir(double alpha = 1.0)
+ {
+ d_prev_output = 0;
+ set_taps(alpha);
+ }
+
+ /*!
+ * \brief compute a single output value.
+ * \returns the filtered input value.
+ */
+ gr_complex filter(const i_type input);
+
+ /*!
+ * \brief compute an array of N output values.
+ * \p input must have n valid entries.
+ */
+ void filterN(gr_complex output[], const i_type input[], unsigned long n);
+
+ /*!
+ * \brief install \p alpha as the current taps.
+ */
+ void set_taps(double alpha)
+ {
+ if(alpha < 0 || alpha > 1)
+ throw std::out_of_range("Alpha must be in [0, 1]\n");
+
+ d_alpha = alpha;
+ d_one_minus_alpha = 1.0 - alpha;
+ }
+
+ //! reset state to zero
+ void reset()
+ {
+ d_prev_output = 0;
+ }
+
+ gr_complexd prev_output() const { return d_prev_output; }
+
+ protected:
+ double d_alpha;
+ double d_one_minus_alpha;
+ gr_complexd d_prev_output;
+ };
+
+ template< class i_type>
+ gr_complex
+ single_pole_iir<gr_complex, i_type, double>::filter(const i_type input)
+ {
+ gr_complexd output;
+
+ output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output;
+ d_prev_output = output;
+
+ return (gr_complex) output;
+ }
+
+ //Do we need to specialize this, although it is the same as the general case?
+
+ template<class i_type>
+ void
+ single_pole_iir<gr_complex, i_type, double>::filterN(gr_complex output[],
+ const i_type input[],
+ unsigned long n)
+ {
+ for(unsigned i = 0; i < n; i++)
+ output[i] = filter(input[i]);
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_H */
diff --git a/gr-filter/include/filter/single_pole_iir_filter_cc.h b/gr-filter/include/filter/single_pole_iir_filter_cc.h
new file mode 100644
index 0000000000..37db7c65fb
--- /dev/null
+++ b/gr-filter/include/filter/single_pole_iir_filter_cc.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,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_SINGLE_POLE_IIR_FILTER_CC_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H
+
+#include <filter/api.h>
+#include <filter/single_pole_iir.h>
+#include <gr_sync_block.h>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief single pole IIR filter with complex input, complex output
+ * \ingroup filter_blk
+ *
+ * The input and output satisfy a difference equation of the form
+ \htmlonly
+ \f{
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \endxmlonly
+
+ * with the corresponding rational system function
+ \htmlonly
+ \f{
+ H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}}
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}}
+ \endxmlonly
+
+ * Note that some texts define the system function with a + in the
+ * denominator. If you're using that convention, you'll need to
+ * negate the feedback tap.
+ */
+ class FILTER_API single_pole_iir_filter_cc : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::single_pole_iir_filter_cc::sptr
+ typedef boost::shared_ptr<single_pole_iir_filter_cc> sptr;
+
+ static FILTER_API sptr make(double alpha, unsigned int vlen=1);
+
+ virtual void set_taps(double alpha) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H */
diff --git a/gr-filter/include/filter/single_pole_iir_filter_ff.h b/gr-filter/include/filter/single_pole_iir_filter_ff.h
new file mode 100644
index 0000000000..8abce94c90
--- /dev/null
+++ b/gr-filter/include/filter/single_pole_iir_filter_ff.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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_SINGLE_POLE_IIR_FILTER_FF_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H
+
+#include <filter/api.h>
+#include <filter/single_pole_iir.h>
+#include <gr_sync_block.h>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief single pole IIR filter with float input, float output
+ * \ingroup filter_blk
+ *
+ * The input and output satisfy a difference equation of the form
+ \htmlonly
+ \f{
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \endxmlonly
+
+ * with the corresponding rational system function
+ \htmlonly
+ \f{
+ H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}}
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}}
+ \endxmlonly
+
+ * Note that some texts define the system function with a + in the
+ * denominator. If you're using that convention, you'll need to
+ * negate the feedback tap.
+ */
+ class FILTER_API single_pole_iir_filter_ff : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::single_pole_iir_filter_ff::sptr
+ typedef boost::shared_ptr<single_pole_iir_filter_ff> sptr;
+
+ static FILTER_API sptr make(double alpha, unsigned int vlen=1);
+
+ virtual void set_taps (double alpha) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 7a6394b572..d661d01b63 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -121,6 +121,8 @@ list(APPEND filter_sources
fft_filter_fff_impl.cc
hilbert_fc_impl.cc
pfb_channelizer_ccf_impl.cc
+ single_pole_iir_filter_cc_impl.cc
+ single_pole_iir_filter_ff_impl.cc
)
list(APPEND filter_libs
diff --git a/gr-filter/lib/single_pole_iir_filter_cc_impl.cc b/gr-filter/lib/single_pole_iir_filter_cc_impl.cc
new file mode 100644
index 0000000000..9406f2c98a
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_cc_impl.cc
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006,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 "single_pole_iir_filter_cc_impl.h"
+#include <gr_io_signature.h>
+
+
+namespace gr {
+ namespace filter {
+
+ single_pole_iir_filter_cc::sptr
+ single_pole_iir_filter_cc::make(double alpha, unsigned int vlen)
+ {
+ return gnuradio::get_initial_sptr
+ (new single_pole_iir_filter_cc_impl(alpha, vlen));
+ }
+
+ single_pole_iir_filter_cc_impl::single_pole_iir_filter_cc_impl
+ (double alpha, unsigned int vlen)
+ : gr_sync_block("single_pole_iir_filter_cc",
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * vlen),
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * vlen)),
+ d_vlen(vlen), d_iir(vlen)
+ {
+ set_taps(alpha);
+ }
+
+ single_pole_iir_filter_cc_impl::~single_pole_iir_filter_cc_impl()
+ {
+ }
+
+ void
+ single_pole_iir_filter_cc_impl::set_taps(double alpha)
+ {
+ for(unsigned int i = 0; i < d_vlen; i++) {
+ d_iir[i].set_taps(alpha);
+ }
+ }
+
+ int
+ single_pole_iir_filter_cc_impl::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];
+ unsigned int vlen = d_vlen;
+
+ if(d_vlen == 1) {
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = d_iir[0].filter(in[i]);
+ }
+ }
+ else {
+ for(int i = 0; i < noutput_items; i++) {
+ for(unsigned int j = 0; j < vlen; j++) {
+ *out++ = d_iir[j].filter(*in++);
+ }
+ }
+ }
+
+ return noutput_items;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/single_pole_iir_filter_cc_impl.h b/gr-filter/lib/single_pole_iir_filter_cc_impl.h
new file mode 100644
index 0000000000..fa627881e5
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_cc_impl.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,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_SINGLE_POLE_IIR_FILTER_CC_IMPL_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H
+
+#include <filter/single_pole_iir.h>
+#include <filter/single_pole_iir_filter_cc.h>
+#include <gr_sync_block.h>
+#include <gr_complex.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API single_pole_iir_filter_cc_impl : public single_pole_iir_filter_cc
+ {
+ private:
+ unsigned int d_vlen;
+ std::vector<single_pole_iir<gr_complex,gr_complex,double> > d_iir;
+
+ public:
+ single_pole_iir_filter_cc_impl(double alpha, unsigned int vlen);
+ ~single_pole_iir_filter_cc_impl();
+
+ void set_taps(double alpha);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H */
diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.cc b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc
new file mode 100644
index 0000000000..7e2bae5db7
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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 "single_pole_iir_filter_ff_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ single_pole_iir_filter_ff::sptr
+ single_pole_iir_filter_ff::make(double alpha, unsigned int vlen)
+ {
+ return gnuradio::get_initial_sptr
+ (new single_pole_iir_filter_ff_impl(alpha, vlen));
+ }
+
+ single_pole_iir_filter_ff_impl::single_pole_iir_filter_ff_impl
+ (double alpha, unsigned int vlen)
+ : gr_sync_block("single_pole_iir_filter_ff",
+ gr_make_io_signature(1, 1, sizeof(float)*vlen),
+ gr_make_io_signature(1, 1, sizeof(float)*vlen)),
+ d_vlen(vlen), d_iir(vlen)
+ {
+ set_taps(alpha);
+ }
+
+ single_pole_iir_filter_ff_impl::~single_pole_iir_filter_ff_impl()
+ {
+ }
+
+ void
+ single_pole_iir_filter_ff_impl::set_taps(double alpha)
+ {
+ for(unsigned int i = 0; i < d_vlen; i++) {
+ d_iir[i].set_taps(alpha);
+ }
+ }
+
+ int
+ single_pole_iir_filter_ff_impl::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];
+ float *out = (float*)output_items[0];
+ unsigned int vlen = d_vlen;
+
+ if(d_vlen == 1) {
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = d_iir[0].filter (in[i]);
+ }
+ }
+ else {
+ for(int i = 0; i < noutput_items; i++) {
+ for(unsigned int j = 0; j < vlen; j++) {
+ *out++ = d_iir[j].filter(*in++);
+ }
+ }
+ }
+ return noutput_items;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.h b/gr-filter/lib/single_pole_iir_filter_ff_impl.h
new file mode 100644
index 0000000000..cba9c188c2
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,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_SINGLE_POLE_IIR_FILTER_FF_IMPL_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H
+
+#include <filter/single_pole_iir.h>
+#include <filter/single_pole_iir_filter_ff.h>
+#include <gr_sync_block.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API single_pole_iir_filter_ff_impl : public single_pole_iir_filter_ff
+ {
+ private:
+ unsigned int d_vlen;
+ std::vector<single_pole_iir<float,float,double> > d_iir;
+
+ public:
+ single_pole_iir_filter_ff_impl(double alpha, unsigned int vlen);
+ ~single_pole_iir_filter_ff_impl();
+
+ void set_taps(double alpha);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H */
diff --git a/gr-filter/python/qa_single_pole_iir.py b/gr-filter/python/qa_single_pole_iir.py
new file mode 100755
index 0000000000..3608c77f95
--- /dev/null
+++ b/gr-filter/python/qa_single_pole_iir.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+
+class test_single_pole_iir_filter(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_ff_001(self):
+ src_data = (0, 1000, 2000, 3000, 4000, 5000)
+ expected_result = src_data
+ src = gr.vector_source_f(src_data)
+ op = filter.single_pole_iir_filter_ff(1.0)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_ff_002(self):
+ src_data = (0, 1000, 2000, 3000, 4000, 5000)
+ expected_result = (0, 125, 359.375, 689.453125, 1103.271484, 1590.36255)
+ src = gr.vector_source_f(src_data)
+ op = filter.single_pole_iir_filter_ff(0.125)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data, 3)
+
+ def test_ff_003(self):
+ block_size = 2
+ src_data = (0, 1000, 2000, 3000, 4000, 5000)
+ expected_result = (0, 125, 250, 484.375, 718.75, 1048.828125)
+ src = gr.vector_source_f(src_data)
+ s2p = gr.serial_to_parallel(gr.sizeof_float, block_size)
+ op = filter.single_pole_iir_filter_ff (0.125, block_size)
+ p2s = gr.parallel_to_serial(gr.sizeof_float, block_size)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, s2p, op, p2s, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data, 3)
+
+ def test_cc_001(self):
+ src_data = (0+0j, 1000+1000j, 2000+2000j, 3000+3000j, 4000+4000j, 5000+5000j)
+ expected_result = src_data
+ src = gr.vector_source_c(src_data)
+ op = filter.single_pole_iir_filter_cc(1.0)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data)
+
+ def test_cc_002(self):
+ src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000),
+ complex(3000,-3000), complex(4000,-4000), complex(5000,-5000))
+ expected_result = (complex(0,0), complex(125,-125), complex(359.375,-359.375),
+ complex(689.453125,-689.453125), complex(1103.271484,-1103.271484),
+ complex(1590.36255,-1590.36255))
+ src = gr.vector_source_c(src_data)
+ op = filter.single_pole_iir_filter_cc(0.125)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 3)
+
+ def test_cc_003(self):
+ block_size = 2
+ src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000),
+ complex(3000,-3000), complex(4000,-4000), complex(5000,-5000))
+ expected_result = (complex(0,0), complex(125,-125), complex(250,-250),
+ complex(484.375,-484.375), complex(718.75,-718.75),
+ complex(1048.828125,-1048.828125))
+ src = gr.vector_source_c(src_data)
+ s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, block_size)
+ op = filter.single_pole_iir_filter_cc(0.125, block_size)
+ p2s = gr.parallel_to_serial(gr.sizeof_gr_complex, block_size)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, s2p, op, p2s, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 3)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_single_pole_iir_filter, "test_single_pole_iir_filter.xml")
+
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index 1bcafeb8c6..8585bda322 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -44,6 +44,8 @@
#include "filter/fft_filter_fff.h"
#include "filter/hilbert_fc.h"
#include "filter/pfb_channelizer_ccf.h"
+#include "filter/single_pole_iir_filter_cc.h"
+#include "filter/single_pole_iir_filter_ff.h"
%}
%include "filter/firdes.h"
@@ -62,6 +64,8 @@
%include "filter/fft_filter_fff.h"
%include "filter/hilbert_fc.h"
%include "filter/pfb_channelizer_ccf.h"
+%include "filter/single_pole_iir_filter_cc.h"
+%include "filter/single_pole_iir_filter_ff.h"
GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccc);
GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccf);
@@ -77,3 +81,5 @@ GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_ccc);
GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_fff);
GR_SWIG_BLOCK_MAGIC2(filter, hilbert_fc);
GR_SWIG_BLOCK_MAGIC2(filter, pfb_channelizer_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_cc);
+GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_ff);