diff options
-rw-r--r-- | gnuradio-core/src/python/build_utils.py | 32 | ||||
-rw-r--r-- | gr-filter/CMakeLists.txt | 4 | ||||
-rw-r--r-- | gr-filter/include/filter/CMakeLists.txt | 15 | ||||
-rw-r--r-- | gr-filter/include/filter/fft.h | 195 | ||||
-rw-r--r-- | gr-filter/include/filter/fft_vcc.h | 57 | ||||
-rw-r--r-- | gr-filter/include/filter/fir_filter.h | 112 | ||||
-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.txt | 69 | ||||
-rw-r--r-- | gr-filter/lib/fir_filter.cc | 268 | ||||
-rw-r--r-- | gr-filter/lib/fir_filter_XXX_impl.cc.t | 98 | ||||
-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.cc | 123 | ||||
-rwxr-xr-x | gr-filter/python/qa_fir_filter.py | 22 | ||||
-rw-r--r-- | gr-filter/swig/CMakeLists.txt | 2 | ||||
-rw-r--r-- | gr-filter/swig/filter_swig.i | 6 |
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); |