summaryrefslogtreecommitdiff
path: root/gr-filter
diff options
context:
space:
mode:
authorTom Rondeau2012-06-16 10:55:36 -0400
committerTom Rondeau2012-06-16 10:55:36 -0400
commitd647fbbaa07554ad314c9eb2b5c1735b6265d13a (patch)
tree0fce319028b37495bef63b7740cd65d7a3378220 /gr-filter
parent3cd0ea45255e2ca43931b2f067ec82fc92f4293e (diff)
downloadgnuradio-d647fbbaa07554ad314c9eb2b5c1735b6265d13a.tar.gz
gnuradio-d647fbbaa07554ad314c9eb2b5c1735b6265d13a.tar.bz2
gnuradio-d647fbbaa07554ad314c9eb2b5c1735b6265d13a.zip
filter: adding freq_xlating_filter.
Includes QA and GRC. Update to build_utils adds a FIR_TYPE for the type of filter and CFIR_TYPE for the type of filter where the taps are always complex (needed for freq_xlating_filter).
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/freq_xlating_fir_filter_xxx.xml93
-rw-r--r--gr-filter/include/filter/CMakeLists.txt1
-rw-r--r--gr-filter/include/filter/fir_filter.h31
-rw-r--r--gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t90
-rw-r--r--gr-filter/lib/CMakeLists.txt1
-rw-r--r--gr-filter/lib/fir_filter.cc108
-rw-r--r--gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t143
-rw-r--r--gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t71
-rw-r--r--gr-filter/python/qa_freq_xlating_fir_filter.py445
-rw-r--r--gr-filter/swig/filter_swig.i18
12 files changed, 1003 insertions, 0 deletions
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
index 63434fe75..531dc5271 100644
--- a/gr-filter/grc/CMakeLists.txt
+++ b/gr-filter/grc/CMakeLists.txt
@@ -23,6 +23,7 @@ install(FILES
fft_filter_xxx.xml
fir_filter_xxx.xml
filter_delay_fc.xml
+ freq_xlating_fir_filter_xxx.xml
hilbert_fc.xml
iir_filter_ffd.xml
pfb_channelizer.xml
diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml
index 2ae4eb628..8ab43644b 100644
--- a/gr-filter/grc/filter_block_tree.xml
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -34,6 +34,7 @@
<block>fft_filter_xxx</block>
<block>fir_filter_xxx</block>
<block>filter_delay_fc</block>
+ <block>freq_xlating_fir_filter_xxx</block>
<block>hilbert_fc</block>
<block>iir_filter_ffd</block>
<block>pfb_channelizer_ccf</block>
diff --git a/gr-filter/grc/freq_xlating_fir_filter_xxx.xml b/gr-filter/grc/freq_xlating_fir_filter_xxx.xml
new file mode 100644
index 000000000..178a42f48
--- /dev/null
+++ b/gr-filter/grc/freq_xlating_fir_filter_xxx.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Frequency Xlating Filter
+###################################################
+ -->
+<block>
+ <name>Frequency Xlating FIR Filter</name>
+ <key>freq_xlating_fir_filter_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.freq_xlating_fir_filter_$(type)($decim, $taps, $center_freq, $samp_rate)</make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_center_freq($center_freq)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Real Taps)</name>
+ <key>fcf</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Real Taps)</name>
+ <key>scf</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Center Frequency</name>
+ <key>center_freq</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index ca8c7bf07..5da171ffa 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -65,6 +65,7 @@ endmacro(expand_h)
# Invoke macro to generate various sources
#######################################################################
expand_h(fir_filter_XXX fff ccf ccc scc fsf)
+expand_h(freq_xlating_fir_filter_XXX ccc ccf fcc fcf scc scf)
add_custom_target(filter_generated_includes DEPENDS
${generated_includes}
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
index ba82c7f48..42b4ac2e0 100644
--- a/gr-filter/include/filter/fir_filter.h
+++ b/gr-filter/include/filter/fir_filter.h
@@ -93,6 +93,37 @@ namespace gr {
/**************************************************************/
+ class FILTER_API fir_filter_fcc
+ {
+ public:
+ fir_filter_fcc(int decimation,
+ const std::vector<gr_complex> &taps);
+ ~fir_filter_fcc();
+
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const float input[]);
+ void filterN(gr_complex output[],
+ const float input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<gr_complex> d_taps;
+ unsigned int d_ntaps;
+ gr_complex **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ /**************************************************************/
+
class FILTER_API fir_filter_ccc
{
public:
diff --git a/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t b/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t
new file mode 100644
index 000000000..d56303461
--- /dev/null
+++ b/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004,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.
+ */
+
+/*
+ * WARNING: This file is automatically generated by cmake.
+ * Any changes made to this file will be overwritten.
+ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+#include <gr_rotator.h>
+
+namespace gr {
+ namespace filter {
+
+
+ /*!
+ * \brief FIR filter combined with frequency translation with
+ * @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps \ingroup
+ * filter_blk
+ *
+ * This class efficiently combines a frequency translation
+ * (typically "down conversion") with a FIR filter (typically
+ * low-pass) and decimation. It is ideally suited for a "channel
+ * selection filter" and can be efficiently used to select and
+ * decimate a narrow band signal out of wide bandwidth input.
+ *
+ * Uses a single input array to produce a single output array.
+ * Additional inputs and/or outputs are ignored.
+ */
+ class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ /*!
+ * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and
+ * @TAP_TYPE@ taps that also frequency translates a signal from
+ * \p center_freq.
+ * \ingroup filter_blk
+ *
+ * Construct a FIR filter with the given taps and a composite
+ * frequency translation that shifts center_freq down to zero
+ * Hz. The frequency translation logically comes before the
+ * filtering operation.
+ *
+ * \param decimation set the integer decimation rate
+ * \param taps a vector/list of taps of type @TAP_TYPE@
+ * \param center_freq Center frequency of signal to down convert from (Hz)
+ * \param sampling_freq Sampling rate of signal (in Hz)
+ */
+ static FILTER_API sptr make(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq);
+
+ virtual void set_center_freq(double center_freq) = 0;
+ virtual double center_freq() const = 0;
+
+ virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0;
+ virtual std::vector<@TAP_TYPE@> taps() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 7a8b5aa0b..055e3da90 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -81,6 +81,7 @@ endmacro(expand_cc)
# Invoke macro to generate various sources
########################################################################
expand_cc(fir_filter_XXX_impl fff ccf ccc scc fsf)
+expand_cc(freq_xlating_fir_filter_XXX_impl ccc ccf fcc fcf scc scf)
########################################################################
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
index 6c82dda5e..7ca1fae19 100644
--- a/gr-filter/lib/fir_filter.cc
+++ b/gr-filter/lib/fir_filter.cc
@@ -238,6 +238,114 @@ namespace gr {
}
}
+
+ /**************************************************************/
+
+
+ fir_filter_fcc::fir_filter_fcc(int decimation,
+ const std::vector<gr_complex> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(float);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_fcc::~fir_filter_fcc()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_fcc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<gr_complex>
+ fir_filter_fcc::taps() const
+ {
+ std::vector<gr_complex> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_fcc::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_fcc::filter(const float input[])
+ {
+ const float *ar = (float *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_32fc_32f_dot_prod_32fc_a(d_output,
+ d_aligned_taps[al],
+ ar,
+ (d_ntaps+al));
+ return *d_output;
+ }
+
+ void
+ fir_filter_fcc::filterN(gr_complex output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_fcc::filterNdec(gr_complex output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
/**************************************************************/
fir_filter_ccc::fir_filter_ccc(int decimation,
diff --git a/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t
new file mode 100644
index 000000000..a59fa12b3
--- /dev/null
+++ b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t
@@ -0,0 +1,143 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,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.
+ */
+
+/*
+ * WARNING: This file is automatically generated by cmake.
+ * Any changes made to this file will be overwritten.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "@IMPL_NAME@.h"
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq)
+ {
+ return gnuradio::get_initial_sptr(new @IMPL_NAME@
+ (decimation, taps,
+ center_freq,
+ sampling_freq));
+ }
+
+ @IMPL_NAME@::@IMPL_NAME@(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq)
+ : gr_sync_decimator("@BASE_NAME@",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
+ decimation),
+ d_proto_taps(taps), d_center_freq(center_freq),
+ d_sampling_freq(sampling_freq),
+ d_updated(false)
+ {
+ std::vector<gr_complex> dummy_taps;
+ d_composite_fir = new kernel::@CFIR_TYPE@(decimation, dummy_taps);
+
+ set_history(d_proto_taps.size());
+ build_composite_fir();
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ delete d_composite_fir;
+ }
+
+ void
+ @IMPL_NAME@::build_composite_fir()
+ {
+ std::vector<gr_complex> ctaps(d_proto_taps.size());
+
+ float fwT0 = -2 * M_PI * d_center_freq / d_sampling_freq;
+ for(unsigned int i = 0; i < d_proto_taps.size(); i++) {
+ ctaps[i] = d_proto_taps[i] * exp(gr_complex(0, i * fwT0));
+ }
+
+ std::reverse(ctaps.begin(), ctaps.end());
+ d_composite_fir->set_taps(ctaps);
+ d_r.set_phase_incr(exp(gr_complex(0, fwT0 * decimation())));
+ }
+
+ void
+ @IMPL_NAME@::set_center_freq(double center_freq)
+ {
+ d_center_freq = center_freq;
+ d_updated = true;
+ }
+
+ double
+ @IMPL_NAME@::center_freq() const
+ {
+ return d_center_freq;
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_proto_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_proto_taps;
+ }
+
+ int
+ @IMPL_NAME@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ @I_TYPE@ *in = (@I_TYPE@ *)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@ *)output_items[0];
+
+ // rebuild composite FIR if the center freq has changed
+ if(d_updated) {
+ set_history(d_proto_taps.size());
+ build_composite_fir();
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ unsigned j = 0;
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = d_r.rotate(d_composite_fir->filter(&in[j]));
+ j += decimation();
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t
new file mode 100644
index 000000000..0cf976d58
--- /dev/null
+++ b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004,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.
+ */
+
+/*
+ * WARNING: This file is automatically generated by cmake.
+ * Any changes made to this file will be overwritten.
+ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <filter/fir_filter.h>
+#include <filter/@BASE_NAME@.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
+ {
+ protected:
+ std::vector<@TAP_TYPE@> d_proto_taps;
+ kernel::@CFIR_TYPE@ *d_composite_fir;
+ gr_rotator d_r;
+ double d_center_freq;
+ double d_sampling_freq;
+ bool d_updated;
+
+ virtual void build_composite_fir();
+ public:
+
+ @IMPL_NAME@(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq);
+ virtual ~@IMPL_NAME@();
+
+ void set_center_freq(double center_freq);
+ double center_freq() const;
+
+ void set_taps(const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> 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 /* @GUARD_NAME@ */
diff --git a/gr-filter/python/qa_freq_xlating_fir_filter.py b/gr-filter/python/qa_freq_xlating_fir_filter.py
new file mode 100644
index 000000000..ee38eb7df
--- /dev/null
+++ b/gr-filter/python/qa_freq_xlating_fir_filter.py
@@ -0,0 +1,445 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,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 this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import cmath, math
+
+class test_freq_xlating_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block ()
+
+ def tearDown(self):
+ self.tb = None
+
+ def generate_ccf_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_ccc_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_fcf_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_fcc_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_scf_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times)
+
+ def generate_scc_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times)
+
+
+ def test_fir_filter_ccf_001(self):
+ self.generate_ccf_source()
+ expected_data = ((0.001697700354270637+0.004312471952289343j),
+ (0.003520616563037038-0.003014103975147009j),
+ (0.004252811893820763-0.008337559178471565j),
+ (0.0030743128154426813-0.010262271389365196j),
+ (0.0007344777695834637-0.007861139252781868j),
+ (-0.0011067686136811972-0.0028924935031682253j),
+ (-0.002371778478845954+0.0019914964213967323j),
+ (-0.003023319412022829+0.005717850290238857j),
+ (-0.0021738125942647457+0.007211698684841394j),
+ (-0.0004628606839105487+0.005501383915543556j),
+ (0.0007428556564264+0.0019867848604917526j),
+ (0.001634795218706131-0.0013514887541532516j),
+ (0.002205110155045986-0.00402155052870512j),
+ (0.0015480631263926625-0.005179159343242645j),
+ (0.00026722141774371266-0.003887997241690755j),
+ (-0.0004911854630336165-0.0013578246580436826j),
+ (-0.0011226939968764782+0.0009080552263185382j),
+ (-0.0016229727771133184+0.0028335191309452057j),
+ (-0.0010890064295381308+0.0037298379465937614j),
+ (-0.00012392725329846144+0.0027196139562875032j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccf(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_ccf_002(self):
+ self.generate_ccf_source()
+ expected_data = ((6.419439159799367e-05-0.0006292851758189499j),
+ (-0.00037074743886478245+0.0013245552545413375j),
+ (0.0006853155209682882-0.0023769831750541925j),
+ (-0.001427714480087161+0.002608160488307476j),
+ (0.0015907397028058767-0.000811046629678458j),
+ (-0.0004226673918310553-0.0024389736354351044j),
+ (-0.0013841050677001476+0.006231029983609915j),
+ (0.0035029184073209763-0.009738259017467499j),
+ (-0.005924836732447147+0.010320881381630898j),
+ (0.006831614300608635-0.003950652200728655j),
+ (-0.0021247887052595615-0.015604906715452671j),
+ (-0.04283163696527481+0.09995654970407486j),
+ (-0.01391829177737236+0.07924056798219681j),
+ (0.010886997915804386-0.02463012933731079j),
+ (-0.0056075905449688435+0.004998659715056419j),
+ (0.0016976913902908564+0.004312459379434586j),
+ (0.0007344821933656931-0.007861112244427204j),
+ (-0.002173811662942171+0.007211671676486731j),
+ (0.0022051059640944004-0.00402153329923749j),
+ (-0.0011226903880015016+0.0009080505697056651j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccf(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_ccc_001(self):
+ self.generate_ccc_source()
+ expected_data = ((0.0036842757836-0.0114002721384j),
+ (0.00324621866457-0.0108166672289j),
+ (0.00206564785913-0.00923090614378j),
+ (0.00109899020754-0.00656201224774j),
+ (0.000506619049702-0.00402844604105j),
+ (-0.000523390364833-0.00166808743961j),
+ (-0.00140534969978+0.00103991874494j),
+ (-0.00154365820345+0.00315759982914j),
+ (-0.00180402118713+0.00427215453237j),
+ (-0.00216706306674+0.00524478312582j),
+ (-0.00178848754149+0.0057489364408j),
+ (-0.00129876169376+0.00512680830434j),
+ (-0.00122803379782+0.00427244976163j),
+ (-0.000722666736692+0.00351428100839j),
+ (5.53092104383e-05+0.00207865727134j),
+ (0.000227351076319+0.000517217209563j),
+ (0.000414477253798-0.000383921898901j),
+ (0.000998671515845-0.00135387131013j),
+ (0.00104933069088-0.00243046949618j),
+ (0.000765930046327-0.0026717747096j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccc(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_ccc_002(self):
+ self.generate_ccc_source()
+ expected_data = ((-0.000650451984257+0.00120697380044j),
+ (-9.59713361226e-05+0.00102412770502j),
+ (0.000958710326813-0.00145424995571j),
+ (0.000901343999431-0.00290832063183j),
+ (-0.000822560978122+0.000296717538731j),
+ (-0.00211223773658+0.00519825471565j),
+ (-0.00037001183955+0.00358242215589j),
+ (0.00327983591706-0.00616005761549j),
+ (0.00356886954978-0.0117237549275j),
+ (-0.00328874029219+0.00182871113066j),
+ (-0.0139285130426+0.0320657044649j),
+ (-0.0198133718222+0.0562113076448j),
+ (-0.0157803222537+0.0530290603638j),
+ (-0.00550725404173+0.0255754813552j),
+ (0.00252919178456-0.00232240976766j),
+ (0.00368427345529-0.0114002330229j),
+ (0.000506620621309-0.00402843113989j),
+ (-0.00180401885882+0.00427213776857j),
+ (-0.00122803344857+0.00427243299782j),
+ (0.000414476031438-0.000383919978049j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccc(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcf_001(self):
+ self.generate_fcf_source()
+ expected_data = ((0.000247188087087-0.000157509770361j),
+ (-0.000155229790835-0.000246197130764j),
+ (-0.000264906557277+0.000174603672349j),
+ (6.99016964063e-05+0.000174961372977j),
+ (-5.48477692064e-05-0.0001131295503j),
+ (-0.000237467131228+0.000118011368613j),
+ (0.000136614587973+0.000229531884543j),
+ (0.000229347482673-0.000166581812664j),
+ (-0.000106010869786-0.000150042149471j),
+ (2.92293734674e-05+0.000142060467624j),
+ (0.000228707227507-9.30760797928e-05j),
+ (-0.000124306126963-0.000216641055886j),
+ (-0.000204823678359+0.00016052465071j),
+ (0.00012825592421+0.000133123627165j),
+ (-1.18284006021e-05-0.000159015646204j),
+ (-0.000219973371713+7.5438656495e-05j),
+ (0.000114713984658+0.000205190401175j),
+ (0.000185727752978-0.000154630601173j),
+ (-0.000141745767905-0.000120098840853j),
+ (-3.9850056055e-07+0.000168364742422j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcf(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcf_002(self):
+ self.generate_fcf_source()
+ expected_data = ((7.3052920925e-05-3.91741014028e-06j),
+ (3.11913172482e-05-0.000109872074972j),
+ (-0.000128646017401-3.49857727997e-05j),
+ (-5.49546712136e-05+8.96326746442e-05j),
+ (5.14321582159e-05+9.64698920143e-05j),
+ (0.000120189361041+2.4231892894e-05j),
+ (0.000100405508419-0.000223224604269j),
+ (-0.000274751859251-2.33274622587e-05j),
+ (1.52600114234e-06+0.000133301247843j),
+ (3.77224641852e-05+5.29596509296e-05j),
+ (-3.60160379387e-06+0.000247975171078j),
+ (0.00113093166146-0.000663110695314j),
+ (0.00059568521101-0.00099650840275j),
+ (-0.000475480686873+0.000250602373853j),
+ (0.000191397906747+0.000271986238658j),
+ (0.000247183139436-0.000157510468853j),
+ (-5.48357638763e-05-0.000113135029096j),
+ (-0.00010601492977-0.00015005269961j),
+ (-0.000204817260965+0.000160534662427j),
+ (0.000114742244477+0.000205190313864j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcf(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcc_001(self):
+ self.generate_fcc_source()
+ expected_data = ((-0.000337088305969+7.46004516259e-05j),
+ (-5.63409266761e-05+0.000301144464174j),
+ (9.16960561881e-05-2.89259278361e-05j),
+ (-0.000231866899412-6.25764005235e-05j),
+ (-0.000116414688819+0.000258557556663j),
+ (0.000206079319469+5.05045172758e-05j),
+ (-3.85114690289e-05-0.00019276549574j),
+ (-0.000146380873048+0.000112079876999j),
+ (0.000215423395275+0.000116706331028j),
+ (0.000136050162837-0.000232611957472j),
+ (-0.000155499437824-5.41604022146e-05j),
+ (0.000106907449663+0.00016310159117j),
+ (0.000224392410018-0.000156331108883j),
+ (-0.000131131906528-0.000172063446371j),
+ (-5.92393880652e-05+0.00016801241145j),
+ (0.000214921761653-5.32235890205e-06j),
+ (-5.96960526309e-05-0.000211164733628j),
+ (-0.000193948610104+0.000113364716526j),
+ (0.000134820176754+0.000142527525895j),
+ (4.74465123261e-05-0.000175131688593j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcc(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcc_002(self):
+ self.generate_fcc_source()
+ expected_data = ((-6.94218761055e-05-9.90489479591e-06j),
+ (-2.56973435171e-05+8.05932795629e-05j),
+ (7.01698663761e-05+7.36373840482e-05j),
+ (7.57163215894e-05-4.65324592369e-05j),
+ (-3.01657128148e-05-0.000122838056996j),
+ (-9.53659764491e-05-3.73945695173e-05j),
+ (-2.33501577895e-05+0.000109135726234j),
+ (6.65136758471e-05+0.000125709688291j),
+ (3.08501912514e-05-9.16842873266e-06j),
+ (-2.64703612629e-05-0.000135892929393j),
+ (0.000136643866426-0.000162003751029j),
+ (0.000501801609062-0.000185820827028j),
+ (0.000694551155902-0.000299874518532j),
+ (0.000424396857852-0.00038379128091j),
+ (-9.1786707344e-05-0.000242479465669j),
+ (-0.000337087287335+7.45999423089e-05j),
+ (-0.000116414521472+0.000258556567132j),
+ (0.000215422536712+0.000116706112749j),
+ (0.000224391726078-0.000156330308528j),
+ (-5.96956087975e-05-0.000211163976928j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcc(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scf_001(self):
+ self.generate_scf_source()
+ expected_data = ((-0.0330070219934+0.101965591311j),
+ (-0.0484239049256+0.0872343629599j),
+ (-0.0214109234512+0.102555386722j),
+ (0.0484058149159+0.0557125210762j),
+ (0.0574690811336-0.0350844524801j),
+ (0.0365394353867-0.0802438184619j),
+ (0.0453781634569-0.130992040038j),
+ (0.00801951438189-0.214278846979j),
+ (-0.0770946145058-0.230616629124j),
+ (-0.105601429939-0.190731987357j),
+ (-0.105361394584-0.177761554718j),
+ (-0.131518915296-0.136102750897j),
+ (-0.103761836886-0.0382263250649j),
+ (-0.0167790111154+0.0152206514031j),
+ (0.0277570039034+0.0300403907895j),
+ (0.056065287441+0.0806603953242j),
+ (0.118084669113+0.104863211513j),
+ (0.128281414509+0.0677760615945j),
+ (0.0748447552323+0.0619902014732j),
+ (0.0512856245041+0.0775099247694j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scf(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scf_002(self):
+ self.generate_scf_source()
+ expected_data = ((0.00824625696987-1.50158575707e-05j),
+ (0.0020101047121-0.0116540221497j),
+ (-0.0126378880814-0.00259830290452j),
+ (-0.00363933457993+0.00837504956871j),
+ (0.00107023562305+0.00915473792702j),
+ (0.0169738996774+0.00422182958573j),
+ (0.00630031805485-0.025423232466j),
+ (-0.0283014029264+0.00104465708137j),
+ (0.00890890974551+0.0115978596732j),
+ (-0.0142687577754+0.00306978379376j),
+ (0.02845691517+0.0331163145602j),
+ (0.0538152232766-0.0908300876617j),
+ (-0.0843691527843-0.0956566259265j),
+ (0.0476895272732+0.0747984498739j),
+ (0.0898786485195+0.082478672266j),
+ (-0.0330070182681+0.101965606213j),
+ (0.0574697069824-0.0350842289627j),
+ (-0.0770940706134-0.230615705252j),
+ (-0.103762261569-0.0382265634835j),
+ (0.11808334291+0.104863762856j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scf(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scc_001(self):
+ self.generate_scc_source()
+ expected_data = ((-0.00775564694777+0.0437113791704j),
+ (0.0108830630779+0.0433648750186j),
+ (0.015553932637-0.0133284125477j),
+ (-0.0264905355871-0.0403266139328j),
+ (-0.0243480335921-0.03030154109j),
+ (-0.000327925226884-0.069333948195j),
+ (-0.0306392069906-0.107313856483j),
+ (-0.0452371090651-0.0854917764664j),
+ (-0.0108894333243-0.0875641107559j),
+ (-0.0182112380862-0.118961036205j),
+ (-0.0447825863957-0.0922874584794j),
+ (-0.0147479763255-0.0572904124856j),
+ (0.00204290449619-0.0721436738968j),
+ (-0.027713002637-0.0548989400268j),
+ (-0.0149045493454-0.00210141134448j),
+ (0.0176361314952-0.00149522523861j),
+ (-0.00527482619509-0.00698099425063j),
+ (-0.0151527002454+0.036265052855j),
+ (0.0199296213686+0.0452499426901j),
+ (0.0122985243797+0.0143278446048j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scc(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scc_002(self):
+ self.generate_scc_source()
+ expected_data = ((-0.0080680437386-0.00158522999845j),
+ (-0.0037795654498+0.00733159901574j),
+ (0.00842926371843+0.00777021236718j),
+ (0.0112090632319-0.00249325321056j),
+ (-0.0027476802934-0.0115710813552j),
+ (-0.0158688724041-0.00715934624895j),
+ (-0.00802888441831+0.00620818417519j),
+ (0.0131985172629+0.0149175003171j),
+ (0.0190298333764+0.00956719089299j),
+ (-0.00112380902283-0.00936658866704j),
+ (-0.0204226914793-0.0333464704454j),
+ (-0.00695514678955-0.0437445007265j),
+ (0.0314490310848-0.0207983348519j),
+ (0.0529675260186+0.0302227605134j),
+ (0.0317338332534+0.0667510479689j),
+ (-0.00775565672666+0.0437112376094j),
+ (-0.024347923696-0.0303014591336j),
+ (-0.0108893103898-0.0875638127327j),
+ (0.00204296782613-0.0721434056759j),
+ (-0.00527479872108-0.00698097236454j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scc(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_freq_xlating_filter, "test_freq_xlating_filter.xml")
+
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index be5338f4b..161fd4fe3 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -42,6 +42,12 @@
#include "filter/fir_filter_fsf.h"
#include "filter/fft_filter_ccc.h"
#include "filter/fft_filter_fff.h"
+#include "filter/freq_xlating_fir_filter_ccc.h"
+#include "filter/freq_xlating_fir_filter_ccf.h"
+#include "filter/freq_xlating_fir_filter_fcc.h"
+#include "filter/freq_xlating_fir_filter_fcf.h"
+#include "filter/freq_xlating_fir_filter_scc.h"
+#include "filter/freq_xlating_fir_filter_scf.h"
#include "filter/hilbert_fc.h"
#include "filter/iir_filter_ffd.h"
#include "filter/pfb_channelizer_ccf.h"
@@ -63,6 +69,12 @@
%include "filter/fir_filter_fsf.h"
%include "filter/fft_filter_ccc.h"
%include "filter/fft_filter_fff.h"
+%include "filter/freq_xlating_fir_filter_ccc.h"
+%include "filter/freq_xlating_fir_filter_ccf.h"
+%include "filter/freq_xlating_fir_filter_fcc.h"
+%include "filter/freq_xlating_fir_filter_fcf.h"
+%include "filter/freq_xlating_fir_filter_scc.h"
+%include "filter/freq_xlating_fir_filter_scf.h"
%include "filter/hilbert_fc.h"
%include "filter/iir_filter_ffd.h"
%include "filter/pfb_channelizer_ccf.h"
@@ -81,6 +93,12 @@ GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_scc);
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fsf);
GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_ccc);
GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_fcc);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_fcf);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_scc);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_scf);
GR_SWIG_BLOCK_MAGIC2(filter, hilbert_fc);
GR_SWIG_BLOCK_MAGIC2(filter, iir_filter_ffd);
GR_SWIG_BLOCK_MAGIC2(filter, pfb_channelizer_ccf);