diff options
38 files changed, 753 insertions, 87 deletions
diff --git a/cmake/Modules/FindFFTW3f.cmake b/cmake/Modules/FindFFTW3f.cmake index 078108958..ec6629f3a 100644 --- a/cmake/Modules/FindFFTW3f.cmake +++ b/cmake/Modules/FindFFTW3f.cmake @@ -22,8 +22,20 @@ FIND_LIBRARY( ${PC_FFTW3F_LIBDIR} PATHS /usr/local/lib /usr/lib + /usr/lib64 ) +FIND_LIBRARY( + FFTW3F_THREADS_LIBRARIES + NAMES fftw3f_threads libfftw3f_threads + HINTS $ENV{FFTW3_DIR}/lib + ${PC_FFTW3F_LIBDIR} + PATHS /usr/local/lib + /usr/lib + /usr/lib64 +) + + INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFTW3F DEFAULT_MSG FFTW3F_LIBRARIES FFTW3F_INCLUDE_DIRS) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFTW3F DEFAULT_MSG FFTW3F_LIBRARIES FFTW3F_INCLUDE_DIRS FFTW3F_THREADS_LIBRARIES) MARK_AS_ADVANCED(FFTW3F_LIBRARIES FFTW3F_INCLUDE_DIRS) diff --git a/gnuradio-core/src/lib/CMakeLists.txt b/gnuradio-core/src/lib/CMakeLists.txt index 52339fc6c..3fbe8f807 100644 --- a/gnuradio-core/src/lib/CMakeLists.txt +++ b/gnuradio-core/src/lib/CMakeLists.txt @@ -63,6 +63,11 @@ list(APPEND gnuradio_core_libs ${FFTW3F_LIBRARIES} ) +if(FFTW3F_THREADS_LIBRARIES) + list(APPEND gnuradio_core_libs ${FFTW3F_THREADS_LIBRARIES} ) + add_definitions("-DFFTW3F_THREADS") +endif() + #need to link with librt on ubuntu 11.10 for shm_* if(LINUX) list(APPEND gnuradio_core_libs rt) diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc index 9fa98cc69..63b52411e 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc @@ -43,13 +43,17 @@ #include <iostream> #include <string.h> -gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps) +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) { - return gnuradio::get_initial_sptr(new gr_fft_filter_ccc (decimation, taps)); + return gnuradio::get_initial_sptr(new gr_fft_filter_ccc (decimation, taps, nthreads)); } -gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps) +gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) : gr_sync_decimator ("fft_filter_ccc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature (1, 1, sizeof (gr_complex)), @@ -58,7 +62,7 @@ gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_compl { set_history(1); #if 1 // don't enable the sse version until handling it is worked out - d_filter = new gri_fft_filter_ccc_generic(decimation, taps); + d_filter = new gri_fft_filter_ccc_generic(decimation, taps, nthreads); #else d_filter = new gri_fft_filter_ccc_sse(decimation, taps); #endif @@ -85,6 +89,23 @@ gr_fft_filter_ccc::taps () const return d_new_taps; } +void +gr_fft_filter_ccc::set_nthreads(int n) +{ + if(d_filter) + d_filter->set_nthreads(n); +} + +int +gr_fft_filter_ccc::nthreads() const +{ + if(d_filter) + return d_filter->nthreads(); + else + return 0; +} + + int gr_fft_filter_ccc::work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h index 1b72a1c00..d037597e8 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h @@ -27,7 +27,9 @@ class gr_fft_filter_ccc; typedef boost::shared_ptr<gr_fft_filter_ccc> gr_fft_filter_ccc_sptr; -GR_CORE_API gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); +GR_CORE_API gr_fft_filter_ccc_sptr +gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); //class gri_fft_filter_ccc_sse; class gri_fft_filter_ccc_generic; @@ -39,7 +41,9 @@ class gri_fft_filter_ccc_generic; class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator { private: - friend GR_CORE_API gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + friend GR_CORE_API gr_fft_filter_ccc_sptr + gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads); int d_nsamples; bool d_updated; @@ -55,8 +59,10 @@ class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator * * \param decimation >= 1 * \param taps complex filter taps + * \param nthreads number of threads for the FFT to use */ - gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); public: ~gr_fft_filter_ccc (); @@ -64,6 +70,16 @@ class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator void set_taps (const std::vector<gr_complex> &taps); std::vector<gr_complex> taps () const; + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i index 812920d8b..acdc347a6 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i @@ -24,17 +24,23 @@ GR_SWIG_BLOCK_MAGIC(gr,fft_filter_ccc) gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, - const std::vector<gr_complex> &taps + const std::vector<gr_complex> &taps, + int nthreads=1 ) throw (std::invalid_argument); class gr_fft_filter_ccc : public gr_sync_decimator { private: - gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); public: ~gr_fft_filter_ccc (); void set_taps (const std::vector<gr_complex> &taps); std::vector<gr_complex> taps () const; + + void set_nthreads(int n); + int nthreads() const; + }; diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc index c0a9b3483..0e4072f63 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc @@ -35,13 +35,17 @@ #include <iostream> #include <string.h> -gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps) +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads) { - return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps)); + return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps, nthreads)); } -gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> &taps) +gr_fft_filter_fff::gr_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads) : gr_sync_decimator ("fft_filter_fff", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (1, 1, sizeof (float)), @@ -51,7 +55,7 @@ gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> & set_history(1); #if 1 // don't enable the sse version until handling it is worked out - d_filter = new gri_fft_filter_fff_generic(decimation, taps); + d_filter = new gri_fft_filter_fff_generic(decimation, taps, nthreads); #else d_filter = new gri_fft_filter_fff_sse(decimation, taps); #endif @@ -78,6 +82,22 @@ gr_fft_filter_fff::taps () const return d_new_taps; } +void +gr_fft_filter_fff::set_nthreads(int n) +{ + if(d_filter) + d_filter->set_nthreads(n); +} + +int +gr_fft_filter_fff::nthreads() const +{ + if(d_filter) + return d_filter->nthreads(); + else + return 0; +} + int gr_fft_filter_fff::work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h index ddd8dcac2..2eeb8c646 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h @@ -27,7 +27,9 @@ class gr_fft_filter_fff; typedef boost::shared_ptr<gr_fft_filter_fff> gr_fft_filter_fff_sptr; -GR_CORE_API gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps); +GR_CORE_API gr_fft_filter_fff_sptr +gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); class gri_fft_filter_fff_generic; //class gri_fft_filter_fff_sse; @@ -39,7 +41,9 @@ class gri_fft_filter_fff_generic; class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator { private: - friend GR_CORE_API gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps); + friend GR_CORE_API gr_fft_filter_fff_sptr + gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads); int d_nsamples; bool d_updated; @@ -55,15 +59,27 @@ class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator * * \param decimation >= 1 * \param taps float filter taps + * \param nthreads number of threads for the FFT to use */ - gr_fft_filter_fff (int decimation, const std::vector<float> &taps); - + gr_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); + public: ~gr_fft_filter_fff (); void set_taps (const std::vector<float> &taps); std::vector<float> taps () const; + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i index 7e2cde977..c8118e09e 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i @@ -24,17 +24,22 @@ GR_SWIG_BLOCK_MAGIC(gr,fft_filter_fff) gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, - const std::vector<float> &taps + const std::vector<float> &taps, + int nthreads=1 ) throw (std::invalid_argument); class gr_fft_filter_fff : public gr_sync_decimator { private: - gr_fft_filter_fff (int decimation, const std::vector<float> &taps); + gr_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); public: ~gr_fft_filter_fff (); void set_taps (const std::vector<float> &taps); std::vector<float> taps () const; + void set_nthreads(int n); + int nthreads() const; + }; diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc index 891905dd0..47e18b3e3 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc @@ -33,8 +33,9 @@ #include <fftw3.h> gri_fft_filter_ccc_generic::gri_fft_filter_ccc_generic (int decimation, - const std::vector<gr_complex> &taps) - : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0) + const std::vector<gr_complex> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0), d_nthreads(nthreads) { set_taps(taps); } @@ -111,12 +112,28 @@ gri_fft_filter_ccc_generic::compute_sizes(int ntaps) if (d_fftsize != old_fftsize){ // compute new plans delete d_fwdfft; delete d_invfft; - d_fwdfft = new gri_fft_complex(d_fftsize, true); - d_invfft = new gri_fft_complex(d_fftsize, false); + d_fwdfft = new gri_fft_complex(d_fftsize, true, d_nthreads); + d_invfft = new gri_fft_complex(d_fftsize, false, d_nthreads); d_xformed_taps.resize(d_fftsize); } } +void +gri_fft_filter_ccc_generic::set_nthreads(int n) +{ + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); +} + +int +gri_fft_filter_ccc_generic::nthreads() const +{ + return d_nthreads; +} + int gri_fft_filter_ccc_generic::filter (int nitems, const gr_complex *input, gr_complex *output) { diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h index 4db7ba50f..217b9ab83 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h @@ -42,6 +42,7 @@ class GR_CORE_API gri_fft_filter_ccc_generic int d_decimation; gri_fft_complex *d_fwdfft; // forward "plan" gri_fft_complex *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add std::vector<gr_complex> d_xformed_taps; // Fourier xformed taps std::vector<gr_complex> d_new_taps; @@ -57,8 +58,10 @@ class GR_CORE_API gri_fft_filter_ccc_generic * in other blocks for complex vectors (such as gr_fft_filter_ccc). * \param decimation The decimation rate of the filter (int) * \param taps The filter taps (complex) + * \param nthreads The number of threads for the FFT to use (int) */ - gri_fft_filter_ccc_generic (int decimation, const std::vector<gr_complex> &taps); + gri_fft_filter_ccc_generic (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); ~gri_fft_filter_ccc_generic (); /*! @@ -68,6 +71,16 @@ class GR_CORE_API gri_fft_filter_ccc_generic * \param taps The filter taps (complex) */ int set_taps (const std::vector<gr_complex> &taps); + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; /*! * \brief Perform the filter operation diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc index b3fbe1d1a..598bf268c 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc @@ -32,8 +32,9 @@ #include <cstring> gri_fft_filter_fff_generic::gri_fft_filter_fff_generic (int decimation, - const std::vector<float> &taps) - : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0) + const std::vector<float> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0), d_nthreads(nthreads) { set_taps(taps); } @@ -104,6 +105,22 @@ gri_fft_filter_fff_generic::compute_sizes(int ntaps) } } +void +gri_fft_filter_fff_generic::set_nthreads(int n) +{ + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); +} + +int +gri_fft_filter_fff_generic::nthreads() const +{ + return d_nthreads; +} + int gri_fft_filter_fff_generic::filter (int nitems, const float *input, float *output) { diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h index 86658043a..be31068aa 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h @@ -39,6 +39,7 @@ class GR_CORE_API gri_fft_filter_fff_generic int d_decimation; gri_fft_real_fwd *d_fwdfft; // forward "plan" gri_fft_real_rev *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use std::vector<float> d_tail; // state carried between blocks for overlap-add std::vector<gr_complex> d_xformed_taps; // Fourier xformed taps std::vector<float> d_new_taps; @@ -55,8 +56,10 @@ class GR_CORE_API gri_fft_filter_fff_generic * in other blocks for floating point vectors (such as gr_fft_filter_fff). * \param decimation The decimation rate of the filter (int) * \param taps The filter taps (float) + * \param nthreads The number of threads for the FFT to use (int) */ - gri_fft_filter_fff_generic (int decimation, const std::vector<float> &taps); + gri_fft_filter_fff_generic (int decimation, const std::vector<float> &taps, + int nthreads=1); ~gri_fft_filter_fff_generic (); /*! @@ -68,6 +71,16 @@ class GR_CORE_API gri_fft_filter_fff_generic int set_taps (const std::vector<float> &taps); /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + /*! * \brief Perform the filter operation * * \param nitems The number of items to produce diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.cc b/gnuradio-core/src/lib/general/gr_burst_tagger.cc index 4b3847b08..bd713d663 100644 --- a/gnuradio-core/src/lib/general/gr_burst_tagger.cc +++ b/gnuradio-core/src/lib/general/gr_burst_tagger.cc @@ -43,10 +43,39 @@ gr_burst_tagger::gr_burst_tagger(size_t itemsize) std::stringstream str; str << name() << unique_id(); - d_key = pmt::pmt_string_to_symbol("burst"); + d_true_key = pmt::pmt_string_to_symbol("burst"); + d_true_value = pmt::PMT_T; + + d_false_key = pmt::pmt_string_to_symbol("burst"); + d_false_value = pmt::PMT_F; + d_id = pmt::pmt_string_to_symbol(str.str()); } +void +gr_burst_tagger::set_true_tag (const std::string &key, bool value) +{ + d_true_key = pmt::pmt_string_to_symbol(key); + if(value == true) { + d_true_value = pmt::PMT_T; + } + else { + d_true_value = pmt::PMT_F; + } +} + +void +gr_burst_tagger::set_false_tag (const std::string &key, bool value) +{ + d_false_key = pmt::pmt_string_to_symbol(key); + if(value == true) { + d_false_value = pmt::PMT_T; + } + else { + d_false_value = pmt::PMT_F; + } +} + gr_burst_tagger::~gr_burst_tagger() { } @@ -66,18 +95,15 @@ gr_burst_tagger::work(int noutput_items, if(trigger[i] > 0) { if(d_state == false) { d_state = true; - pmt::pmt_t value = pmt::PMT_T; - add_item_tag(0, nitems_written(0)+i, d_key, value, d_id); + add_item_tag(0, nitems_written(0)+i, d_true_key, d_true_value, d_id); } } else { if(d_state == true) { d_state = false; - pmt::pmt_t value = pmt::PMT_F; - add_item_tag(0, nitems_written(0)+i, d_key, value, d_id); + add_item_tag(0, nitems_written(0)+i, d_false_key, d_false_value, d_id); } } } - return noutput_items; } diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.h b/gnuradio-core/src/lib/general/gr_burst_tagger.h index 7547ba9cc..663a146f2 100644 --- a/gnuradio-core/src/lib/general/gr_burst_tagger.h +++ b/gnuradio-core/src/lib/general/gr_burst_tagger.h @@ -40,14 +40,21 @@ class GR_CORE_API gr_burst_tagger : public gr_sync_block { size_t d_itemsize; bool d_state; - pmt::pmt_t d_key; + pmt::pmt_t d_true_key; + pmt::pmt_t d_true_value; + + pmt::pmt_t d_false_key; + pmt::pmt_t d_false_value; + pmt::pmt_t d_id; - + friend GR_CORE_API gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize); gr_burst_tagger(size_t itemsize); public: ~gr_burst_tagger(); + void set_true_tag (const std::string &key, bool value); + void set_false_tag (const std::string &key, bool value); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.i b/gnuradio-core/src/lib/general/gr_burst_tagger.i index ebf1eea8c..868941fc6 100644 --- a/gnuradio-core/src/lib/general/gr_burst_tagger.i +++ b/gnuradio-core/src/lib/general/gr_burst_tagger.i @@ -28,4 +28,8 @@ class gr_burst_tagger : public gr_sync_block { private: gr_burst_tagger(size_t itemsize); + + public: + void set_true_tag(const std::string &key, bool value); + void set_false_tag(const std::string &key, bool value); }; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.cc b/gnuradio-core/src/lib/general/gr_fft_vcc.cc index d07f6fa07..64dda2491 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.cc +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.cc @@ -32,9 +32,12 @@ #include <string.h> gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward,const std::vector<float> &window, bool shift) +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) { - return gr_make_fft_vcc_fftw(fft_size, forward, window, shift); + return gr_make_fft_vcc_fftw(fft_size, forward, + window, shift, nthreads); } gr_fft_vcc::gr_fft_vcc (const std::string &name, @@ -62,3 +65,16 @@ gr_fft_vcc::set_window(const std::vector<float> &window) else return false; } + +void +gr_fft_vcc::set_nthreads(int n) +{ + throw std::runtime_error("gr_fft_vcc::set_nthreads not implemented."); +} + +int +gr_fft_vcc::nthreads() const +{ + throw std::runtime_error("gr_fft_vcc::nthreads not implemented."); + return 0; +} diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.h b/gnuradio-core/src/lib/general/gr_fft_vcc.h index a7c8e1162..6c3985987 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.h +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.h @@ -30,7 +30,9 @@ class gr_fft_vcc; typedef boost::shared_ptr<gr_fft_vcc> gr_fft_vcc_sptr; GR_CORE_API gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift=false); +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); /*! * \brief Compute forward or reverse FFT. complex vector in / complex vector out. @@ -42,7 +44,9 @@ class GR_CORE_API gr_fft_vcc : public gr_sync_block { protected: friend GR_CORE_API gr_fft_vcc_sptr - gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift); unsigned int d_fft_size; std::vector<float> d_window; @@ -55,6 +59,9 @@ protected: public: ~gr_fft_vcc (); + virtual void set_nthreads(int n); + virtual int nthreads() const; + bool set_window(const std::vector<float> &window); }; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.i b/gnuradio-core/src/lib/general/gr_fft_vcc.i index f35316e70..0dc5353b2 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.i +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.i @@ -23,13 +23,19 @@ GR_SWIG_BLOCK_MAGIC(gr, fft_vcc) gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift=false); +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); class gr_fft_vcc : public gr_sync_block { protected: - gr_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift); public: bool set_window(const std::vector<float> &window); + void set_nthreads(int n); + int nthreads() const; }; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc index 948ab20b9..e6032ad9e 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc +++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc @@ -31,16 +31,21 @@ #include <string.h> gr_fft_vcc_sptr -gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift) +gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) { - return gnuradio::get_initial_sptr(new gr_fft_vcc_fftw (fft_size, forward, window, shift)); + return gnuradio::get_initial_sptr(new gr_fft_vcc_fftw + (fft_size, forward, window, + shift, nthreads)); } gr_fft_vcc_fftw::gr_fft_vcc_fftw (int fft_size, bool forward, - const std::vector<float> &window, bool shift) + const std::vector<float> &window, + bool shift, int nthreads) : gr_fft_vcc("fft_vcc_fftw", fft_size, forward, window, shift) { - d_fft = new gri_fft_complex (d_fft_size, forward); + d_fft = new gri_fft_complex (d_fft_size, forward, nthreads); } gr_fft_vcc_fftw::~gr_fft_vcc_fftw () @@ -48,6 +53,18 @@ gr_fft_vcc_fftw::~gr_fft_vcc_fftw () delete d_fft; } +void +gr_fft_vcc_fftw::set_nthreads(int n) +{ + d_fft->set_nthreads(n); +} + +int +gr_fft_vcc_fftw::nthreads() const +{ + return d_fft->nthreads(); +} + int gr_fft_vcc_fftw::work (int noutput_items, gr_vector_const_void_star &input_items, @@ -70,7 +87,7 @@ gr_fft_vcc_fftw::work (int noutput_items, if(!d_forward && d_shift){ int offset = (!d_forward && d_shift)?(d_fft_size/2):0; int fft_m_offset = d_fft_size - offset; - for (unsigned int i = 0; i < offset; i++) // apply window + for (int i = 0; i < offset; i++) // apply window dst[i+fft_m_offset] = in[i] * d_window[i]; for (unsigned int i = offset; i < d_fft_size; i++) // apply window dst[i-offset] = in[i] * d_window[i]; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h index 8535d133c..82b7512d7 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h +++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h @@ -29,7 +29,9 @@ class gri_fft_complex; GR_CORE_API gr_fft_vcc_sptr -gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift=false); +gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); /*! * \brief Compute forward or reverse FFT. complex vector in / complex vector out. @@ -40,15 +42,22 @@ gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &wind class GR_CORE_API gr_fft_vcc_fftw : public gr_fft_vcc { friend GR_CORE_API gr_fft_vcc_sptr - gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads); gri_fft_complex *d_fft; - gr_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads=1); public: ~gr_fft_vcc_fftw (); + void set_nthreads(int n); + int nthreads() const; + int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gnuradio-core/src/lib/general/gri_fft.cc b/gnuradio-core/src/lib/general/gri_fft.cc index 0df1af25d..63e307776 100644 --- a/gnuradio-core/src/lib/general/gri_fft.cc +++ b/gnuradio-core/src/lib/general/gri_fft.cc @@ -78,6 +78,22 @@ gri_fftw_import_wisdom () } static void +gri_fftw_config_threading (int nthreads) +{ + static int fftw_threads_inited = 0; + +#ifdef FFTW3F_THREADS + if (fftw_threads_inited == 0) + { + fftw_threads_inited = 1; + fftwf_init_threads(); + } + + fftwf_plan_with_nthreads(nthreads); +#endif +} + +static void gri_fftw_export_wisdom () { const char *filename = wisdom_filename (); @@ -94,7 +110,7 @@ gri_fftw_export_wisdom () // ---------------------------------------------------------------- -gri_fft_complex::gri_fft_complex (int fft_size, bool forward) +gri_fft_complex::gri_fft_complex (int fft_size, bool forward, int nthreads) { // Hold global mutex during plan construction and destruction. gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); @@ -115,7 +131,10 @@ gri_fft_complex::gri_fft_complex (int fft_size, bool forward) throw std::runtime_error ("fftwf_malloc"); } + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_1d (fft_size, reinterpret_cast<fftwf_complex *>(d_inbuf), reinterpret_cast<fftwf_complex *>(d_outbuf), @@ -139,6 +158,18 @@ gri_fft_complex::~gri_fft_complex () fftwf_free (d_outbuf); } +void +gri_fft_complex::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + void gri_fft_complex::execute () { @@ -147,7 +178,7 @@ gri_fft_complex::execute () // ---------------------------------------------------------------- -gri_fft_real_fwd::gri_fft_real_fwd (int fft_size) +gri_fft_real_fwd::gri_fft_real_fwd (int fft_size, int nthreads) { // Hold global mutex during plan construction and destruction. gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); @@ -168,7 +199,10 @@ gri_fft_real_fwd::gri_fft_real_fwd (int fft_size) throw std::runtime_error ("fftwf_malloc"); } + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_r2c_1d (fft_size, d_inbuf, reinterpret_cast<fftwf_complex *>(d_outbuf), @@ -191,6 +225,18 @@ gri_fft_real_fwd::~gri_fft_real_fwd () fftwf_free (d_outbuf); } +void +gri_fft_real_fwd::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + void gri_fft_real_fwd::execute () { @@ -199,7 +245,7 @@ gri_fft_real_fwd::execute () // ---------------------------------------------------------------- -gri_fft_real_rev::gri_fft_real_rev (int fft_size) +gri_fft_real_rev::gri_fft_real_rev (int fft_size, int nthreads) { // Hold global mutex during plan construction and destruction. gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); @@ -220,11 +266,13 @@ gri_fft_real_rev::gri_fft_real_rev (int fft_size) throw std::runtime_error ("fftwf_malloc"); } + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); + gri_fftw_import_wisdom (); // load prior wisdom from disk + // FIXME If there's ever a chance that the planning functions // will be called in multiple threads, we've got to ensure single // threaded access. They are not thread-safe. - - gri_fftw_import_wisdom (); // load prior wisdom from disk d_plan = fftwf_plan_dft_c2r_1d (fft_size, reinterpret_cast<fftwf_complex *>(d_inbuf), d_outbuf, @@ -244,6 +292,18 @@ gri_fft_real_rev::~gri_fft_real_rev () fftwf_free (d_outbuf); } +void +gri_fft_real_rev::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + void gri_fft_real_rev::execute () { diff --git a/gnuradio-core/src/lib/general/gri_fft.h b/gnuradio-core/src/lib/general/gri_fft.h index 91a82fb55..ed80badf1 100644 --- a/gnuradio-core/src/lib/general/gri_fft.h +++ b/gnuradio-core/src/lib/general/gri_fft.h @@ -49,12 +49,13 @@ public: */ class GR_CORE_API gri_fft_complex { int d_fft_size; + int d_nthreads; gr_complex *d_inbuf; gr_complex *d_outbuf; void *d_plan; public: - gri_fft_complex (int fft_size, bool forward = true); + gri_fft_complex (int fft_size, bool forward = true, int nthreads=1); virtual ~gri_fft_complex (); /* @@ -69,6 +70,16 @@ public: 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 (); @@ -80,12 +91,13 @@ public: */ class GR_CORE_API gri_fft_real_fwd { int d_fft_size; + int d_nthreads; float *d_inbuf; gr_complex *d_outbuf; void *d_plan; public: - gri_fft_real_fwd (int fft_size); + gri_fft_real_fwd (int fft_size, int nthreads=1); virtual ~gri_fft_real_fwd (); /* @@ -100,6 +112,16 @@ public: 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 (); @@ -111,12 +133,13 @@ public: */ class GR_CORE_API gri_fft_real_rev { int d_fft_size; + int d_nthreads; gr_complex *d_inbuf; float *d_outbuf; void *d_plan; public: - gri_fft_real_rev (int fft_size); + gri_fft_real_rev (int fft_size, int nthreads=1); virtual ~gri_fft_real_rev (); /* @@ -131,6 +154,16 @@ public: 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 (); diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft.py index 98d80fbb0..e90eb2e7f 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_fft.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft.py @@ -152,6 +152,60 @@ class test_fft(gr_unittest.TestCase): #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) self.assert_fft_ok2(expected_result, result_data) + def test_003(self): + # Same test as above, only use 2 threads + + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + nthreads = 2 + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + fft = gr.fft_vcc(fft_size, False, [], False, nthreads) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, fft, v2s, dst) + tb.run() + result_data = dst.data() + self.assert_fft_ok2(expected_result, result_data) if __name__ == '__main__': gr_unittest.run(test_fft, "test_fft.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py index 325495c1d..1e9fdb6a8 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py @@ -110,6 +110,23 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccc_002(self): + # Test nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps, nthreads) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_ccc_003(self): tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (2,) @@ -124,6 +141,7 @@ class test_fft_filter(gr_unittest.TestCase): #print 'results: ', result_data self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + def test_ccc_004(self): random.seed(0) for i in xrange(25): @@ -167,6 +185,30 @@ class test_fft_filter(gr_unittest.TestCase): self.assert_fft_ok2(expected_result, result_data) + def test_ccc_006(self): + # Test decimating with nthreads=2 + random.seed(0) + nthreads = 2 + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(dec, taps, nthreads) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + del tb + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + # ---------------------------------------------------------------- # test _fff version # ---------------------------------------------------------------- @@ -202,7 +244,22 @@ class test_fft_filter(gr_unittest.TestCase): #print 'results: ', result_data self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) - def xtest_fff_003(self): + def test_fff_003(self): + # Test 02 with nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps, nthreads) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def xtest_fff_004(self): random.seed(0) for i in xrange(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) @@ -232,7 +289,7 @@ class test_fft_filter(gr_unittest.TestCase): actual.write(`x` + '\n') raise - def xtest_fff_004(self): + def xtest_fff_005(self): random.seed(0) for i in xrange(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) @@ -252,7 +309,7 @@ class test_fft_filter(gr_unittest.TestCase): self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0) - def xtest_fff_005(self): + def xtest_fff_006(self): random.seed(0) for i in xrange(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) @@ -273,6 +330,29 @@ class test_fft_filter(gr_unittest.TestCase): self.assert_fft_float_ok2(expected_result, result_data) + def xtest_fff_007(self): + # test decimation with nthreads + random.seed(0) + nthreads = 2 + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(dec, taps, nthreads) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + def test_fff_get0(self): random.seed(0) for i in xrange(25): diff --git a/gr-digital/include/digital_mpsk_receiver_cc.h b/gr-digital/include/digital_mpsk_receiver_cc.h index e70495bfa..02cea8d25 100644 --- a/gr-digital/include/digital_mpsk_receiver_cc.h +++ b/gr-digital/include/digital_mpsk_receiver_cc.h @@ -91,23 +91,37 @@ class DIGITAL_API digital_mpsk_receiver_cc : public gr_block, public gri_control gr_vector_void_star &output_items); - // Member functions related to the symbol tracking portion of the receiver - //! (M&M) Returns current value of mu - float mu() const { return d_mu;} + //! Returns the modulation order (M) currently set + float modulation_order() const { return d_M; } - //! (M&M) Returns current value of omega - float omega() const { return d_omega;} + //! Returns current value of theta + float theta() const { return d_theta; } - //! (M&M) Returns mu gain factor - float gain_mu() const { return d_gain_mu;} + //! Returns current value of mu + float mu() const { return d_mu; } - //! (M&M) Returns omega gain factor - float gain_omega() const { return d_gain_omega;} + //! Returns current value of omega + float omega() const { return d_omega; } - //! (M&M) Sets value of mu + //! Returns mu gain factor + float gain_mu() const { return d_gain_mu; } + + //! Returns omega gain factor + float gain_omega() const { return d_gain_omega; } + + //! Returns the relative omega limit + float gain_omega_rel() const {return d_omega_rel; } + + //! Sets the modulation order (M) currently + void set_modulation_order(unsigned int M); + + //! Sets value of theta + void set_theta(float theta) { d_theta = theta; } + + //! Sets value of mu void set_mu (float mu) { d_mu = mu; } - //! (M&M) Sets value of omega and its min and max values + //! Sets value of omega and its min and max values void set_omega (float omega) { d_omega = omega; d_min_omega = omega*(1.0 - d_omega_rel); @@ -115,12 +129,15 @@ class DIGITAL_API digital_mpsk_receiver_cc : public gr_block, public gri_control d_omega_mid = 0.5*(d_min_omega+d_max_omega); } - //! (M&M) Sets value for mu gain factor + //! Sets value for mu gain factor void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } - //! (M&M) Sets value for omega gain factor + //! Sets value for omega gain factor void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + //! Sets the relative omega limit and resets omega min/max values + void set_gain_omega_rel(float omega_rel); + protected: /*! diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.cc b/gr-digital/lib/digital_mpsk_receiver_cc.cc index 363b86c9f..6d2bab8a4 100644 --- a/gr-digital/lib/digital_mpsk_receiver_cc.cc +++ b/gr-digital/lib/digital_mpsk_receiver_cc.cc @@ -85,7 +85,18 @@ digital_mpsk_receiver_cc::digital_mpsk_receiver_cc (unsigned int M, float theta, // zero double length delay line. for (unsigned int i = 0; i < 2 * DLLEN; i++) d_dl[i] = gr_complex(0.0,0.0); + + set_modulation_order(d_M); +} + +digital_mpsk_receiver_cc::~digital_mpsk_receiver_cc () +{ + delete d_interp; +} +void +digital_mpsk_receiver_cc::set_modulation_order(unsigned int M) +{ // build the constellation vector from M make_constellation(); @@ -108,9 +119,11 @@ digital_mpsk_receiver_cc::digital_mpsk_receiver_cc (unsigned int M, float theta, } } -digital_mpsk_receiver_cc::~digital_mpsk_receiver_cc () +void +digital_mpsk_receiver_cc::set_gain_omega_rel(float omega_rel) { - delete d_interp; + d_omega_rel = omega_rel; + set_omega(d_omega); } void diff --git a/gr-digital/swig/digital_mpsk_receiver_cc.i b/gr-digital/swig/digital_mpsk_receiver_cc.i index b51411f6f..2338a1854 100644 --- a/gr-digital/swig/digital_mpsk_receiver_cc.i +++ b/gr-digital/swig/digital_mpsk_receiver_cc.i @@ -37,16 +37,21 @@ class digital_mpsk_receiver_cc : public gr_block, public gri_control_loop float mu, float gain_mu, float omega, float gain_omega, float omega_rel); public: + float modulation_order() const { return d_M; } float mu() const { return d_mu;} float omega() const { return d_omega;} float gain_mu() const { return d_gain_mu;} float gain_omega() const { return d_gain_omega;} + float gain_omega_rel() const {return d_omega_rel; } + void set_modulation_order(unsigned int M); void set_mu (float mu) { d_mu = mu; } void set_omega (float omega) { d_omega = omega; d_min_omega = omega*(1.0 - d_omega_rel); d_max_omega = omega*(1.0 + d_omega_rel); } + void set_theta(float theta) { d_theta = theta; } void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_gain_omega_rel(float omega_rel); }; diff --git a/gr-howto-write-a-block/version.sh b/gr-howto-write-a-block/version.sh index 58ec712f6..88a3de947 100644 --- a/gr-howto-write-a-block/version.sh +++ b/gr-howto-write-a-block/version.sh @@ -1,4 +1,4 @@ MAJOR_VERSION=3 API_COMPAT=5 -MINOR_VERSION=1 -MAINT_VERSION=0 +MINOR_VERSION=2 +MAINT_VERSION=git diff --git a/gr-uhd/apps/uhd_fft.py b/gr-uhd/apps/uhd_fft.py index 7314c4759..18edc8f86 100755 --- a/gr-uhd/apps/uhd_fft.py +++ b/gr-uhd/apps/uhd_fft.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr +from gnuradio import gr, gru from gnuradio import uhd from gnuradio import eng_notation from gnuradio.eng_option import eng_option @@ -75,6 +75,8 @@ class app_top_block(stdgui2.std_top_block): help="Set wire format from USRP [default=%default]") parser.add_option("", "--scalar", type="int", default=1024, help="Set scalar multiplier value sc8 wire format [default=%default]") + parser.add_option("", "--show-async-msg", action="store_true", default=False, + help="Show asynchronous message notifications from UHD [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() @@ -146,6 +148,16 @@ class app_top_block(stdgui2.std_top_block): if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") + # Direct asynchronous notifications to callback function + if self.options.show_async_msg: + self.async_msgq = gr.msg_queue(0) + self.async_src = uhd.amsg_source("", self.async_msgq) + self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback) + + def async_callback(self, msg): + md = self.async_src.msg_to_async_metadata_t(msg) + print "Channel: %i Time: %f Event: %i" % (md.channel, md.time_spec.get_real_secs(), md.event_code) + def _set_status_msg(self, msg): self.frame.GetStatusBar().SetStatusText(msg, 0) diff --git a/gr-uhd/apps/uhd_rx_cfile.py b/gr-uhd/apps/uhd_rx_cfile.py index de44d4f56..718bb80b7 100755 --- a/gr-uhd/apps/uhd_rx_cfile.py +++ b/gr-uhd/apps/uhd_rx_cfile.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -26,7 +26,7 @@ outputs single precision complex float values or complex short values (interleaved 16 bit signed short integers). """ -from gnuradio import gr, eng_notation +from gnuradio import gr, gru, eng_notation from gnuradio import uhd from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -106,6 +106,17 @@ class rx_cfile_block(gr.top_block): else: print "Writing 32-bit complex floats" print "Output filename:", filename + + # Direct asynchronous notifications to callback function + if options.show_async_msg: + self.async_msgq = gr.msg_queue(0) + self.async_src = uhd.amsg_source("", self.async_msgq) + self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback) + + def async_callback(self, msg): + md = self.async_src.msg_to_async_metadata_t(msg) + print "Channel: %i Time: %f Event: %i" % (md.channel, md.time_spec.get_real_secs(), md.event_code) + def get_options(): usage="%prog: [options] output_filename" @@ -134,6 +145,8 @@ def get_options(): help="set wire format from USRP [default=%default") parser.add_option("", "--scalar", type="int", default=1024, help="set scalar multiplier value for sc8 wire format [default=%default]") + parser.add_option("", "--show-async-msg", action="store_true", default=False, + help="Show asynchronous message notifications from UHD [default=%default]") (options, args) = parser.parse_args () if len(args) != 1: diff --git a/gr-uhd/apps/uhd_rx_nogui.py b/gr-uhd/apps/uhd_rx_nogui.py index e692e6ea3..bcb52c619 100755 --- a/gr-uhd/apps/uhd_rx_nogui.py +++ b/gr-uhd/apps/uhd_rx_nogui.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2011 Free Software Foundation, Inc. +# Copyright 2006,2007,2011,2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -190,6 +190,17 @@ class app_top_block(gr.top_block): AUDIO = audio.sink(int(options.output_rate), options.audio_output) self.connect(tail, AUDIO) + + # Direct asynchronous notifications to callback function + if self.options.show_async_msg: + self.async_msgq = gr.msg_queue(0) + self.async_src = uhd.amsg_source("", self.async_msgq) + self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback) + + def async_callback(self, msg): + md = self.async_src.msg_to_async_metadata_t(msg) + print "Channel: %i Time: %f Event: %i" % (md.channel, md.time_spec.get_real_secs(), md.event_code) + def main(): parser = OptionParser(option_class=eng_option) @@ -222,6 +233,8 @@ def main(): help="set CTCSS squelch to FREQ [default=%default]") parser.add_option("-O", "--audio-output", type="string", default="", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + parser.add_option("", "--show-async-msg", action="store_true", default=False, + help="Show asynchronous message notifications from UHD [default=%default]") (options, args) = parser.parse_args() if options.frequency is None: diff --git a/gr-uhd/apps/uhd_siggen.py b/gr-uhd/apps/uhd_siggen.py index 27e9e8e01..e1af586ae 100755 --- a/gr-uhd/apps/uhd_siggen.py +++ b/gr-uhd/apps/uhd_siggen.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2008,2009,2011 Free Software Foundation, Inc. +# Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -38,7 +38,7 @@ TYPE_KEY = 'type' def setter(ps, key, val): ps[key] = val -from gnuradio import gr, uhd, eng_notation +from gnuradio import gr, gru, uhd, eng_notation from gnuradio.gr.pubsub import pubsub from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -114,6 +114,16 @@ class top_block(gr.top_block, pubsub): if self._verbose: print str(self._u) + # Direct asynchronous notifications to callback function + if options.show_async_msg: + self.async_msgq = gr.msg_queue(0) + self.async_src = uhd.amsg_source("", self.async_msgq) + self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback) + + def async_callback(self, msg): + md = self.async_src.msg_to_async_metadata_t(msg) + print "Channel: %i Time: %f Event: %i" % (md.channel, md.time_spec.get_real_secs(), md.event_code) + def _set_tx_amplitude(self, ampl): """ Sets the transmit amplitude sent to the USRP @@ -325,6 +335,8 @@ def get_options(): metavar="AMPL") parser.add_option("-v", "--verbose", action="store_true", default=False, help="Use verbose console output [default=%default]") + parser.add_option("", "--show-async-msg", action="store_true", default=False, + help="Show asynchronous message notifications from UHD [default=%default]") (options, args) = parser.parse_args() diff --git a/gr-uhd/include/gr_uhd_amsg_source.h b/gr-uhd/include/gr_uhd_amsg_source.h index accf15ce2..3c1b59fa7 100644 --- a/gr-uhd/include/gr_uhd_amsg_source.h +++ b/gr-uhd/include/gr_uhd_amsg_source.h @@ -38,6 +38,13 @@ GR_UHD_API boost::shared_ptr<uhd_amsg_source> uhd_make_amsg_source( ); class GR_UHD_API uhd_amsg_source{ +public: + /*! + * Convert a raw asynchronous message to an asynchronous metatdata object. + * \return The asynchronous metadata object. + */ + static uhd::async_metadata_t msg_to_async_metadata_t(const gr_message_sptr msg); + }; #endif /* INCLUDED_GR_UHD_AMSG_SOURCE_H */ diff --git a/gr-uhd/lib/gr_uhd_amsg_source.cc b/gr-uhd/lib/gr_uhd_amsg_source.cc index f2958f115..08941584b 100644 --- a/gr-uhd/lib/gr_uhd_amsg_source.cc +++ b/gr-uhd/lib/gr_uhd_amsg_source.cc @@ -75,6 +75,11 @@ protected: bool _running; }; +uhd::async_metadata_t uhd_amsg_source::msg_to_async_metadata_t(const gr_message_sptr msg) +{ + return *(uhd::async_metadata_t *)msg->msg(); +} + /*********************************************************************** * Make UHD Asynchronous Message Source **********************************************************************/ diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am index 020dcecdd..738e79f24 100644 --- a/grc/blocks/Makefile.am +++ b/grc/blocks/Makefile.am @@ -162,6 +162,7 @@ dist_ourdata_DATA = \ gr_stream_to_vector.xml \ gr_streams_to_stream.xml \ gr_streams_to_vector.xml \ + gr_burst_tagger.xml \ gr_sub_xx.xml \ gr_threshold_ff.xml \ gr_throttle.xml \ diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index 183408cec..abc12b97f 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -104,6 +104,7 @@ <block>blks2_stream_to_vector_decimator</block> <block>gr_stream_mux</block> + <block>gr_burst_tagger</block> </cat> <cat> <name>Misc Conversions</name> diff --git a/grc/blocks/gr_burst_tagger.xml b/grc/blocks/gr_burst_tagger.xml new file mode 100644 index 000000000..58c909999 --- /dev/null +++ b/grc/blocks/gr_burst_tagger.xml @@ -0,0 +1,87 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Burst tagger: +## all types, 1 output, 2 input: stream & trigger (short) +################################################### + --> +<block> + <name>Burst Tagger</name> + <key>gr_burst_tagger</key> + <import>from gnuradio import gr</import> + <make>gr.burst_tagger($type.size) +self.$(id).set_true_tag($true_key,$true_value) +self.$(id).set_false_tag($false_key,$false_value) + </make> + <callback>set_true_tag($true_key,$true_value)</callback> + <callback>set_false_tag($false_key,$false_value)</callback> + <param> + <name>Stream Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>True KeyID</name> + <key>true_key</key> + <value>burst</value> + <type>string</type> + </param> + <param> + <name>True Value</name> + <key>true_value</key> + <value>True</value> + <type>bool</type> + </param> + <param> + <name>False KeyID</name> + <key>false_key</key> + <value>burst</value> + <type>string</type> + </param> + <param> + <name>False Value</name> + <key>false_value</key> + <value>False</value> + <type>bool</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + <vlen>1</vlen> + </sink> + <sink> + <name>trigger</name> + <type>short</type> + <vlen>1</vlen> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>1</vlen> + </source> +</block> diff --git a/version.sh b/version.sh index 58ec712f6..88a3de947 100644 --- a/version.sh +++ b/version.sh @@ -1,4 +1,4 @@ MAJOR_VERSION=3 API_COMPAT=5 -MINOR_VERSION=1 -MAINT_VERSION=0 +MINOR_VERSION=2 +MAINT_VERSION=git |