summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnuradio-core/src/python/build_utils.py32
-rw-r--r--gr-filter/CMakeLists.txt4
-rw-r--r--gr-filter/include/filter/CMakeLists.txt15
-rw-r--r--gr-filter/include/filter/fft.h195
-rw-r--r--gr-filter/include/filter/fft_vcc.h57
-rw-r--r--gr-filter/include/filter/fir_filter.h112
-rw-r--r--gr-filter/include/filter/fir_filter_XXX.h.t (renamed from gr-filter/include/filter/fir_filter_fff.h)22
-rw-r--r--gr-filter/lib/CMakeLists.txt69
-rw-r--r--gr-filter/lib/fir_filter.cc268
-rw-r--r--gr-filter/lib/fir_filter_XXX_impl.cc.t98
-rw-r--r--gr-filter/lib/fir_filter_XXX_impl.h.t (renamed from gr-filter/lib/fir_filter_fff_impl.h)27
-rw-r--r--gr-filter/lib/fir_filter_fff_impl.cc123
-rwxr-xr-xgr-filter/python/qa_fir_filter.py22
-rw-r--r--gr-filter/swig/CMakeLists.txt2
-rw-r--r--gr-filter/swig/filter_swig.i6
15 files changed, 643 insertions, 409 deletions
diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py
index 0660941d5..0898f46c4 100644
--- a/gnuradio-core/src/python/build_utils.py
+++ b/gnuradio-core/src/python/build_utils.py
@@ -182,7 +182,37 @@ def standard_dict (name, code3):
d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper ()
d['BASE_NAME'] = re.sub ('^gr_', '', name)
d['SPTR_NAME'] = '%s_sptr' % name
- d['WARNING'] = 'WARNING: this file is machine generated. Edits will be over written'
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+
+def standard_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['BASE_NAME'] = name
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+def standard_impl_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['IMPL_NAME'] = name
+ d['BASE_NAME'] = name.rstrip("_impl")
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
d['COPYRIGHT'] = copyright
d['TYPE'] = i_type (code3)
d['I_TYPE'] = i_type (code3)
diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt
index a4d25fd13..02b8f23fe 100644
--- a/gr-filter/CMakeLists.txt
+++ b/gr-filter/CMakeLists.txt
@@ -35,9 +35,11 @@ GR_REGISTER_COMPONENT("gr-filter" ENABLE_GR_FILTER
ENABLE_GR_FFT
)
-GR_SET_GLOBAL(FILTER_INCLUDE_DIRS
+GR_SET_GLOBAL(GR_FILTER_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_BINARY_DIR}/lib
+ ${CMAKE_CURRENT_BINARY_DIR}/include
)
########################################################################
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index a3c83f3dc..4889312da 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -32,7 +32,7 @@ os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
if __name__ == '__main__':
import build_utils
- root, inp = sys.argv[1:3]
+ root, inp = sys.argv[1:3]
for sig in sys.argv[3:]:
name = re.sub ('X+', sig, root)
d = build_utils.standard_dict2(name, sig, 'filter')
@@ -64,19 +64,20 @@ endmacro(expand_h)
########################################################################
# Invoke macro to generate various sources
#######################################################################
-#expand_h(fir_filter_XXX fff ccc ccf fcc fsf scc)
+expand_h(fir_filter_XXX fff ccf ccc)
-#add_custom_target(filter_generated_includes DEPENDS
-# ${generated_includes}
-#)
+add_custom_target(filter_generated_includes DEPENDS
+ ${generated_includes}
+)
########################################################################
# Install header files
########################################################################
install(FILES
api.h
- fir_filter_fff.h
- DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft
+ fir_filter.h
+ ${generated_includes}
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter
COMPONENT "fft_devel"
)
diff --git a/gr-filter/include/filter/fft.h b/gr-filter/include/filter/fft.h
deleted file mode 100644
index 5cc2e21e8..000000000
--- a/gr-filter/include/filter/fft.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2008,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 _FFT_FFT_H_
-#define _FFT_FFT_H_
-
-/*
- * Wrappers for FFTW single precision 1d dft
- */
-
-#include <fft/api.h>
-#include <gr_complex.h>
-#include <boost/thread.hpp>
-
-namespace gr {
- namespace fft {
-
-
- /*! \brief Helper function for allocating complex fft buffers
- */
- gr_complex* malloc_complex(int size);
-
- /*! \brief Helper function for allocating float fft buffers
- */
- float* malloc_float(int size);
-
- /*! \brief Helper function for freeing fft buffers
- */
- void free(void *b);
-
- /*!
- * \brief Export reference to planner mutex for those apps that
- * want to use FFTW w/o using the fft_impl_fftw* classes.
- */
- class FFT_API planner {
- public:
- typedef boost::mutex::scoped_lock scoped_lock;
- /*!
- * Return reference to planner mutex
- */
- static boost::mutex &mutex();
- };
-
- /*!
- * \brief FFT: complex in, complex out
- * \ingroup misc
- */
- class FFT_API fft_complex {
- int d_fft_size;
- int d_nthreads;
- gr_complex *d_inbuf;
- gr_complex *d_outbuf;
- void *d_plan;
-
- public:
- fft_complex(int fft_size, bool forward = true, int nthreads=1);
- virtual ~fft_complex();
-
- /*
- * These return pointers to buffers owned by fft_impl_fft_complex
- * into which input and output take place. It's done this way in
- * order to ensure optimal alignment for SIMD instructions.
- */
- gr_complex *get_inbuf() const { return d_inbuf; }
- gr_complex *get_outbuf() const { return d_outbuf; }
-
- int inbuf_length() const { return d_fft_size; }
- int outbuf_length() const { return d_fft_size; }
-
- /*!
- * Set the number of threads to use for caclulation.
- */
- void set_nthreads(int n);
-
- /*!
- * Get the number of threads being used by FFTW
- */
- int nthreads() const { return d_nthreads; }
-
- /*!
- * compute FFT. The input comes from inbuf, the output is placed in
- * outbuf.
- */
- void execute();
- };
-
- /*!
- * \brief FFT: real in, complex out
- * \ingroup misc
- */
- class FFT_API fft_real_fwd {
- int d_fft_size;
- int d_nthreads;
- float *d_inbuf;
- gr_complex *d_outbuf;
- void *d_plan;
-
- public:
- fft_real_fwd (int fft_size, int nthreads=1);
- virtual ~fft_real_fwd ();
-
- /*
- * These return pointers to buffers owned by fft_impl_fft_real_fwd
- * into which input and output take place. It's done this way in
- * order to ensure optimal alignment for SIMD instructions.
- */
- float *get_inbuf() const { return d_inbuf; }
- gr_complex *get_outbuf() const { return d_outbuf; }
-
- int inbuf_length() const { return d_fft_size; }
- int outbuf_length() const { return d_fft_size / 2 + 1; }
-
- /*!
- * Set the number of threads to use for caclulation.
- */
- void set_nthreads(int n);
-
- /*!
- * Get the number of threads being used by FFTW
- */
- int nthreads() const { return d_nthreads; }
-
- /*!
- * compute FFT. The input comes from inbuf, the output is placed in
- * outbuf.
- */
- void execute();
- };
-
- /*!
- * \brief FFT: complex in, float out
- * \ingroup misc
- */
- class FFT_API fft_real_rev {
- int d_fft_size;
- int d_nthreads;
- gr_complex *d_inbuf;
- float *d_outbuf;
- void *d_plan;
-
- public:
- fft_real_rev(int fft_size, int nthreads=1);
- virtual ~fft_real_rev();
-
- /*
- * These return pointers to buffers owned by fft_impl_fft_real_rev
- * into which input and output take place. It's done this way in
- * order to ensure optimal alignment for SIMD instructions.
- */
- gr_complex *get_inbuf() const { return d_inbuf; }
- float *get_outbuf() const { return d_outbuf; }
-
- int inbuf_length() const { return d_fft_size / 2 + 1; }
- int outbuf_length() const { return d_fft_size; }
-
- /*!
- * Set the number of threads to use for caclulation.
- */
- void set_nthreads(int n);
-
- /*!
- * Get the number of threads being used by FFTW
- */
- int nthreads() const { return d_nthreads; }
-
- /*!
- * compute FFT. The input comes from inbuf, the output is placed in
- * outbuf.
- */
- void execute();
- };
-
- } /* namespace fft */
-} /*namespace gr */
-
-#endif /* _FFT_FFT_H_ */
diff --git a/gr-filter/include/filter/fft_vcc.h b/gr-filter/include/filter/fft_vcc.h
deleted file mode 100644
index 561ae858d..000000000
--- a/gr-filter/include/filter/fft_vcc.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2007,2008,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_FFT_FFT_VCC_H
-#define INCLUDED_FFT_FFT_VCC_H
-
-#include <fft/api.h>
-#include <gr_sync_block.h>
-
-namespace gr {
- namespace fft {
-
- class FFT_API fft_vcc : virtual public gr_sync_block
- {
- public:
-
- // gr::fft::fft_vcc::sptr
- typedef boost::shared_ptr<fft_vcc> sptr;
-
- /*!
- * \brief Compute forward or reverse FFT. complex vector in / complex vector out.
- * \ingroup dft_blk
- */
- static FFT_API sptr make(int fft_size, bool forward,
- const std::vector<float> &window,
- bool shift=false, int nthreads=1);
-
- virtual void set_nthreads(int n) = 0;
-
- virtual int nthreads() const = 0;
-
- virtual bool set_window(const std::vector<float> &window) = 0;
- };
-
- } /* namespace fft */
-} /* namespace gr */
-
-#endif /* INCLUDED_FFT_FFT_VCC_H */
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
new file mode 100644
index 000000000..c307fea46
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter.h
@@ -0,0 +1,112 @@
+/* -*- 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.
+ */
+
+#include <filter/api.h>
+#include <vector>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+ namespace impl {
+
+ class FILTER_API fir_filter_fff
+ {
+ public:
+ fir_filter_fff(int decimation,
+ const std::vector<float> &taps);
+ ~fir_filter_fff();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps() const;
+ unsigned int ntaps() const;
+
+ float filter(const float input[]);
+ void filterN(float output[],
+ const float input[],
+ unsigned long n);
+ void filterNdec(float output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ private:
+ unsigned int d_ntaps;
+ float *d_taps;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_ccf
+ {
+ public:
+ fir_filter_ccf(int decimation,
+ const std::vector<float> &taps);
+ ~fir_filter_ccf();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const gr_complex input[]);
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ private:
+ unsigned int d_ntaps;
+ gr_complex *d_taps;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_ccc
+ {
+ public:
+ fir_filter_ccc(int decimation,
+ const std::vector<gr_complex> &taps);
+ ~fir_filter_ccc();
+
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const gr_complex input[]);
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ private:
+ unsigned int d_ntaps;
+ gr_complex *d_taps;
+ };
+
+ } /* namespace impl */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/include/filter/fir_filter_fff.h b/gr-filter/include/filter/fir_filter_XXX.h.t
index 5b6d19b34..ef6b8bfc9 100644
--- a/gr-filter/include/filter/fir_filter_fff.h
+++ b/gr-filter/include/filter/fir_filter_XXX.h.t
@@ -20,8 +20,10 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef FILTER_FIR_FILTER_FFF_H
-#define FILTER_FIR_FILTER_FFF_H
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
#include <filter/api.h>
#include <gr_sync_decimator.h>
@@ -29,25 +31,25 @@
namespace gr {
namespace filter {
- class FILTER_API fir_filter_fff : virtual public gr_sync_decimator
+ class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator
{
public:
- // gr::filter::fir_filter_fff::sptr
- typedef boost::shared_ptr<fir_filter_fff> sptr;
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
/*!
- * \brief FIR filter with float input, float output, and float taps
+ * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps
* \ingroup filter_blk
*/
static FILTER_API sptr make(int decimation,
- const std::vector<float> &taps);
+ const std::vector<@TAP_TYPE@> &taps);
- virtual void set_taps (const std::vector<float> &taps) = 0;
- virtual std::vector<float> taps () 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 /* FILTER_FIR_FILTER_FFF_H */
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 2850b6925..784a3c109 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -18,6 +18,72 @@
# Boston, MA 02110-1301, USA.
########################################################################
+# generate helper scripts to expand templated files
+########################################################################
+include(GrPython)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "
+#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_CORE_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_impl_dict2(name, sig, 'filter')
+ build_utils.expand_template(d, inp)
+")
+
+macro(expand_cc root)
+ #make a list of all the generated files
+ unset(expanded_files_cc)
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc)
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+
+ #create a command to generate the source files
+ add_custom_command(
+ OUTPUT ${expanded_files_cc}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.cc.t ${ARGN}
+ )
+
+ #create a command to generate the header file
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #make source files depends on headers to force generation
+ set_source_files_properties(${expanded_files_cc}
+ PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
+ )
+
+ #install rules for the generated cc files
+ list(APPEND generated_sources ${expanded_files_cc})
+ list(APPEND generated_headers ${expanded_files_h})
+endmacro(expand_cc)
+
+########################################################################
+# Invoke macro to generate various sources
+########################################################################
+expand_cc(fir_filter_XXX_impl fff ccf ccc)
+
+
+########################################################################
# Setup the include and linker paths
########################################################################
include_directories(
@@ -39,7 +105,8 @@ link_directories(${FFTW3F_LIBRARY_DIRS})
# Setup library
########################################################################
list(APPEND filter_sources
- fir_filter_fff_impl.cc
+ fir_filter.cc
+ ${generated_sources}
)
list(APPEND filter_libs
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
new file mode 100644
index 000000000..5f0e0912d
--- /dev/null
+++ b/gr-filter/lib/fir_filter.cc
@@ -0,0 +1,268 @@
+/* -*- 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.
+ */
+
+#include <filter/fir_filter.h>
+#include <fft/fft.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace filter {
+ namespace impl {
+
+ fir_filter_fff::fir_filter_fff(int decimation,
+ const std::vector<float> &taps)
+ {
+ d_taps = NULL;
+ set_taps(taps);
+ }
+
+ fir_filter_fff::~fir_filter_fff()
+ {
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+ }
+
+ void
+ fir_filter_fff::set_taps(const std::vector<float> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_float(d_ntaps);
+ for(unsigned int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = taps[i];
+ }
+ }
+
+ std::vector<float>
+ fir_filter_fff::taps() const
+ {
+ std::vector<float> t;
+ for(unsigned int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i]);
+ return t;
+ }
+
+ unsigned int
+ fir_filter_fff::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ float
+ fir_filter_fff::filter(const float input[])
+ {
+ float output;
+ volk_32f_x2_dot_prod_32f_u(&output, input, d_taps, d_ntaps);
+ return output;
+ }
+
+ void
+ fir_filter_fff::filterN(float output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_fff::filterNdec(float 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_ccf::fir_filter_ccf(int decimation,
+ const std::vector<float> &taps)
+ {
+ d_taps = NULL;
+ set_taps(taps);
+ }
+
+ fir_filter_ccf::~fir_filter_ccf()
+ {
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+ }
+
+ void
+ fir_filter_ccf::set_taps(const std::vector<float> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_complex(d_ntaps);
+ for(unsigned int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = gr_complex(taps[i],0);
+ }
+ }
+
+ std::vector<float>
+ fir_filter_ccf::taps() const
+ {
+ std::vector<float> t;
+ for(unsigned int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i].real());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_ccf::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_ccf::filter(const gr_complex input[])
+ {
+ gr_complex output;
+ volk_32fc_x2_dot_prod_32fc_u(&output, input, d_taps, d_ntaps);
+ return output;
+ }
+
+ void
+ fir_filter_ccf::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_ccf::filterNdec(gr_complex output[],
+ const gr_complex 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,
+ const std::vector<gr_complex> &taps)
+ {
+ d_taps = NULL;
+ set_taps(taps);
+ }
+
+ fir_filter_ccc::~fir_filter_ccc()
+ {
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+ }
+
+ void
+ fir_filter_ccc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_complex(d_ntaps);
+ for(unsigned int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = taps[i];
+ }
+ }
+
+ std::vector<gr_complex>
+ fir_filter_ccc::taps() const
+ {
+ std::vector<gr_complex> t;
+ for(unsigned int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i]);
+ return t;
+ }
+
+ unsigned int
+ fir_filter_ccc::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_ccc::filter(const gr_complex input[])
+ {
+ gr_complex output;
+ volk_32fc_x2_dot_prod_32fc_u(&output, input, d_taps, d_ntaps);
+ return output;
+ }
+
+ void
+ fir_filter_ccc::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_ccc::filterNdec(gr_complex output[],
+ const gr_complex 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;
+ }
+ }
+
+ } /* namespace impl */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fir_filter_XXX_impl.cc.t b/gr-filter/lib/fir_filter_XXX_impl.cc.t
new file mode 100644
index 000000000..70c3fba3f
--- /dev/null
+++ b/gr-filter/lib/fir_filter_XXX_impl.cc.t
@@ -0,0 +1,98 @@
+/* -*- 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 "@IMPL_NAME@.h"
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+#include <fft/fft.h>
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(int decimation, const std::vector<@TAP_TYPE@> &taps)
+ {
+ return gnuradio::get_initial_sptr(new @IMPL_NAME@
+ (decimation, taps));
+ }
+
+
+ @IMPL_NAME@::@IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps)
+ : gr_sync_decimator("fir_filter_fff",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
+ decimation)
+ {
+ d_fir = new impl::@BASE_NAME@(decimation, taps);
+ d_updated = false;
+ set_history(d_fir->ntaps()+1);
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ delete d_fir;
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_fir->set_taps(taps);
+ d_updated = true;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_fir->taps();
+ }
+
+ int
+ @IMPL_NAME@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@*)output_items[0];
+
+ if (d_updated) {
+ set_history(d_fir->ntaps()+1);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ if (decimation() == 1) {
+ d_fir->filterN(out, in, noutput_items);
+ }
+ else {
+ d_fir->filterNdec(out, in, noutput_items, decimation());
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/fir_filter_fff_impl.h b/gr-filter/lib/fir_filter_XXX_impl.h.t
index 962781466..a40c49bf2 100644
--- a/gr-filter/lib/fir_filter_fff_impl.h
+++ b/gr-filter/lib/fir_filter_XXX_impl.h.t
@@ -20,30 +20,31 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef FILTER_FIR_FILTER_FFF_IMPL_H
-#define FILTER_FIR_FILTER_FFF_IMPL_H
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
#include <filter/api.h>
-#include <filter/fir_filter_fff.h>
+#include <filter/fir_filter.h>
+#include <filter/@BASE_NAME@.h>
namespace gr {
namespace filter {
- class FILTER_API fir_filter_fff_impl : public fir_filter_fff
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
{
private:
- float *d_taps;
- int d_ntaps;
- bool d_updated;
+ impl::@BASE_NAME@ *d_fir;
+ bool d_updated;
public:
- fir_filter_fff_impl(int decimation,
- const std::vector<float> &taps);
+ @IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps);
- ~fir_filter_fff_impl();
+ ~@IMPL_NAME@();
- void set_taps(const std::vector<float> &taps);
- std::vector<float> taps() 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,
@@ -53,4 +54,4 @@ namespace gr {
} /* namespace filter */
} /* namespace gr */
-#endif /* FILTER_FIR_FILTER_FFF_IMPL_H */
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/fir_filter_fff_impl.cc b/gr-filter/lib/fir_filter_fff_impl.cc
deleted file mode 100644
index 15ccb4d07..000000000
--- a/gr-filter/lib/fir_filter_fff_impl.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- 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 "fir_filter_fff_impl.h"
-#include <gr_io_signature.h>
-#include <volk/volk.h>
-#include <fft/fft.h>
-#include <gr_math.h>
-
-namespace gr {
- namespace filter {
-
- fir_filter_fff::sptr
- fir_filter_fff::make(int decimation, const std::vector<float> &taps)
- {
- return gnuradio::get_initial_sptr(new fir_filter_fff_impl
- (decimation, taps));
- }
-
-
- fir_filter_fff_impl::fir_filter_fff_impl(int decimation,
- const std::vector<float> &taps)
- : gr_sync_decimator("fir_filter_fff",
- gr_make_io_signature (1, 1, sizeof(float)),
- gr_make_io_signature (1, 1, sizeof(float)),
- decimation)
- {
- d_taps = NULL;
- set_taps(taps);
- d_updated = false;
- set_history(d_ntaps+1);
- }
-
- fir_filter_fff_impl::~fir_filter_fff_impl()
- {
- if(d_taps != NULL) {
- fft::free(d_taps);
- d_taps = NULL;
- }
- }
-
- void
- fir_filter_fff_impl::set_taps(const std::vector<float> &taps)
- {
- // Free the taps if already allocated
- if(d_taps != NULL) {
- fft::free(d_taps);
- d_taps = NULL;
- }
-
- d_ntaps = (int)taps.size();
- d_taps = fft::malloc_float(d_ntaps);
- for(int i = 0; i < d_ntaps; i++) {
- d_taps[i] = taps[i];
- }
- d_updated = true;
- }
-
- std::vector<float>
- fir_filter_fff_impl::taps() const
- {
- std::vector<float> t;
- for(int i = 0; i < d_ntaps; i++)
- t.push_back(d_taps[i]);
- return t;
- }
-
- int
- fir_filter_fff_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];
-
- if (d_updated) {
- set_history((unsigned int)d_ntaps+1);
- d_updated = false;
- return 0; // history requirements may have changed.
- }
-
- if (decimation() == 1) {
- for(int i = 0; i < noutput_items; i++) {
- volk_32f_x2_dot_prod_32f_u(&out[i], &in[i], d_taps, d_ntaps);
- }
- }
- else {
- int j = 0;
- for(int i = 0; i < noutput_items; i++) {
- volk_32f_x2_dot_prod_32f_u(&out[i], &in[j], d_taps, d_ntaps);
- j += decimation();
- }
- }
-
- return noutput_items;
- }
-
- } /* namespace filter */
-} /* namespace gr */
-
diff --git a/gr-filter/python/qa_fir_filter.py b/gr-filter/python/qa_fir_filter.py
index 928f17aa3..2c88e7830 100755
--- a/gr-filter/python/qa_fir_filter.py
+++ b/gr-filter/python/qa_fir_filter.py
@@ -41,6 +41,28 @@ class test_filter(gr_unittest.TestCase):
result_data = dst.data()
self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5)
+ def test_fir_filter_ccf_001(self):
+ src_data = [1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = [0+0j, 0.5+0.5j, 1.5+1.5j, 2.5+2.5j]
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccf(1, [0.5, 0.5])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccc_001(self):
+ src_data = [1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = [0+0j, -0.5+1.5j, -1.5+4.5j, -2.5+7.5j]
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccc(1, [0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
if __name__ == '__main__':
gr_unittest.run(test_filter, "test_filter.xml")
diff --git a/gr-filter/swig/CMakeLists.txt b/gr-filter/swig/CMakeLists.txt
index 5dff9f631..3eee3a1ee 100644
--- a/gr-filter/swig/CMakeLists.txt
+++ b/gr-filter/swig/CMakeLists.txt
@@ -24,7 +24,7 @@ include(GrPython)
include(GrSwig)
set(GR_SWIG_INCLUDE_DIRS
- ${FILTER_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
${FFT_INCLUDE_DIRS}
${FFTW3F_INCLUDE_DIRS}
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index 55ee3c56c..28268528a 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -29,8 +29,14 @@
%{
#include "filter/fir_filter_fff.h"
+#include "filter/fir_filter_ccf.h"
+#include "filter/fir_filter_ccc.h"
%}
%include "filter/fir_filter_fff.h"
+%include "filter/fir_filter_ccf.h"
+%include "filter/fir_filter_ccc.h"
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccc);