diff options
319 files changed, 17530 insertions, 5968 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f617df901..858a7d6a2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,8 +46,8 @@ message(STATUS "Build type set to ${CMAKE_BUILD_TYPE}.") # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) set(VERSION_INFO_API_COMPAT 7) -set(VERSION_INFO_MINOR_VERSION 5) -set(VERSION_INFO_MAINT_VERSION 1) +set(VERSION_INFO_MINOR_VERSION 6) +set(VERSION_INFO_MAINT_VERSION git) include(GrVersion) #setup version info # Append -O2 optimization flag for Debug builds diff --git a/cmake/Modules/FindUHD.cmake b/cmake/Modules/FindUHD.cmake index cfb89b11ce..21cb0942c3 100644 --- a/cmake/Modules/FindUHD.cmake +++ b/cmake/Modules/FindUHD.cmake @@ -2,7 +2,7 @@ # Find the library for the USRP Hardware Driver ######################################################################## -# make this file non-reentrant +# make this file non-reentrant within the current context if(__INCLUDED_FIND_UHD_CMAKE) return() endif() @@ -20,6 +20,12 @@ unset(CMAKE_MODULE_PATH) # handle REQUIRED internally later unset(UHD_FOUND) +# set that UHDConfig.cmake was not used. Have to use the ENV, since +# UHDConfigVersion does not allow CACHE changes and UHDConfig might +# not allow CACHE changes. +set(ENV{UHD_CONFIG_USED} FALSE) +set(ENV{UHD_CONFIG_VERSION_USED} FALSE) + # was the version specified? unset(LOCAL_UHD_FIND_VERSION) if(UHD_FIND_VERSION) @@ -42,10 +48,10 @@ find_package( # restore CMAKE_MODULE_PATH set(CMAKE_MODULE_PATH ${SAVED_CMAKE_MODULE_PATH}) -# check if UHD was found above -if(NOT UHD_FOUND) +# check if UHDConfig was used above +if(NOT $ENV{UHD_CONFIG_VERSION_USED}) - # Not found; try the "old" method (not as robust) + # Not used; try the "old" method (not as robust) include(FindPkgConfig) pkg_check_modules(PC_UHD uhd) @@ -67,7 +73,7 @@ if(NOT UHD_FOUND) PATHS /usr/local/lib /usr/lib ) -endif(NOT UHD_FOUND) +endif(NOT $ENV{UHD_CONFIG_VERSION_USED}) if(UHD_LIBRARIES AND UHD_INCLUDE_DIRS) @@ -79,7 +85,9 @@ if(UHD_LIBRARIES AND UHD_INCLUDE_DIRS) mark_as_advanced(UHD_LIBRARIES UHD_INCLUDE_DIRS) elseif(UHD_FIND_REQUIRED) - - message(FATAL_ERROR "UHD is required, but was not found.") - + if($ENV{UHD_CONFIG_VERSION_USED} AND NOT $ENV{UHD_CONFIG_USED}) + message(FATAL_ERROR "The found UHD version ($ENV{UHD_PACKAGE_VERSION}) is not compatible with the version required (${UHD_FIND_VERSION}).") + else() + message(FATAL_ERROR "UHD is required, but was not found.") + endif() endif() diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in index 3b82e2c40c..3f558526e7 100644 --- a/docs/doxygen/Doxyfile.in +++ b/docs/doxygen/Doxyfile.in @@ -142,26 +142,51 @@ STRIP_FROM_PATH = # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = @CMAKE_SOURCE_DIR@/gnuradio-runtime/include \ + @CMAKE_BINARY_DIR@/gnuradio-runtime/include \ @CMAKE_SOURCE_DIR@/gr-analog/include \ + @CMAKE_BINARY_DIR@/gr-analog/include \ @CMAKE_SOURCE_DIR@/gr-atsc/include \ + @CMAKE_BINARY_DIR@/gr-atsc/include \ @CMAKE_SOURCE_DIR@/gr-audio/include \ + @CMAKE_BINARY_DIR@/gr-audio/include \ @CMAKE_SOURCE_DIR@/gr-blocks/include \ + @CMAKE_BINARY_DIR@/gr-blocks/include \ @CMAKE_SOURCE_DIR@/gr-channels/include \ + @CMAKE_BINARY_DIR@/gr-channels/include \ @CMAKE_SOURCE_DIR@/gr-comedi/include \ + @CMAKE_BINARY_DIR@/gr-comedi/include \ @CMAKE_SOURCE_DIR@/gr-digital/include \ + @CMAKE_BINARY_DIR@/gr-digital/include \ + @CMAKE_SOURCE_DIR@/gr-dtv/include \ + @CMAKE_BINARY_DIR@/gr-dtv/include \ @CMAKE_SOURCE_DIR@/gr-fcd/include \ + @CMAKE_BINARY_DIR@/gr-fcd/include \ @CMAKE_SOURCE_DIR@/gr-fec/include \ + @CMAKE_BINARY_DIR@/gr-fec/include \ @CMAKE_SOURCE_DIR@/gr-fft/include \ + @CMAKE_BINARY_DIR@/gr-fft/include \ @CMAKE_SOURCE_DIR@/gr-filter/include \ + @CMAKE_BINARY_DIR@/gr-filter/include \ @CMAKE_SOURCE_DIR@/gr-noaa/include \ + @CMAKE_BINARY_DIR@/gr-noaa/include \ @CMAKE_SOURCE_DIR@/gr-pager/include \ + @CMAKE_BINARY_DIR@/gr-pager/include \ @CMAKE_SOURCE_DIR@/gr-qtgui/include \ + @CMAKE_BINARY_DIR@/gr-qtgui/include \ @CMAKE_SOURCE_DIR@/gr-trellis/include \ + @CMAKE_BINARY_DIR@/gr-trellis/include \ @CMAKE_SOURCE_DIR@/gr-uhd/include \ + @CMAKE_BINARY_DIR@/gr-uhd/include \ @CMAKE_SOURCE_DIR@/gr-video-sdl/include \ + @CMAKE_BINARY_DIR@/gr-video-sdl/include \ @CMAKE_SOURCE_DIR@/gr-vocoder/include \ + @CMAKE_BINARY_DIR@/gr-vocoder/include \ + @CMAKE_SOURCE_DIR@/gr-wavelet/include \ + @CMAKE_BINARY_DIR@/gr-wavelet/include \ @CMAKE_SOURCE_DIR@/gr-wxgui/include \ - @CMAKE_SOURCE_DIR@/volk/include + @CMAKE_BINARY_DIR@/gr-wxgui/include \ + @CMAKE_SOURCE_DIR@/volk/include \ + @CMAKE_BINARY_DIR@/volk/include # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system diff --git a/docs/doxygen/other/pmt.dox b/docs/doxygen/other/pmt.dox index bc7f870ccd..51e1865d39 100644 --- a/docs/doxygen/other/pmt.dox +++ b/docs/doxygen/other/pmt.dox @@ -477,4 +477,21 @@ pmt::pmt_t a pmt::from_double(1.0); std::cout << "The PMT a contains " << a << std::endl; \endcode + +\section pmt_python Conversion between Python Objects and PMTs + +Although PMTs can be manipulated in Python using the Python versions +of the C++ interfaces, there are some additional goodies that make it +easier to work with PMTs in python. There are functions to automate +the conversion between PMTs and Python types for booleans, strings, +integers, longs, floats, complex numbers, dictionaries, lists, tuples +and combinations thereof. + +Two functions capture most of this functionality: + +\code +pmt.to_pmt # Converts a python object to a PMT. +pmt.to_python # Converts a PMT into a python object. +\endcode + */ diff --git a/docs/doxygen/other/stream_tags.dox b/docs/doxygen/other/stream_tags.dox index 851740984e..d48ec1ddee 100644 --- a/docs/doxygen/other/stream_tags.dox +++ b/docs/doxygen/other/stream_tags.dox @@ -61,7 +61,10 @@ at <em>nitems_written(0)+i</em> for the 0th output port. \section stream_tags_api Stream Tags API The stream tags API consists of four functions, two to add and two to -get the stream tags. These functions are: +get the stream tags. These functions are only meant to be accessed +within a call to general_work/work. While they can be called elsewhere +in time by a block, the behavior outside of work is undefined without +exact knowledge of the item counts in the buffers. \li gr::block::add_item_tag: Adds an item tag to a particular output port using a gr::tag_t data type. diff --git a/gnuradio-runtime/include/gnuradio/block.h b/gnuradio-runtime/include/gnuradio/block.h index a033e0ac27..4a534b7f46 100644 --- a/gnuradio-runtime/include/gnuradio/block.h +++ b/gnuradio-runtime/include/gnuradio/block.h @@ -221,7 +221,8 @@ namespace gr { /*! * \brief Tell the scheduler \p how_many_items of input stream \p - * which_input were consumed. + * which_input were consumed. + * This function should be called at the end of work() or general_work(), after all processing is finished. */ void consume(int which_input, int how_many_items); @@ -503,6 +504,11 @@ namespace gr { float pc_work_time_total(); /*! + * \brief Gets average throughput. + */ + float pc_throughput_avg(); + + /*! * \brief Resets the performance counters */ void reset_perf_counters(); @@ -636,7 +642,7 @@ namespace gr { void add_item_tag(unsigned int which_output, const tag_t &tag); /*! - * \brief Removes a tag from the given input buffer. + * \brief DEPRECATED. Will be removed in 3.8. * * \param which_input an integer of which input stream to remove the tag from * \param abs_offset a uint64 number of the absolute item number @@ -662,9 +668,7 @@ namespace gr { } /*! - * \brief Removes a tag from the given input buffer. - * - * If no such tag is found, does nothing. + * \brief DEPRECATED. Will be removed in 3.8. * * \param which_input an integer of which input stream to remove the tag from * \param tag the tag object to remove diff --git a/gnuradio-runtime/include/gnuradio/block_detail.h b/gnuradio-runtime/include/gnuradio/block_detail.h index 41568c8ab3..916c0a46c1 100644 --- a/gnuradio-runtime/include/gnuradio/block_detail.h +++ b/gnuradio-runtime/include/gnuradio/block_detail.h @@ -219,6 +219,7 @@ namespace gr { float pc_output_buffers_full_avg(size_t which); std::vector<float> pc_output_buffers_full_avg(); float pc_work_time_avg(); + float pc_throughput_avg(); float pc_noutput_items_var(); float pc_nproduced_var(); @@ -246,6 +247,9 @@ namespace gr { float d_ins_noutput_items; float d_avg_noutput_items; float d_var_noutput_items; + float d_total_noutput_items; + gr::high_res_timer_type d_pc_start_time; + gr::high_res_timer_type d_pc_last_work_time; float d_ins_nproduced; float d_avg_nproduced; float d_var_nproduced; @@ -260,6 +264,7 @@ namespace gr { float d_avg_work_time; float d_var_work_time; float d_total_work_time; + float d_avg_throughput; float d_pc_counter; block_detail(unsigned int ninputs, unsigned int noutputs); diff --git a/gnuradio-runtime/include/gnuradio/buffer.h b/gnuradio-runtime/include/gnuradio/buffer.h index e2d5760e59..c0c9f3d39d 100644 --- a/gnuradio-runtime/include/gnuradio/buffer.h +++ b/gnuradio-runtime/include/gnuradio/buffer.h @@ -28,7 +28,7 @@ #include <gnuradio/tags.h> #include <boost/weak_ptr.hpp> #include <gnuradio/thread/thread.h> -#include <deque> +#include <map> namespace gr { @@ -125,8 +125,10 @@ namespace gr { */ void prune_tags(uint64_t max_time); - std::deque<tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } - std::deque<tag_t>::iterator get_tags_end() { return d_item_tags.end(); } + std::multimap<uint64_t,tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } + std::multimap<uint64_t,tag_t>::iterator get_tags_end() { return d_item_tags.end(); } + std::multimap<uint64_t,tag_t>::iterator get_tags_lower_bound(uint64_t x) { return d_item_tags.lower_bound(x); } + std::multimap<uint64_t,tag_t>::iterator get_tags_upper_bound(uint64_t x) { return d_item_tags.upper_bound(x); } // ------------------------------------------------------------------------- @@ -157,7 +159,7 @@ namespace gr { unsigned int d_write_index; // in items [0,d_bufsize) uint64_t d_abs_write_offset; // num items written since the start bool d_done; - std::deque<tag_t> d_item_tags; + std::multimap<uint64_t,tag_t> d_item_tags; uint64_t d_last_min_items_read; unsigned index_add(unsigned a, unsigned b) diff --git a/gnuradio-runtime/include/gnuradio/logger.h.in b/gnuradio-runtime/include/gnuradio/logger.h.in index 05367a1873..941ce75af3 100644 --- a/gnuradio-runtime/include/gnuradio/logger.h.in +++ b/gnuradio-runtime/include/gnuradio/logger.h.in @@ -844,8 +844,11 @@ namespace gr { * block, we use 'alias()' for this value, and this is set up for us * automatically in gr::block. */ - GR_RUNTIME_API bool configure_default_loggers(gr::logger_ptr &l, gr::logger_ptr &d, - const std::string name); + GR_RUNTIME_API bool configure_default_loggers(gr::logger_ptr &l, gr::logger_ptr &d, + const std::string name); + + GR_RUNTIME_API bool update_logger_alias(const std::string &name, const std::string &alias); + } /* namespace gr */ diff --git a/gnuradio-runtime/include/gnuradio/tagged_stream_block.h b/gnuradio-runtime/include/gnuradio/tagged_stream_block.h index 1fe92ee25a..86343f281d 100644 --- a/gnuradio-runtime/include/gnuradio/tagged_stream_block.h +++ b/gnuradio-runtime/include/gnuradio/tagged_stream_block.h @@ -97,6 +97,8 @@ namespace gr { */ void /* final */ forecast (int noutput_items, gr_vector_int &ninput_items_required); + bool check_topology(int ninputs, int /* noutputs */); + /*! * - Reads the number of input items from the tags using parse_length_tags() * - Checks there's enough data on the input and output buffers diff --git a/gnuradio-runtime/include/pmt/pmt.h b/gnuradio-runtime/include/pmt/pmt.h index 3e17571b23..cb6fdf44d5 100644 --- a/gnuradio-runtime/include/pmt/pmt.h +++ b/gnuradio-runtime/include/pmt/pmt.h @@ -201,6 +201,7 @@ PMT_API bool is_real(pmt_t obj); //! Return the pmt value that represents double \p x. PMT_API pmt_t from_double(double x); +PMT_API pmt_t from_float(float x); /*! * \brief Convert pmt to double if possible. @@ -211,6 +212,15 @@ PMT_API pmt_t from_double(double x); */ PMT_API double to_double(pmt_t x); +/*! + * \brief Convert pmt to float if possible. + * + * This basically is to_double() with a type-cast; the PMT stores + * the value as a double in any case. Use this when strict typing + * is required. + */ +PMT_API float to_float(pmt_t x); + /* * ------------------------------------------------------------------------ * Complex diff --git a/gnuradio-runtime/lib/basic_block.cc b/gnuradio-runtime/lib/basic_block.cc index 686c1d6e65..09d2eb2b3a 100644 --- a/gnuradio-runtime/lib/basic_block.cc +++ b/gnuradio-runtime/lib/basic_block.cc @@ -26,6 +26,7 @@ #include <gnuradio/basic_block.h> #include <gnuradio/block_registry.h> +#include <gnuradio/logger.h> #include <stdexcept> #include <sstream> #include <iostream> @@ -82,6 +83,7 @@ namespace gr { // set the block's alias d_symbol_alias = name; + update_logger_alias(symbol_name(), d_symbol_alias); } // ** Message passing interface ** diff --git a/gnuradio-runtime/lib/block.cc b/gnuradio-runtime/lib/block.cc index a15fb89c85..9173094e53 100644 --- a/gnuradio-runtime/lib/block.cc +++ b/gnuradio-runtime/lib/block.cc @@ -60,7 +60,7 @@ namespace gr { message_port_register_in(pmt::mp("system")); set_msg_handler(pmt::mp("system"), boost::bind(&block::system_handler, this, _1)); - configure_default_loggers(d_logger, d_debug_logger, alias()); + configure_default_loggers(d_logger, d_debug_logger, symbol_name()); } block::~block() @@ -682,6 +682,16 @@ namespace gr { } } + float + block::pc_throughput_avg() { + if(d_detail) { + return d_detail->pc_throughput_avg(); + } + else { + return 0; + } + } + void block::reset_perf_counters() { diff --git a/gnuradio-runtime/lib/block_detail.cc b/gnuradio-runtime/lib/block_detail.cc index 77c457cf7f..9463e8d13b 100644 --- a/gnuradio-runtime/lib/block_detail.cc +++ b/gnuradio-runtime/lib/block_detail.cc @@ -46,6 +46,7 @@ namespace gr { d_ins_noutput_items(0), d_avg_noutput_items(0), d_var_noutput_items(0), + d_total_noutput_items(0), d_ins_nproduced(0), d_avg_nproduced(0), d_var_nproduced(0), @@ -58,9 +59,11 @@ namespace gr { d_ins_work_time(0), d_avg_work_time(0), d_var_work_time(0), + d_avg_throughput(0), d_pc_counter(0) { s_ncurrently_allocated++; + d_pc_start_time = gr::high_res_timer_now(); } block_detail::~block_detail() @@ -279,6 +282,8 @@ namespace gr { d_ins_noutput_items = noutput_items; d_avg_noutput_items = noutput_items; d_var_noutput_items = 0; + d_total_noutput_items = noutput_items; + d_pc_start_time = (float)gr::high_res_timer_now(); for(size_t i=0; i < d_input.size(); i++) { gr::thread::scoped_lock guard(*d_input[i]->mutex()); float pfull = static_cast<float>(d_input[i]->items_available()) / @@ -312,6 +317,10 @@ namespace gr { d_ins_noutput_items = noutput_items; d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter; d_var_noutput_items = d_var_noutput_items + d*d; + d_total_noutput_items += noutput_items; + d_pc_last_work_time = gr::high_res_timer_now(); + float monitor_time = (float)(d_pc_last_work_time - d_pc_start_time) / (float)gr::high_res_timer_tps(); + d_avg_throughput = d_total_noutput_items / monitor_time; for(size_t i=0; i < d_input.size(); i++) { gr::thread::scoped_lock guard(*d_input[i]->mutex()); @@ -501,4 +510,8 @@ namespace gr { return d_total_work_time; } + float + block_detail::pc_throughput_avg() { + return d_avg_throughput; + } } /* namespace gr */ diff --git a/gnuradio-runtime/lib/buffer.cc b/gnuradio-runtime/lib/buffer.cc index 162324e590..f00e9a04bf 100644 --- a/gnuradio-runtime/lib/buffer.cc +++ b/gnuradio-runtime/lib/buffer.cc @@ -23,7 +23,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - +#include <algorithm> #include <gnuradio/buffer.h> #include <gnuradio/math.h> #include "vmcircbuf.h" @@ -225,16 +225,16 @@ namespace gr { buffer::add_item_tag(const tag_t &tag) { gr::thread::scoped_lock guard(*mutex()); - d_item_tags.push_back(tag); + d_item_tags.insert(std::pair<uint64_t,tag_t>(tag.offset,tag)); } void buffer::remove_item_tag(const tag_t &tag, long id) { gr::thread::scoped_lock guard(*mutex()); - for(std::deque<tag_t>::iterator it = d_item_tags.begin(); it != d_item_tags.end(); ++it) { - if(*it == tag) { - (*it).marked_deleted.push_back(id); + for(std::multimap<uint64_t,tag_t>::iterator it = d_item_tags.lower_bound(tag.offset); it != d_item_tags.upper_bound(tag.offset); ++it) { + if((*it).second == tag) { + (*it).second.marked_deleted.push_back(id); } } } @@ -250,25 +250,9 @@ namespace gr { If this function is used elsewhere, remember to lock the buffer's mutex al la the scoped_lock line below. */ - //gr::thread::scoped_lock guard(*mutex()); - std::deque<tag_t>::iterator itr = d_item_tags.begin(); - - uint64_t item_time; - - // Since tags are not guarenteed to be in any particular order, we - // need to erase here instead of pop_front. An erase in the middle - // invalidates all iterators; so this resets the iterator to find - // more. Mostly, we wil be erasing from the front and - // therefore lose little time this way. - while(itr != d_item_tags.end()) { - item_time = (*itr).offset; - if(item_time+d_max_reader_delay + bufsize() < max_time) { - d_item_tags.erase(itr); - itr = d_item_tags.begin(); - } - else - itr++; - } + std::multimap<uint64_t, tag_t>::iterator end_itr = d_item_tags.lower_bound(max_time); + std::multimap<uint64_t, tag_t>::iterator begin_itr = d_item_tags.begin(); + d_item_tags.erase(begin_itr, end_itr); } long @@ -333,30 +317,28 @@ namespace gr { buffer_reader::get_tags_in_range(std::vector<tag_t> &v, uint64_t abs_start, uint64_t abs_end, - long id) + long id) { gr::thread::scoped_lock guard(*mutex()); v.resize(0); - std::deque<tag_t>::iterator itr = d_buffer->get_tags_begin(); + std::multimap<uint64_t,tag_t>::iterator itr = d_buffer->get_tags_lower_bound(abs_start); + std::multimap<uint64_t,tag_t>::iterator itr_end = d_buffer->get_tags_upper_bound(abs_end); uint64_t item_time; - while(itr != d_buffer->get_tags_end()) { - item_time = (*itr).offset + d_attr_delay; - + while(itr != itr_end) { + item_time = (*itr).second.offset + d_attr_delay; if((item_time >= abs_start) && (item_time < abs_end)) { - std::vector<long>::iterator id_itr; - id_itr = std::find(itr->marked_deleted.begin(), itr->marked_deleted.end(), id); - + std::vector<long>::iterator id_itr; + id_itr = std::find(itr->second.marked_deleted.begin(), itr->second.marked_deleted.end(), id); // If id is not in the vector of marked blocks - if(id_itr == itr->marked_deleted.end()) { - tag_t t = *itr; + if(id_itr == itr->second.marked_deleted.end()) { + tag_t t = (*itr).second; t.offset += d_attr_delay; - v.push_back(t); - v.back().marked_deleted.clear(); - } + v.push_back(t); + v.back().marked_deleted.clear(); + } } - itr++; } } diff --git a/gnuradio-runtime/lib/logger.cc b/gnuradio-runtime/lib/logger.cc index bb1d4b4c33..13c8391c8e 100644 --- a/gnuradio-runtime/lib/logger.cc +++ b/gnuradio-runtime/lib/logger.cc @@ -417,4 +417,35 @@ namespace gr { return false; } + bool + update_logger_alias(const std::string &name, const std::string &alias) + { +#ifdef ENABLE_GR_LOG +#ifdef HAVE_LOG4CPP + prefs *p = prefs::singleton(); + std::string log_file = p->get_string("LOG", "log_file", ""); + std::string debug_file = p->get_string("LOG", "debug_file", ""); + + GR_LOG_GETLOGGER(LOG, "gr_log." + name); + if(log_file.size() > 0) { + if(log_file == "stdout") { + boost::format str("gr::log :%%p: %1% - %%m%%n"); + GR_LOG_SET_CONSOLE_APPENDER(LOG, "cout", boost::str(str % alias)); + } + else if(log_file == "stderr") { + boost::format str("gr::log :%%p: %1% - %%m%%n"); + GR_LOG_SET_CONSOLE_APPENDER(LOG, "cerr", boost::str(str % alias)); + } + else { + boost::format str("%%r :%%p: %1% - %%m%%n"); + GR_LOG_SET_FILE_APPENDER(LOG, log_file, true, boost::str(str % alias)); + } + } + return true; +#endif /* HAVE_LOG4CPP */ +#endif /* ENABLE_GR_LOG */ + + return false; + } + } /* namespace gr */ diff --git a/gnuradio-runtime/lib/pmt/pmt.cc b/gnuradio-runtime/lib/pmt/pmt.cc index 082b98a80d..da830e1aed 100644 --- a/gnuradio-runtime/lib/pmt/pmt.cc +++ b/gnuradio-runtime/lib/pmt/pmt.cc @@ -368,6 +368,12 @@ from_double(double x) return pmt_t(new pmt_real(x)); } +pmt_t +from_float(float x) +{ + return pmt_t(new pmt_real(x)); +} + double to_double(pmt_t x) { @@ -379,6 +385,12 @@ to_double(pmt_t x) throw wrong_type("pmt_to_double", x); } +float +to_float(pmt_t x) +{ + return float(to_double(x)); +} + //////////////////////////////////////////////////////////////////////////// // Complex //////////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc index 2f46b014db..2b3ca32293 100644 --- a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc +++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc @@ -125,6 +125,15 @@ qa_pmt_prims::test_reals() CPPUNIT_ASSERT_EQUAL(-1.0, pmt::to_double(m1)); CPPUNIT_ASSERT_EQUAL(1.0, pmt::to_double(p1)); CPPUNIT_ASSERT_EQUAL(1.0, pmt::to_double(pmt::from_long(1))); + + pmt::pmt_t p2 = pmt::from_float(1); + pmt::pmt_t m2 = pmt::from_float(-1); + CPPUNIT_ASSERT(pmt::is_real(p2)); + CPPUNIT_ASSERT(pmt::is_real(m2)); + CPPUNIT_ASSERT_THROW(pmt::to_float(pmt::PMT_T), pmt::wrong_type); + CPPUNIT_ASSERT_EQUAL(float(-1.0), pmt::to_float(m2)); + CPPUNIT_ASSERT_EQUAL(float(1.0), pmt::to_float(p2)); + CPPUNIT_ASSERT_EQUAL(float(1.0), pmt::to_float(pmt::from_long(1))); } void diff --git a/gnuradio-runtime/lib/tagged_stream_block.cc b/gnuradio-runtime/lib/tagged_stream_block.cc index c6d5fc1fec..252a235fbf 100644 --- a/gnuradio-runtime/lib/tagged_stream_block.cc +++ b/gnuradio-runtime/lib/tagged_stream_block.cc @@ -89,6 +89,14 @@ namespace gr { return; } + bool + tagged_stream_block::check_topology(int ninputs, int /* noutputs */) + { + d_n_input_items_reqd.resize(ninputs, 0); + return true; + } + + int tagged_stream_block::general_work(int noutput_items, gr_vector_int &ninput_items, @@ -99,7 +107,9 @@ namespace gr { return work(noutput_items, ninput_items, input_items, output_items); } - if(d_n_input_items_reqd[0] == 0) { // Otherwise, it's already set from a previous call + // Read TSB tags, unless we... + // ...don't have inputs or ... ... we already set it in a previous run. + if(!d_n_input_items_reqd.empty() && d_n_input_items_reqd[0] == 0) { std::vector<std::vector<tag_t> > tags(input_items.size(), std::vector<tag_t>()); for(unsigned i = 0; i < input_items.size(); i++) { get_tags_in_range(tags[i], i, nitems_read(i), nitems_read(i)+1); diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py index cbca9d44ae..ba46e3f4d9 100644 --- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py @@ -89,9 +89,22 @@ def python_to_tag(tag_struct): tag.srcid = tag_struct[3] good = True + elif(len(tag_struct) == 3): + if(isinstance(tag_struct[0], (int,long))): + tag.offset = tag_struct[0] + good = True + + if(isinstance(tag_struct[1], pmt.pmt_swig.swig_int_ptr)): + tag.key = tag_struct[1] + good = True + + if(isinstance(tag_struct[2], pmt.pmt_swig.swig_int_ptr)): + tag.value = tag_struct[2] + good = True + + tag.srcid = pmt.PMT_F + if(good): return tag else: return None - - diff --git a/gnuradio-runtime/python/pmt/qa_pmt.py b/gnuradio-runtime/python/pmt/qa_pmt.py index 5c1af2c00e..32cff62f44 100755 --- a/gnuradio-runtime/python/pmt/qa_pmt.py +++ b/gnuradio-runtime/python/pmt/qa_pmt.py @@ -36,7 +36,9 @@ class test_pmt(unittest.TestCase): const = 123765 x_pmt = pmt.from_double(const) x_int = pmt.to_double(x_pmt) + x_float = pmt.to_float(x_pmt) self.assertEqual(x_int, const) + self.assertEqual(x_float, const) def test03(self): v = pmt.init_f32vector(3, [11, -22, 33]) diff --git a/gnuradio-runtime/swig/block.i b/gnuradio-runtime/swig/block.i index 9f3f374d78..945cea79b2 100644 --- a/gnuradio-runtime/swig/block.i +++ b/gnuradio-runtime/swig/block.i @@ -96,6 +96,7 @@ class gr::block : public gr::basic_block float pc_work_time_avg(); float pc_work_time_var(); float pc_work_time_total(); + float pc_throughput_avg(); // Methods to manage processor affinity. void set_processor_affinity(const std::vector<int> &mask); diff --git a/gnuradio-runtime/swig/pmt_swig.i b/gnuradio-runtime/swig/pmt_swig.i index e54b544977..c4b678222d 100644 --- a/gnuradio-runtime/swig/pmt_swig.i +++ b/gnuradio-runtime/swig/pmt_swig.i @@ -111,6 +111,8 @@ namespace pmt{ bool is_real(pmt_t obj); pmt_t from_double(double x); double to_double(pmt_t x); + pmt_t from_float(double x); + double to_float(pmt_t x); bool is_complex(pmt_t obj); pmt_t make_rectangular(double re, double im); diff --git a/gr-analog/grc/analog_probe_avg_mag_sqrd_x.xml b/gr-analog/grc/analog_probe_avg_mag_sqrd_x.xml index b05ac6d0d1..482982b21f 100644 --- a/gr-analog/grc/analog_probe_avg_mag_sqrd_x.xml +++ b/gr-analog/grc/analog_probe_avg_mag_sqrd_x.xml @@ -11,6 +11,7 @@ <make>analog.probe_avg_mag_sqrd_$(type)($threshold, $alpha)</make> <callback>set_alpha($alpha)</callback> <callback>set_threshold($threshold)</callback> + <callback>reset()</callback> <param> <name>Type</name> <key>type</key> diff --git a/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_c.h b/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_c.h index 781d72f742..e6816f7fb6 100644 --- a/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_c.h +++ b/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_c.h @@ -60,6 +60,7 @@ namespace gr { virtual void set_alpha(double alpha) = 0; virtual void set_threshold(double decibels) = 0; + virtual void reset() = 0; }; } /* namespace analog */ diff --git a/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_cf.h b/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_cf.h index 03f465b2c5..9aeb8761be 100644 --- a/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_cf.h +++ b/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_cf.h @@ -62,6 +62,7 @@ namespace gr { virtual void set_alpha(double alpha) = 0; virtual void set_threshold(double decibels) = 0; + virtual void reset() = 0; }; } /* namespace analog */ diff --git a/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_f.h b/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_f.h index b9424dbd96..66095c3709 100644 --- a/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_f.h +++ b/gr-analog/include/gnuradio/analog/probe_avg_mag_sqrd_f.h @@ -62,6 +62,7 @@ namespace gr { virtual void set_alpha (double alpha) = 0; virtual void set_threshold (double decibels) = 0; + virtual void reset() = 0; }; } /* namespace analog */ diff --git a/gr-analog/lib/probe_avg_mag_sqrd_c_impl.cc b/gr-analog/lib/probe_avg_mag_sqrd_c_impl.cc index 78e0c842ed..3d04c8bc6f 100644 --- a/gr-analog/lib/probe_avg_mag_sqrd_c_impl.cc +++ b/gr-analog/lib/probe_avg_mag_sqrd_c_impl.cc @@ -87,5 +87,11 @@ namespace gr { d_iir.set_taps(alpha); } + void + probe_avg_mag_sqrd_c_impl::reset() + { + d_iir.reset(); + } + } /* namespace analog */ } /* namespace gr */ diff --git a/gr-analog/lib/probe_avg_mag_sqrd_c_impl.h b/gr-analog/lib/probe_avg_mag_sqrd_c_impl.h index cddb9a7234..0128491f9d 100644 --- a/gr-analog/lib/probe_avg_mag_sqrd_c_impl.h +++ b/gr-analog/lib/probe_avg_mag_sqrd_c_impl.h @@ -48,6 +48,7 @@ namespace gr { void set_alpha(double alpha); void set_threshold(double decibels); + void reset(); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.cc b/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.cc index 76d54880d4..c57f5cefd8 100644 --- a/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.cc +++ b/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.cc @@ -89,5 +89,11 @@ namespace gr { d_iir.set_taps(alpha); } + void + probe_avg_mag_sqrd_cf_impl::reset() + { + d_iir.reset(); + } + } /* namespace analog */ } /* namespace gr */ diff --git a/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.h b/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.h index 359f7f8d53..0284981cac 100644 --- a/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.h +++ b/gr-analog/lib/probe_avg_mag_sqrd_cf_impl.h @@ -48,6 +48,7 @@ namespace gr { void set_alpha(double alpha); void set_threshold(double decibels); + void reset(); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-analog/lib/probe_avg_mag_sqrd_f_impl.cc b/gr-analog/lib/probe_avg_mag_sqrd_f_impl.cc index 505a24a5e9..0d2ce63f7b 100644 --- a/gr-analog/lib/probe_avg_mag_sqrd_f_impl.cc +++ b/gr-analog/lib/probe_avg_mag_sqrd_f_impl.cc @@ -87,6 +87,12 @@ namespace gr { d_iir.set_taps(alpha); } + void + probe_avg_mag_sqrd_f_impl::reset() + { + d_iir.reset(); + } + } /* namespace analog */ } /* namespace gr */ diff --git a/gr-analog/lib/probe_avg_mag_sqrd_f_impl.h b/gr-analog/lib/probe_avg_mag_sqrd_f_impl.h index bdccfc7b3a..1f82f85e18 100644 --- a/gr-analog/lib/probe_avg_mag_sqrd_f_impl.h +++ b/gr-analog/lib/probe_avg_mag_sqrd_f_impl.h @@ -48,6 +48,7 @@ namespace gr { void set_alpha(double alpha); void set_threshold(double decibels); + void reset(); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-blocks/examples/CMakeLists.txt b/gr-blocks/examples/CMakeLists.txt index c9829661b6..bb07cdc2b5 100644 --- a/gr-blocks/examples/CMakeLists.txt +++ b/gr-blocks/examples/CMakeLists.txt @@ -17,6 +17,14 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. +install( + FILES + matrix_multiplexer.grc + vector_source_with_tags.grc + DESTINATION ${GR_PKG_DATA_DIR}/examples/blocks + COMPONENT "runtime_python" +) + add_subdirectory(metadata) add_subdirectory(tags) diff --git a/gr-blocks/examples/msg_passing/strobe.grc b/gr-blocks/examples/msg_passing/strobe.grc index e5001a4262..f24887ab76 100644 --- a/gr-blocks/examples/msg_passing/strobe.grc +++ b/gr-blocks/examples/msg_passing/strobe.grc @@ -1,4 +1,5 @@ <?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> <flow_graph> <timestamp>Sun Mar 17 20:42:59 2013</timestamp> <block> @@ -52,8 +53,12 @@ <value></value> </param> <param> + <key>alias</key> + <value></value> + </param> + <param> <key>_coordinate</key> - <value>(10, 10)</value> + <value>(-8, -12)</value> </param> <param> <key>_rotation</key> @@ -61,41 +66,42 @@ </param> </block> <block> - <key>variable</key> + <key>blocks_pdu_to_tagged_stream</key> <param> <key>id</key> - <value>samp_rate</value> + <value>blocks_pdu_to_tagged_stream_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>32000</value> + <key>type</key> + <value>byte</value> </param> <param> - <key>_coordinate</key> - <value>(10, 170)</value> + <key>tag</key> + <value>packet_len</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>alias</key> + <value></value> </param> - </block> - <block> - <key>blocks_message_debug</key> <param> - <key>id</key> - <value>blocks_message_debug_0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(1049, 176)</value> + <value>(264, 179)</value> </param> <param> <key>_rotation</key> @@ -103,22 +109,42 @@ </param> </block> <block> - <key>blocks_pdu_to_tagged_stream</key> + <key>blocks_message_strobe</key> <param> <key>id</key> - <value>blocks_pdu_to_tagged_stream_0</value> + <value>blocks_message_strobe_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>byte</value> + <key>msg</key> + <value>pmt.cons( pmt.PMT_NIL, pmt.make_u8vector(512,0) )</value> + </param> + <param> + <key>period</key> + <value>750</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(388, 85)</value> + <value>(48, 172)</value> </param> <param> <key>_rotation</key> @@ -129,7 +155,7 @@ <key>blocks_message_strobe</key> <param> <key>id</key> - <value>blocks_message_strobe_0_0</value> + <value>blocks_message_strobe_0</value> </param> <param> <key>_enabled</key> @@ -137,15 +163,31 @@ </param> <param> <key>msg</key> - <value>pmt.cons( pmt.PMT_NIL, pmt.make_u8vector(512,0) )</value> + <value>pmt.intern("TEST")</value> </param> <param> <key>period</key> - <value>750</value> + <value>1000</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(95, 95)</value> + <value>(56, 108)</value> </param> <param> <key>_rotation</key> @@ -175,8 +217,28 @@ <value>1</value> </param> <param> + <key>showports</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(629, 81)</value> + <value>(496, 179)</value> </param> <param> <key>_rotation</key> @@ -198,8 +260,28 @@ <value>byte</value> </param> <param> + <key>tag</key> + <value>packet_len</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(837, 47)</value> + <value>(664, 179)</value> </param> <param> <key>_rotation</key> @@ -207,26 +289,26 @@ </param> </block> <block> - <key>blocks_message_strobe</key> + <key>blocks_message_debug</key> <param> <key>id</key> - <value>blocks_message_strobe_0</value> + <value>blocks_message_debug_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>msg</key> - <value>pmt.intern("TEST")</value> + <key>alias</key> + <value></value> </param> <param> - <key>period</key> - <value>1000</value> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(423, 164)</value> + <value>(944, 120)</value> </param> <param> <key>_rotation</key> @@ -234,22 +316,16 @@ </param> </block> <connection> - <source_block_id>blocks_message_strobe_0</source_block_id> - <sink_block_id>blocks_message_debug_0</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> - </connection> - <connection> <source_block_id>blocks_message_strobe_0_0</source_block_id> <sink_block_id>blocks_pdu_to_tagged_stream_0</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> + <source_key>strobe</source_key> + <sink_key>pdus</sink_key> </connection> <connection> - <source_block_id>blocks_tagged_stream_to_pdu_0</source_block_id> - <sink_block_id>blocks_message_debug_0</sink_block_id> + <source_block_id>blocks_pdu_to_tagged_stream_0</source_block_id> + <sink_block_id>blocks_copy_0</sink_block_id> <source_key>0</source_key> - <sink_key>2</sink_key> + <sink_key>0</sink_key> </connection> <connection> <source_block_id>blocks_copy_0</source_block_id> @@ -258,9 +334,15 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_pdu_to_tagged_stream_0</source_block_id> - <sink_block_id>blocks_copy_0</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> + <source_block_id>blocks_message_strobe_0</source_block_id> + <sink_block_id>blocks_message_debug_0</sink_block_id> + <source_key>strobe</source_key> + <sink_key>print</sink_key> + </connection> + <connection> + <source_block_id>blocks_tagged_stream_to_pdu_0</source_block_id> + <sink_block_id>blocks_message_debug_0</sink_block_id> + <source_key>pdus</source_key> + <sink_key>print_pdu</sink_key> </connection> </flow_graph> diff --git a/gr-blocks/examples/vector_source_with_tags.grc b/gr-blocks/examples/vector_source_with_tags.grc new file mode 100644 index 0000000000..e266b91f85 --- /dev/null +++ b/gr-blocks/examples/vector_source_with_tags.grc @@ -0,0 +1,698 @@ +<?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> +<flow_graph> + <timestamp>Mon Sep 22 11:59:58 2014</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>vector_source_with_tags</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value>Shows how to use tags in a vector_source</value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>qt_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>tag1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>gr.tag_utils.python_to_tag((1, pmt.intern('mark'), pmt.PMT_T))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 267)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>tag0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>gr.tag_utils.python_to_tag((0, pmt.intern('mark'), pmt.PMT_T, pmt.intern("src")))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 203)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>32000</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(184, 11)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_pmt</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import pmt</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(280, 11)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>ignoretag</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(272, 123)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_tag_debug</key> + <param> + <key>id</key> + <value>blocks_tag_debug_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>name</key> + <value></value> + </param> + <param> + <key>filter</key> + <value>""</value> + </param> + <param> + <key>num_inputs</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>display</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(456, 195)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>blocks_vector_source_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>vector</key> + <value>(-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 0.0)</value> + </param> + <param> + <key>tags</key> + <value>[tag0, tag1]</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 107)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>qtgui_time_sink_x</key> + <param> + <key>id</key> + <value>qtgui_time_sink_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>name</key> + <value>""</value> + </param> + <param> + <key>ylabel</key> + <value>Amplitude</value> + </param> + <param> + <key>yunit</key> + <value>""</value> + </param> + <param> + <key>size</key> + <value>60</value> + </param> + <param> + <key>srate</key> + <value>samp_rate</value> + </param> + <param> + <key>grid</key> + <value>True</value> + </param> + <param> + <key>autoscale</key> + <value>False</value> + </param> + <param> + <key>ymin</key> + <value>-1</value> + </param> + <param> + <key>ymax</key> + <value>1</value> + </param> + <param> + <key>nconnections</key> + <value>1</value> + </param> + <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>entags</key> + <value>True</value> + </param> + <param> + <key>gui_hint</key> + <value></value> + </param> + <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_TAG</value> + </param> + <param> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> + </param> + <param> + <key>tr_level</key> + <value>0.0</value> + </param> + <param> + <key>tr_delay</key> + <value>0</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> + <key>tr_tag</key> + <value>mark</value> + </param> + <param> + <key>label1</key> + <value></value> + </param> + <param> + <key>width1</key> + <value>1</value> + </param> + <param> + <key>color1</key> + <value>"blue"</value> + </param> + <param> + <key>style1</key> + <value>1</value> + </param> + <param> + <key>marker1</key> + <value>0</value> + </param> + <param> + <key>alpha1</key> + <value>1.0</value> + </param> + <param> + <key>label2</key> + <value></value> + </param> + <param> + <key>width2</key> + <value>1</value> + </param> + <param> + <key>color2</key> + <value>"red"</value> + </param> + <param> + <key>style2</key> + <value>1</value> + </param> + <param> + <key>marker2</key> + <value>-1</value> + </param> + <param> + <key>alpha2</key> + <value>1.0</value> + </param> + <param> + <key>label3</key> + <value></value> + </param> + <param> + <key>width3</key> + <value>1</value> + </param> + <param> + <key>color3</key> + <value>"green"</value> + </param> + <param> + <key>style3</key> + <value>1</value> + </param> + <param> + <key>marker3</key> + <value>-1</value> + </param> + <param> + <key>alpha3</key> + <value>1.0</value> + </param> + <param> + <key>label4</key> + <value></value> + </param> + <param> + <key>width4</key> + <value>1</value> + </param> + <param> + <key>color4</key> + <value>"black"</value> + </param> + <param> + <key>style4</key> + <value>1</value> + </param> + <param> + <key>marker4</key> + <value>-1</value> + </param> + <param> + <key>alpha4</key> + <value>1.0</value> + </param> + <param> + <key>label5</key> + <value></value> + </param> + <param> + <key>width5</key> + <value>1</value> + </param> + <param> + <key>color5</key> + <value>"cyan"</value> + </param> + <param> + <key>style5</key> + <value>1</value> + </param> + <param> + <key>marker5</key> + <value>-1</value> + </param> + <param> + <key>alpha5</key> + <value>1.0</value> + </param> + <param> + <key>label6</key> + <value></value> + </param> + <param> + <key>width6</key> + <value>1</value> + </param> + <param> + <key>color6</key> + <value>"magenta"</value> + </param> + <param> + <key>style6</key> + <value>1</value> + </param> + <param> + <key>marker6</key> + <value>-1</value> + </param> + <param> + <key>alpha6</key> + <value>1.0</value> + </param> + <param> + <key>label7</key> + <value></value> + </param> + <param> + <key>width7</key> + <value>1</value> + </param> + <param> + <key>color7</key> + <value>"yellow"</value> + </param> + <param> + <key>style7</key> + <value>1</value> + </param> + <param> + <key>marker7</key> + <value>-1</value> + </param> + <param> + <key>alpha7</key> + <value>1.0</value> + </param> + <param> + <key>label8</key> + <value></value> + </param> + <param> + <key>width8</key> + <value>1</value> + </param> + <param> + <key>color8</key> + <value>"dark red"</value> + </param> + <param> + <key>style8</key> + <value>1</value> + </param> + <param> + <key>marker8</key> + <value>-1</value> + </param> + <param> + <key>alpha8</key> + <value>1.0</value> + </param> + <param> + <key>label9</key> + <value></value> + </param> + <param> + <key>width9</key> + <value>1</value> + </param> + <param> + <key>color9</key> + <value>"dark green"</value> + </param> + <param> + <key>style9</key> + <value>1</value> + </param> + <param> + <key>marker9</key> + <value>-1</value> + </param> + <param> + <key>alpha9</key> + <value>1.0</value> + </param> + <param> + <key>label10</key> + <value></value> + </param> + <param> + <key>width10</key> + <value>1</value> + </param> + <param> + <key>color10</key> + <value>"blue"</value> + </param> + <param> + <key>style10</key> + <value>1</value> + </param> + <param> + <key>marker10</key> + <value>-1</value> + </param> + <param> + <key>alpha10</key> + <value>1.0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(456, 107)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_vector_source_x_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_tag_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gr-blocks/grc/blocks_abs_xx.xml b/gr-blocks/grc/blocks_abs_xx.xml index 65ef97ddff..77298716c8 100644 --- a/gr-blocks/grc/blocks_abs_xx.xml +++ b/gr-blocks/grc/blocks_abs_xx.xml @@ -8,7 +8,13 @@ <name>Abs</name> <key>blocks_abs_xx</key> <import>from gnuradio import blocks</import> - <make>blocks.abs_$(type.fcn)()</make> + <make>blocks.abs_$(type.fcn)($vlen)</make> + <param> + <name>Vec Length</name> + <key>vlen</key> + <value>1</value> + <type>int</type> + </param> <param> <name>IO Type</name> <key>type</key> @@ -29,21 +35,14 @@ <opt>fcn:ff</opt> </option> </param> - <param> - <name>Num Inputs</name> - <key>num_inputs</key> - <value>1</value> - <type>int</type> - </param> - <check>$num_inputs >= 1</check> <sink> <name>in</name> <type>$type</type> - <nports>$num_inputs</nports> + <vlen>$vlen</vlen> </sink> <source> <name>out</name> <type>$type</type> - <nports>$num_inputs</nports> + <vlen>$vlen</vlen> </source> </block> diff --git a/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml b/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml index f85b47fb19..ae8ad3b6c5 100644 --- a/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml +++ b/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml @@ -42,5 +42,6 @@ <source> <name>pdus</name> <type>message</type> + <optional>1</optional> </source> </block> diff --git a/gr-blocks/include/gnuradio/blocks/abs_XX.h.t b/gr-blocks/include/gnuradio/blocks/abs_XX.h.t index f8688edcd3..541716296f 100644 --- a/gr-blocks/include/gnuradio/blocks/abs_XX.h.t +++ b/gr-blocks/include/gnuradio/blocks/abs_XX.h.t @@ -49,7 +49,7 @@ namespace gr { /*! * \brief Create an instance of @NAME@ */ - static sptr make(); + static sptr make(size_t vlen=1); }; } /* namespace blocks */ diff --git a/gr-blocks/include/gnuradio/blocks/control_loop.h b/gr-blocks/include/gnuradio/blocks/control_loop.h index f7ff9770f9..821c3824ec 100644 --- a/gr-blocks/include/gnuradio/blocks/control_loop.h +++ b/gr-blocks/include/gnuradio/blocks/control_loop.h @@ -268,6 +268,87 @@ namespace gr { float get_min_freq() const; }; + // This is a table of tanh(x) for x in [-2, 2] used in tanh_lut. + static float + tanh_lut_table[256] = { -0.96402758, -0.96290241, -0.96174273, -0.96054753, -0.95931576, + -0.95804636, -0.95673822, -0.95539023, -0.95400122, -0.95257001, + -0.95109539, -0.9495761 , -0.94801087, -0.94639839, -0.94473732, + -0.94302627, -0.94126385, -0.93944862, -0.93757908, -0.93565374, + -0.93367104, -0.93162941, -0.92952723, -0.92736284, -0.92513456, + -0.92284066, -0.92047938, -0.91804891, -0.91554743, -0.91297305, + -0.91032388, -0.90759795, -0.9047933 , -0.90190789, -0.89893968, + -0.89588656, -0.89274642, -0.88951709, -0.88619637, -0.88278203, + -0.87927182, -0.87566342, -0.87195453, -0.86814278, -0.86422579, + -0.86020115, -0.85606642, -0.85181914, -0.84745683, -0.84297699, + -0.83837709, -0.83365461, -0.82880699, -0.82383167, -0.81872609, + -0.81348767, -0.80811385, -0.80260204, -0.7969497 , -0.79115425, + -0.78521317, -0.77912392, -0.772884 , -0.76649093, -0.75994227, + -0.75323562, -0.74636859, -0.73933889, -0.73214422, -0.7247824 , + -0.71725127, -0.70954876, -0.70167287, -0.6936217 , -0.68539341, + -0.67698629, -0.66839871, -0.65962916, -0.65067625, -0.64153871, + -0.6322154 , -0.62270534, -0.61300768, -0.60312171, -0.59304692, + -0.58278295, -0.57232959, -0.56168685, -0.55085493, -0.53983419, + -0.52862523, -0.51722883, -0.50564601, -0.49387799, -0.48192623, + -0.46979241, -0.45747844, -0.44498647, -0.4323189 , -0.41947836, + -0.40646773, -0.39329014, -0.37994896, -0.36644782, -0.35279057, + -0.33898135, -0.32502449, -0.31092459, -0.2966865 , -0.28231527, + -0.26781621, -0.25319481, -0.23845682, -0.22360817, -0.208655 , + -0.19360362, -0.17846056, -0.16323249, -0.14792623, -0.13254879, + -0.11710727, -0.10160892, -0.08606109, -0.07047123, -0.05484686, + -0.0391956 , -0.02352507, -0.00784298, 0.00784298, 0.02352507, + 0.0391956 , 0.05484686, 0.07047123, 0.08606109, 0.10160892, + 0.11710727, 0.13254879, 0.14792623, 0.16323249, 0.17846056, + 0.19360362, 0.208655 , 0.22360817, 0.23845682, 0.25319481, + 0.26781621, 0.28231527, 0.2966865 , 0.31092459, 0.32502449, + 0.33898135, 0.35279057, 0.36644782, 0.37994896, 0.39329014, + 0.40646773, 0.41947836, 0.4323189 , 0.44498647, 0.45747844, + 0.46979241, 0.48192623, 0.49387799, 0.50564601, 0.51722883, + 0.52862523, 0.53983419, 0.55085493, 0.56168685, 0.57232959, + 0.58278295, 0.59304692, 0.60312171, 0.61300768, 0.62270534, + 0.6322154 , 0.64153871, 0.65067625, 0.65962916, 0.66839871, + 0.67698629, 0.68539341, 0.6936217 , 0.70167287, 0.70954876, + 0.71725127, 0.7247824 , 0.73214422, 0.73933889, 0.74636859, + 0.75323562, 0.75994227, 0.76649093, 0.772884 , 0.77912392, + 0.78521317, 0.79115425, 0.7969497 , 0.80260204, 0.80811385, + 0.81348767, 0.81872609, 0.82383167, 0.82880699, 0.83365461, + 0.83837709, 0.84297699, 0.84745683, 0.85181914, 0.85606642, + 0.86020115, 0.86422579, 0.86814278, 0.87195453, 0.87566342, + 0.87927182, 0.88278203, 0.88619637, 0.88951709, 0.89274642, + 0.89588656, 0.89893968, 0.90190789, 0.9047933 , 0.90759795, + 0.91032388, 0.91297305, 0.91554743, 0.91804891, 0.92047938, + 0.92284066, 0.92513456, 0.92736284, 0.92952723, 0.93162941, + 0.93367104, 0.93565374, 0.93757908, 0.93944862, 0.94126385, + 0.94302627, 0.94473732, 0.94639839, 0.94801087, 0.9495761 , + 0.95109539, 0.95257001, 0.95400122, 0.95539023, 0.95673822, + 0.95804636, 0.95931576, 0.96054753, 0.96174273, 0.96290241, + 0.96402758 }; + + /*! + * A look-up table (LUT) tanh calcuation. This function returns an + * estimate to tanh(x) based on a 256-point LUT between -2 and + * 2. If x < -2, it returns -1; if > 2, it retursn 1. + * + * This LUT form of the tanh is "hidden" in this code because it + * is likely too coarse an estimate for any real uses of a + * tanh. It is useful, however, in certain control loop + * applications where the input is expected to be within these + * bounds and the noise will be greater than the quanitzation of + * this small LUT. For more accurate forms of tanh, see + * volk_32f_tanh_32f. + */ + static inline float + tanhf_lut(float x) + { + if(x > 2) + return 1; + else if(x <= -2) + return -1; + else { + int index = 128 + 64*x; + return tanh_lut_table[index]; + } + } + } /* namespace blocks */ } /* namespace gr */ diff --git a/gr-blocks/include/gnuradio/blocks/pdu_to_tagged_stream.h b/gr-blocks/include/gnuradio/blocks/pdu_to_tagged_stream.h index 9ae2ecd297..479e367e72 100644 --- a/gr-blocks/include/gnuradio/blocks/pdu_to_tagged_stream.h +++ b/gr-blocks/include/gnuradio/blocks/pdu_to_tagged_stream.h @@ -25,7 +25,7 @@ #include <gnuradio/blocks/api.h> #include <gnuradio/blocks/pdu.h> -#include <gnuradio/sync_block.h> +#include <gnuradio/tagged_stream_block.h> namespace gr { namespace blocks { @@ -34,7 +34,7 @@ namespace gr { * \brief Turns received PDUs into a tagged stream of items * \ingroup message_tools_blk */ - class BLOCKS_API pdu_to_tagged_stream : virtual public sync_block + class BLOCKS_API pdu_to_tagged_stream : virtual public tagged_stream_block { public: // gr::blocks::pdu_to_tagged_stream::sptr diff --git a/gr-blocks/lib/abs_XX_impl.cc.t b/gr-blocks/lib/abs_XX_impl.cc.t index 6bb9f149fd..195d8dff3d 100644 --- a/gr-blocks/lib/abs_XX_impl.cc.t +++ b/gr-blocks/lib/abs_XX_impl.cc.t @@ -32,15 +32,16 @@ namespace gr { namespace blocks { - @NAME@::sptr @NAME@::make() + @NAME@::sptr @NAME@::make(size_t vlen) { - return gnuradio::get_initial_sptr(new @NAME_IMPL@()); + return gnuradio::get_initial_sptr(new @NAME_IMPL@(vlen)); } - @NAME_IMPL@::@NAME_IMPL@() + @NAME_IMPL@::@NAME_IMPL@(size_t vlen) : sync_block ("@NAME@", - io_signature::make (1, 1, sizeof (@I_TYPE@)), - io_signature::make (1, 1, sizeof (@O_TYPE@))) + io_signature::make (1, 1, sizeof (@I_TYPE@)*vlen), + io_signature::make (1, 1, sizeof (@O_TYPE@)*vlen)), + d_vlen(vlen) { } @@ -52,7 +53,7 @@ namespace gr { @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; - for(int i=0; i<noutput_items; i++) { + for(size_t i=0; i<noutput_items*d_vlen; i++) { @I_TYPE@ val = iptr[i]; optr[i] = ((val < ((@I_TYPE@)0)) ? -val : val); } diff --git a/gr-blocks/lib/abs_XX_impl.h.t b/gr-blocks/lib/abs_XX_impl.h.t index b31ef5fb31..fa96c84073 100644 --- a/gr-blocks/lib/abs_XX_impl.h.t +++ b/gr-blocks/lib/abs_XX_impl.h.t @@ -32,8 +32,11 @@ namespace gr { class BLOCKS_API @NAME_IMPL@ : public @NAME@ { + private: + size_t d_vlen; + public: - @NAME_IMPL@(); + @NAME_IMPL@(size_t vlen); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-blocks/lib/deinterleave_impl.cc b/gr-blocks/lib/deinterleave_impl.cc index c9d0e9aeda..9e18c35e58 100644 --- a/gr-blocks/lib/deinterleave_impl.cc +++ b/gr-blocks/lib/deinterleave_impl.cc @@ -41,13 +41,20 @@ namespace gr { io_signature::make (1, io_signature::IO_INFINITE, itemsize)), d_itemsize(itemsize), d_blocksize(blocksize), d_current_output(0) { + d_size_bytes = d_itemsize * d_blocksize; set_output_multiple(blocksize); } + void + deinterleave_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items * d_noutputs; + } + bool deinterleave_impl::check_topology(int ninputs, int noutputs) { - set_relative_rate((double)noutputs); + set_relative_rate(1.0/(double)noutputs); d_noutputs = noutputs; return true; } @@ -61,10 +68,29 @@ namespace gr { const char *in = (const char*)input_items[0]; char **out = (char**)&output_items[0]; - memcpy(out[d_current_output], in, d_itemsize * d_blocksize); - consume_each(d_blocksize); - produce(d_current_output, d_blocksize); - d_current_output = (d_current_output + 1) % d_noutputs; + int count = 0, totalcount = noutput_items*d_noutputs; + unsigned int skip = 0; + unsigned int acc = 0; + while(count < totalcount) { + memcpy(out[d_current_output]+skip*d_size_bytes, in, d_size_bytes); + in += d_size_bytes; + produce(d_current_output, d_blocksize); + d_current_output = (d_current_output + 1) % d_noutputs; + + // accumulate times through the loop; increment skip after a + // full pass over the output streams. + // This is separate than d_current_output since we could be in + // the middle of a loop when we exit. + acc++; + if(acc >= d_noutputs) { + skip++; + acc = 0; + } + + // Keep track of our loop counter + count+=d_blocksize; + } + consume_each(totalcount); return WORK_CALLED_PRODUCE; } diff --git a/gr-blocks/lib/deinterleave_impl.h b/gr-blocks/lib/deinterleave_impl.h index 247ee3a018..71a551a69c 100644 --- a/gr-blocks/lib/deinterleave_impl.h +++ b/gr-blocks/lib/deinterleave_impl.h @@ -35,11 +35,12 @@ namespace gr { unsigned int d_blocksize; unsigned int d_current_output; unsigned int d_noutputs; - + unsigned int d_size_bytes; // block size in bytes public: deinterleave_impl(size_t itemsize, unsigned int blocksize); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); bool check_topology(int ninputs, int noutputs); int general_work(int noutput_items, diff --git a/gr-blocks/lib/message_strobe_impl.cc b/gr-blocks/lib/message_strobe_impl.cc index bd0ad80142..b3f1782229 100644 --- a/gr-blocks/lib/message_strobe_impl.cc +++ b/gr-blocks/lib/message_strobe_impl.cc @@ -47,15 +47,15 @@ namespace gr { message_strobe_impl::message_strobe_impl(pmt::pmt_t msg, float period_ms) : block("message_strobe", - io_signature::make(0, 0, 0), - io_signature::make(0, 0, 0)), + io_signature::make(0, 0, 0), + io_signature::make(0, 0, 0)), d_finished(false), d_period_ms(period_ms), d_msg(msg) { message_port_register_out(pmt::mp("strobe")); - d_thread = boost::shared_ptr<boost::thread> - (new boost::thread(boost::bind(&message_strobe_impl::run, this))); + d_thread = boost::shared_ptr<gr::thread::thread> + (new gr::thread::thread(boost::bind(&message_strobe_impl::run, this))); message_port_register_in(pmt::mp("set_msg")); set_msg_handler(pmt::mp("set_msg"), diff --git a/gr-blocks/lib/message_strobe_impl.h b/gr-blocks/lib/message_strobe_impl.h index 7a54680286..0f37cd2e0e 100644 --- a/gr-blocks/lib/message_strobe_impl.h +++ b/gr-blocks/lib/message_strobe_impl.h @@ -31,7 +31,7 @@ namespace gr { class BLOCKS_API message_strobe_impl : public message_strobe { private: - boost::shared_ptr<boost::thread> d_thread; + boost::shared_ptr<gr::thread::thread> d_thread; bool d_finished; float d_period_ms; pmt::pmt_t d_msg; diff --git a/gr-blocks/lib/message_strobe_random_impl.cc b/gr-blocks/lib/message_strobe_random_impl.cc index 80819fc2fc..c62aad1c7a 100644 --- a/gr-blocks/lib/message_strobe_random_impl.cc +++ b/gr-blocks/lib/message_strobe_random_impl.cc @@ -61,8 +61,8 @@ namespace gr { // set up ports message_port_register_out(pmt::mp("strobe")); - d_thread = boost::shared_ptr<boost::thread> - (new boost::thread(boost::bind(&message_strobe_random_impl::run, this))); + d_thread = boost::shared_ptr<gr::thread::thread> + (new gr::thread::thread(boost::bind(&message_strobe_random_impl::run, this))); message_port_register_in(pmt::mp("set_msg")); set_msg_handler(pmt::mp("set_msg"), diff --git a/gr-blocks/lib/message_strobe_random_impl.h b/gr-blocks/lib/message_strobe_random_impl.h index 32eddb592c..2dcaa7effa 100644 --- a/gr-blocks/lib/message_strobe_random_impl.h +++ b/gr-blocks/lib/message_strobe_random_impl.h @@ -36,7 +36,7 @@ namespace gr { class BLOCKS_API message_strobe_random_impl : public message_strobe_random { private: - boost::shared_ptr<boost::thread> d_thread; + boost::shared_ptr<gr::thread::thread> d_thread; bool d_finished; float d_mean_ms; float d_std_ms; diff --git a/gr-blocks/lib/pdu_to_tagged_stream_impl.cc b/gr-blocks/lib/pdu_to_tagged_stream_impl.cc index 8baa9773d6..a8ba5d22b9 100644 --- a/gr-blocks/lib/pdu_to_tagged_stream_impl.cc +++ b/gr-blocks/lib/pdu_to_tagged_stream_impl.cc @@ -32,90 +32,79 @@ namespace gr { namespace blocks { pdu_to_tagged_stream::sptr - pdu_to_tagged_stream::make(pdu::vector_type type, const std::string& lengthtagname) + pdu_to_tagged_stream::make(pdu::vector_type type, const std::string& tsb_tag_key) { - return gnuradio::get_initial_sptr(new pdu_to_tagged_stream_impl(type, lengthtagname)); + return gnuradio::get_initial_sptr(new pdu_to_tagged_stream_impl(type, tsb_tag_key)); } - pdu_to_tagged_stream_impl::pdu_to_tagged_stream_impl(pdu::vector_type type, const std::string& lengthtagname) - : sync_block("pdu_to_tagged_stream", - io_signature::make(0, 0, 0), - io_signature::make(1, 1, pdu::itemsize(type))), - d_itemsize(pdu::itemsize(type)), - d_type(type), - d_tag(pmt::mp(lengthtagname)) + pdu_to_tagged_stream_impl::pdu_to_tagged_stream_impl(pdu::vector_type type, const std::string& tsb_tag_key) + : tagged_stream_block("pdu_to_tagged_stream", + io_signature::make(0, 0, 0), + io_signature::make(1, 1, pdu::itemsize(type)), + tsb_tag_key), + d_itemsize(pdu::itemsize(type)), + d_type(type), + d_curr_len(0) { message_port_register_in(PDU_PORT_ID); } - int - pdu_to_tagged_stream_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + int pdu_to_tagged_stream_impl::calculate_output_stream_length(const gr_vector_int &) { - char *out = (char *)output_items[0]; - int nout = 0; - - // if we have remaining output, send it - if (d_remain.size() > 0) { - nout = std::min((size_t)d_remain.size()/d_itemsize, (size_t)noutput_items); - memcpy(out, &d_remain[0], nout*d_itemsize); - d_remain.erase(d_remain.begin(), d_remain.begin()+nout*d_itemsize); - noutput_items -= nout; - out += nout*d_itemsize; - } - - // if we have space for at least one item output as much as we can - if (noutput_items > 0) { - - // grab a message if one exists - pmt::pmt_t msg(delete_head_nowait(PDU_PORT_ID)); - if (msg.get() == NULL) - return nout; - - // make sure type is valid - if (!pmt::is_pair(msg)) // TODO: implement pdu::is_valid() - throw std::runtime_error("received a malformed pdu message"); - - // grab the components of the pdu message - pmt::pmt_t meta(pmt::car(msg)); - pmt::pmt_t vect(pmt::cdr(msg)); + if (d_curr_len == 0) { + pmt::pmt_t msg(delete_head_nowait(PDU_PORT_ID)); + if (msg.get() == NULL) { + return 0; + } - // compute offset for output tag - uint64_t offset = nitems_written(0) + nout; + if (!pmt::is_pair(msg)) + throw std::runtime_error("received a malformed pdu message"); - // add a tag for pdu length - add_item_tag(0, offset, d_tag, pmt::from_long(pmt::length(vect)), pmt::mp(alias())); + d_curr_meta = pmt::car(msg); + d_curr_vect = pmt::cdr(msg); + d_curr_len = pmt::length(d_curr_vect); + } - // if we recieved metadata add it as tags - if (!pmt::eq(meta, pmt::PMT_NIL) ) { - pmt::pmt_t klist(pmt::dict_keys(meta)); - for(size_t i=0; i<pmt::length(klist); i++){ - pmt::pmt_t k(pmt::nth(i, klist)); - pmt::pmt_t v(pmt::dict_ref(meta, k, pmt::PMT_NIL)); - add_item_tag(0, offset, k, v, pmt::mp(alias())); - } + return d_curr_len; } - // copy vector output - size_t ncopy = std::min((size_t)noutput_items, (size_t)pmt::length(vect)); - size_t nsave = pmt::length(vect) - ncopy; + int + pdu_to_tagged_stream_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + uint8_t *out = (uint8_t*) output_items[0]; - // copy output - size_t io(0); - nout += ncopy; - const uint8_t* ptr = (uint8_t*) uniform_vector_elements(vect, io); - memcpy(out, ptr, ncopy*d_itemsize); + if (d_curr_len == 0) { + return 0; + } - // save leftover items if needed for next work call - if (nsave > 0) { - d_remain.resize(nsave*d_itemsize, 0); - memcpy(&d_remain[0], ptr + ncopy*d_itemsize, nsave*d_itemsize); + // work() should only be called if the current PDU fits entirely + // into the output buffer. + assert(noutput_items >= d_curr_len); + + // Copy vector output + size_t nout = d_curr_len; + size_t io(0); + const uint8_t* ptr = (uint8_t*) uniform_vector_elements(d_curr_vect, io); + memcpy(out, ptr, d_curr_len*d_itemsize); + + // Copy tags + if (!pmt::eq(d_curr_meta, pmt::PMT_NIL) ) { + pmt::pmt_t klist(pmt::dict_keys(d_curr_meta)); + for (size_t i = 0; i < pmt::length(klist); i++) { + pmt::pmt_t k(pmt::nth(i, klist)); + pmt::pmt_t v(pmt::dict_ref(d_curr_meta, k, pmt::PMT_NIL)); + add_item_tag(0, nitems_written(0), k, v, pmt::mp(alias())); } } + // Reset state + d_curr_len = 0; + return nout; - } + } /* work() */ } /* namespace blocks */ } /* namespace gr */ diff --git a/gr-blocks/lib/pdu_to_tagged_stream_impl.h b/gr-blocks/lib/pdu_to_tagged_stream_impl.h index 4bfd9cfd4e..99f68147c8 100644 --- a/gr-blocks/lib/pdu_to_tagged_stream_impl.h +++ b/gr-blocks/lib/pdu_to_tagged_stream_impl.h @@ -32,18 +32,23 @@ namespace gr { { size_t d_itemsize; pdu::vector_type d_type; - std::vector<uint8_t> d_remain; - pmt::pmt_t d_tag; + pmt::pmt_t d_curr_meta; + pmt::pmt_t d_curr_vect; + size_t d_curr_len; public: pdu_to_tagged_stream_impl(pdu::vector_type type, const std::string& lengthtagname="packet_len"); + int calculate_output_stream_length(const gr_vector_int &ninput_items); + int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); }; } /* namespace blocks */ } /* namespace gr */ -#endif +#endif /* INCLUDED_PDU_TO_TAGGED_STREAM_IMPL_H */ diff --git a/gr-blocks/lib/qa_block_tags.cc b/gr-blocks/lib/qa_block_tags.cc index c554425f8e..d794f8edfe 100644 --- a/gr-blocks/lib/qa_block_tags.cc +++ b/gr-blocks/lib/qa_block_tags.cc @@ -33,20 +33,32 @@ #include <gnuradio/blocks/annotator_alltoall.h> #include <gnuradio/blocks/annotator_1to1.h> #include <gnuradio/blocks/keep_one_in_n.h> -#include <gnuradio/tags.h> // ---------------------------------------------------------------- // set to 1 to turn on debug output // The debug output fully checks that the tags seen are what are expected. While -// this behavior currently works with our implementation, there is no guarentee +// this behavior currently works with our implementation, there is no guarantee // that the tags will be coming in this specific order, so it's dangerous to // rely on this as a test of the tag system working. We would really want to // tags we know we should see and then test that they all occur once, but in no // particular order. #define QA_TAGS_DEBUG 0 +gr::tag_t make_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t value, pmt::pmt_t srcid) { + gr::tag_t result; + result.offset = offset; + result.key = key; + result.value = value; + result.srcid = srcid; + return result; +} + +std::ostream& +operator << (std::ostream& os, const gr::tag_t &t) { + return os; +} void qa_block_tags::t0() { @@ -59,8 +71,6 @@ qa_block_tags::t0() tb->connect(src, 0, head, 0); tb->connect(head, 0, snk, 0); - //CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::runtime_error); - //CPPUNIT_ASSERT_THROW(src->nitems_written(0), std::runtime_error); CPPUNIT_ASSERT_EQUAL(src->nitems_read(0), (uint64_t)0); CPPUNIT_ASSERT_EQUAL(src->nitems_written(0), (uint64_t)0); @@ -117,39 +127,39 @@ qa_block_tags::t1() str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt::pmt_t expected_tags3[8]; - expected_tags3[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags3[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags3[2] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags3[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags3[4] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags3[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags3[6] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags3[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - - pmt::pmt_t expected_tags4[8]; - expected_tags4[0] = mp(pmt::from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); - expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[2] = mp(pmt::from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[4] = mp(pmt::from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[6] = mp(pmt::from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); - expected_tags4[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + gr::tag_t expected_tags3[8]; + expected_tags3[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[2] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags3[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[4] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags3[6] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags3[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + + gr::tag_t expected_tags4[8]; + expected_tags4[0] = make_tag(0, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[2] = make_tag(10000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[4] = make_tag(20000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[6] = make_tag(30000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); std::cout << std::endl << "qa_block_tags::t1" << std::endl; // For annotator 3, we know it gets tags from ann0 and ann1, test this for(size_t i = 0; i < tags3.size(); i++) { std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags3[i]), pmt::write_string(expected_tags3[i])); + CPPUNIT_ASSERT_EQUAL(tags3[i], expected_tags3[i]); } // For annotator 4, we know it gets tags from ann0 and ann2, test this std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(tags4[i], expected_tags4[i]); } #endif } @@ -207,33 +217,33 @@ qa_block_tags::t2 () str0 << ann0->name() << ann0->unique_id(); str1 << ann1->name() << ann1->unique_id(); - pmt::pmt_t expected_tags2[12]; - expected_tags2[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags2[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags2[2] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags2[3] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags2[4] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags2[5] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags2[6] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(6)); - expected_tags2[7] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags2[8] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags2[9] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(9)); - expected_tags2[10] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - expected_tags2[11] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); - - pmt::pmt_t expected_tags4[12]; - expected_tags4[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(2)); - expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags4[2] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(5)); - expected_tags4[4] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[6] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(8)); - expected_tags4[7] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags4[8] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[9] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(11)); - expected_tags4[10] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - expected_tags4[11] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + gr::tag_t expected_tags2[12]; + expected_tags2[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[2] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags2[3] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[4] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags2[5] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[6] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(6)); + expected_tags2[7] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags2[8] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags2[9] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(9)); + expected_tags2[10] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + expected_tags2[11] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); + + gr::tag_t expected_tags4[12]; + expected_tags4[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags4[2] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[3] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[4] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[5] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[6] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(8)); + expected_tags4[7] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags4[8] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[9] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(11)); + expected_tags4[10] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + expected_tags4[11] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); std::cout << std::endl << "qa_block_tags::t2" << std::endl; @@ -243,13 +253,13 @@ qa_block_tags::t2 () // inconceivable for ann3 to have it wrong. for(size_t i = 0; i < tags2.size(); i++) { std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags2[i]), pmt::write_string(expected_tags2[i])); + CPPUNIT_ASSERT_EQUAL(tags2[i], expected_tags2[i]); } std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(tags4[i], expected_tags4[i]); } #endif } @@ -301,39 +311,39 @@ qa_block_tags::t3() str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt::pmt_t expected_tags3[8]; - expected_tags3[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags3[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags3[2] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags3[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags3[4] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags3[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags3[6] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags3[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - - pmt::pmt_t expected_tags4[8]; - expected_tags4[0] = mp(pmt::from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); - expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[2] = mp(pmt::from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[4] = mp(pmt::from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[6] = mp(pmt::from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); - expected_tags4[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + gr::tag_t expected_tags3[8]; + expected_tags3[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[2] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags3[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[4] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags3[6] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags3[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + + gr::tag_t expected_tags4[8]; + expected_tags4[0] = make_tag(0, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[2] = make_tag(10000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[4] = make_tag(20000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[6] = make_tag(30000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); std::cout << std::endl << "qa_block_tags::t3" << std::endl; // For annotator 3, we know it gets tags from ann0 and ann1, test this for(size_t i = 0; i < tags3.size(); i++) { std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags3[i]), pmt::write_string(expected_tags3[i])); + CPPUNIT_ASSERT_EQUAL(tags3[i], expected_tags3[i]); } // For annotator 4, we know it gets tags from ann0 and ann2, test this std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(tags4[i], expected_tags4[i]); } #endif } @@ -409,23 +419,23 @@ qa_block_tags::t5() str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt_t expected_tags1[5]; - expected_tags1[0] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags1[1] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(1)); - expected_tags1[2] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags1[3] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(3)); - - pmt_t expected_tags2[10]; - expected_tags2[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags2[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags2[2] = mp(pmt::from_uint64(1000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags2[3] = mp(pmt::from_uint64(1000), mp(str0.str()), mp("seq"), mp(1)); - expected_tags2[4] = mp(pmt::from_uint64(2000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags2[5] = mp(pmt::from_uint64(2000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags2[6] = mp(pmt::from_uint64(3000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags2[7] = mp(pmt::from_uint64(3000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags2[8] = mp(pmt::from_uint64(4000), mp(str1.str()), mp("seq"), mp(4)); - expected_tags2[9] = mp(pmt::from_uint64(4000), mp(str0.str()), mp("seq"), mp(4)); + gr::tag_t expected_tags1[5]; + expected_tags1[0] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags1[1] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags1[2] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags1[3] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + + gr::tag_t expected_tags2[10]; + expected_tags2[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[2] = make_tag(1000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags2[3] = make_tag(1000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags2[4] = make_tag(2000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags2[5] = make_tag(2000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags2[6] = make_tag(3000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[7] = make_tag(3000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[8] = make_tag(4000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags2[9] = make_tag(4000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); std::cout << std::endl << "qa_block_tags::t5" << std::endl; @@ -433,7 +443,7 @@ qa_block_tags::t5() std::cout << "tags1.size(): " << tags1.size() << std::endl; for(size_t i = 0; i < tags1.size(); i++) { std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags1[i]), pmt::write_string(expected_tags1[i])); + CPPUNIT_ASSERT_EQUAL(tags1[i], expected_tags1[i]); } // annotator 2 gets tags from annotators 0 and 1 @@ -441,7 +451,7 @@ qa_block_tags::t5() std::cout << "tags2.size(): " << tags2.size() << std::endl; for(size_t i = 0; i < tags2.size(); i++) { std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags2[i]), pmt::write_string(expected_tags2[i])); + CPPUNIT_ASSERT_EQUAL(tags2[i], expected_tags2[i]); } #endif } diff --git a/gr-blocks/lib/throttle_impl.cc b/gr-blocks/lib/throttle_impl.cc index f46decee11..7c24f80ae1 100644 --- a/gr-blocks/lib/throttle_impl.cc +++ b/gr-blocks/lib/throttle_impl.cc @@ -57,6 +57,14 @@ namespace gr { { } + bool + throttle_impl::start() + { + d_start = boost::get_system_time(); + d_total_samples = 0; + return block::start(); + } + void throttle_impl::set_sample_rate(double rate) { diff --git a/gr-blocks/lib/throttle_impl.h b/gr-blocks/lib/throttle_impl.h index c5e43d7564..6afacbba5d 100644 --- a/gr-blocks/lib/throttle_impl.h +++ b/gr-blocks/lib/throttle_impl.h @@ -41,6 +41,9 @@ namespace gr { throttle_impl(size_t itemsize, double samples_per_sec, bool ignore_tags=true); ~throttle_impl(); + // Overloading gr::block::start to reset timer + bool start(); + void setup_rpc(); void set_sample_rate(double rate); diff --git a/gr-blocks/lib/udp_sink_impl.cc b/gr-blocks/lib/udp_sink_impl.cc index ae6488f6dd..6989fdb27c 100644 --- a/gr-blocks/lib/udp_sink_impl.cc +++ b/gr-blocks/lib/udp_sink_impl.cc @@ -76,13 +76,12 @@ namespace gr { std::string s_port = (boost::format("%d")%port).str(); if(host.size() > 0) { boost::asio::ip::udp::resolver resolver(d_io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), - host, s_port, + boost::asio::ip::udp::resolver::query query(host, s_port, boost::asio::ip::resolver_query_base::passive); d_endpoint = *resolver.resolve(query); d_socket = new boost::asio::ip::udp::socket(d_io_service); - d_socket->open(boost::asio::ip::udp::v4()); + d_socket->open(d_endpoint.protocol()); boost::asio::socket_base::reuse_address roption(true); d_socket->set_option(roption); diff --git a/gr-blocks/lib/udp_source_impl.cc b/gr-blocks/lib/udp_source_impl.cc index c3ab8953e7..ca4018464d 100644 --- a/gr-blocks/lib/udp_source_impl.cc +++ b/gr-blocks/lib/udp_source_impl.cc @@ -84,8 +84,7 @@ namespace gr { if(host.size() > 0) { boost::asio::ip::udp::resolver resolver(d_io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), - d_host, s_port, + boost::asio::ip::udp::resolver::query query(d_host, s_port, boost::asio::ip::resolver_query_base::passive); d_endpoint = *resolver.resolve(query); diff --git a/gr-blocks/lib/vector_source_X_impl.cc.t b/gr-blocks/lib/vector_source_X_impl.cc.t index 93f672bfb9..cb17c70d63 100644 --- a/gr-blocks/lib/vector_source_X_impl.cc.t +++ b/gr-blocks/lib/vector_source_X_impl.cc.t @@ -106,7 +106,7 @@ namespace gr { optr += size; for(unsigned t = 0; t < d_tags.size(); t++) { add_item_tag(0, nitems_written(0)+i+d_tags[t].offset, - d_tags[t].key, d_tags[t].value); + d_tags[t].key, d_tags[t].value, d_tags[t].srcid); } } } diff --git a/gr-blocks/python/blocks/qa_pdu.py b/gr-blocks/python/blocks/qa_pdu.py index 5a29e04735..bbee3605ba 100755 --- a/gr-blocks/python/blocks/qa_pdu.py +++ b/gr-blocks/python/blocks/qa_pdu.py @@ -99,8 +99,6 @@ class test_pdu(gr_unittest.TestCase): msg = pmt.cons( pmt.PMT_NIL, pmt.init_f32vector(10, src_data)) src.to_basic_block()._post(port, msg) - src.set_max_noutput_items(5) - self.tb.start() #ideally, would wait until we get ten samples time.sleep(0.2) diff --git a/gr-digital/grc/digital_costas_loop_cc.xml b/gr-digital/grc/digital_costas_loop_cc.xml index 668c43dec6..40db3a4a6f 100644 --- a/gr-digital/grc/digital_costas_loop_cc.xml +++ b/gr-digital/grc/digital_costas_loop_cc.xml @@ -5,34 +5,60 @@ ################################################### --> <block> - <name>Costas Loop</name> - <key>digital_costas_loop_cc</key> - <import>from gnuradio import digital</import> - <make>digital.costas_loop_cc($w, $order)</make> - <callback>set_loop_bandwidth($w)</callback> - <param> - <name>Loop Bandwidth</name> - <key>w</key> - <type>real</type> - </param> - <param> - <name>Order</name> - <key>order</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> + <name>Costas Loop</name> + <key>digital_costas_loop_cc</key> + <import>from gnuradio import digital</import> + <make>digital.costas_loop_cc($w, $order, $use_snr)</make> + <callback>set_loop_bandwidth($w)</callback> - <!-- Optional Outputs --> - <source> - <name>frequency</name> - <type>float</type> - <optional>1</optional> - </source> + <param> + <name>Loop Bandwidth</name> + <key>w</key> + <type>real</type> + </param> + + <param> + <name>Order</name> + <key>order</key> + <type>int</type> + </param> + + <param> + <name>Use SNR</name> + <key>use_snr</key> + <value>False</value> + <type>enum</type> + <hide>part</hide> + <option> + <name>Yes</name> + <key>True</key> + </option> + <option> + <name>No</name> + <key>False</key> + </option> + </param> + + <sink> + <name>in</name> + <type>complex</type> + </sink> + + <sink> + <name>noise</name> + <type>message</type> + <optional>1</optional> + </sink> + + <source> + <name>out</name> + <type>complex</type> + </source> + + <!-- Optional Outputs --> + <source> + <name>frequency</name> + <type>float</type> + <optional>1</optional> + </source> </block> diff --git a/gr-digital/include/gnuradio/digital/costas_loop_cc.h b/gr-digital/include/gnuradio/digital/costas_loop_cc.h index d924d969b7..ff5b9b993a 100644 --- a/gr-digital/include/gnuradio/digital/costas_loop_cc.h +++ b/gr-digital/include/gnuradio/digital/costas_loop_cc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2011,2012 Free Software Foundation, Inc. + * Copyright 2006,2011,2012,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -58,6 +58,9 @@ namespace gr { * The Costas loop can have two output streams: * \li stream 1 (required) is the baseband I and Q; * \li stream 2 (optional) is the normalized frequency of the loop + * + * There is a single optional message input: + * \li noise: A noise floor estimate used to calculate the SNR of a sample. */ class DIGITAL_API costas_loop_cc : virtual public sync_block, @@ -72,8 +75,10 @@ namespace gr { * * \param loop_bw internal 2nd order loop bandwidth (~ 2pi/100) * \param order the loop order, either 2, 4, or 8 + * \param use_snr Use or ignore SNR estimates (from noise message port) + * in measurements; also uses tanh instead of slicing. */ - static sptr make(float loop_bw, int order); + static sptr make(float loop_bw, int order, bool use_snr=false); /*! * Returns the current value of the loop error. diff --git a/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h b/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h index 2715316a93..be38b6f8ae 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h +++ b/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h @@ -58,18 +58,19 @@ namespace gr { /*! * \param equalizer The equalizer object that will do the actual work * \param cp_len Length of the cyclic prefix in samples (required to correct the frequency offset) - * \param len_tag_key Length tag key + * \param tsb_key TSB key * \param propagate_channel_state If true, the channel state after the last symbol * will be added to the first symbol as a tag - * \param fixed_frame_len Set if the frame length is fixed throughout, - * helps with book keeping. + * \param fixed_frame_len Set if the frame length is fixed. When this value is given, + * the TSB tag key can be left empty, but it is useful even + * when using tagged streams at the input. */ static sptr make( - ofdm_equalizer_base::sptr equalizer, - int cp_len, - const std::string &len_tag_key = "frame_len", - bool propagate_channel_state=false, - int fixed_frame_len=0 + ofdm_equalizer_base::sptr equalizer, + int cp_len, + const std::string &tsb_key="frame_len", + bool propagate_channel_state=false, + int fixed_frame_len=0 ); }; diff --git a/gr-digital/lib/costas_loop_cc_impl.cc b/gr-digital/lib/costas_loop_cc_impl.cc index 36f95ac022..a53045ac55 100644 --- a/gr-digital/lib/costas_loop_cc_impl.cc +++ b/gr-digital/lib/costas_loop_cc_impl.cc @@ -35,37 +35,52 @@ namespace gr { namespace digital { costas_loop_cc::sptr - costas_loop_cc::make(float loop_bw, int order) + costas_loop_cc::make(float loop_bw, int order, bool use_snr) { return gnuradio::get_initial_sptr - (new costas_loop_cc_impl(loop_bw, order)); + (new costas_loop_cc_impl(loop_bw, order, use_snr)); } - costas_loop_cc_impl::costas_loop_cc_impl(float loop_bw, int order) + costas_loop_cc_impl::costas_loop_cc_impl(float loop_bw, int order, bool use_snr) : sync_block("costas_loop_cc", io_signature::make(1, 1, sizeof(gr_complex)), io_signature::make2(1, 2, sizeof(gr_complex), sizeof(float))), blocks::control_loop(loop_bw, 1.0, -1.0), - d_order(order), d_error(0), d_phase_detector(NULL) + d_order(order), d_error(0), d_noise(1.0), d_phase_detector(NULL) { // Set up the phase detector to use based on the constellation order switch(d_order) { case 2: - d_phase_detector = &costas_loop_cc_impl::phase_detector_2; + if(use_snr) + d_phase_detector = &costas_loop_cc_impl::phase_detector_snr_2; + else + d_phase_detector = &costas_loop_cc_impl::phase_detector_2; break; case 4: - d_phase_detector = &costas_loop_cc_impl::phase_detector_4; + if(use_snr) + d_phase_detector = &costas_loop_cc_impl::phase_detector_snr_4; + else + d_phase_detector = &costas_loop_cc_impl::phase_detector_4; break; case 8: - d_phase_detector = &costas_loop_cc_impl::phase_detector_8; + if(use_snr) + d_phase_detector = &costas_loop_cc_impl::phase_detector_snr_8; + else + d_phase_detector = &costas_loop_cc_impl::phase_detector_8; break; default: throw std::invalid_argument("order must be 2, 4, or 8"); break; } + + message_port_register_in(pmt::mp("noise")); + set_msg_handler( + pmt::mp("noise"), + boost::bind(&costas_loop_cc_impl::handle_set_noise, + this, _1)); } costas_loop_cc_impl::~costas_loop_cc_impl() @@ -114,11 +129,50 @@ namespace gr { } float + costas_loop_cc_impl::phase_detector_snr_8(gr_complex sample) const + { + float K = (sqrt(2.0) - 1); + float snr = abs(sample)*abs(sample) / d_noise; + if(fabsf(sample.real()) >= fabsf(sample.imag())) { + return ((blocks::tanhf_lut(snr*sample.real()) * sample.imag()) - + (blocks::tanhf_lut(snr*sample.imag()) * sample.real() * K)); + } + else { + return ((blocks::tanhf_lut(snr*sample.real()) * sample.imag() * K) - + (blocks::tanhf_lut(snr*sample.imag()) * sample.real())); + } + } + + float + costas_loop_cc_impl::phase_detector_snr_4(gr_complex sample) const + { + float snr = abs(sample)*abs(sample) / d_noise; + return ((blocks::tanhf_lut(snr*sample.real()) * sample.imag()) - + (blocks::tanhf_lut(snr*sample.imag()) * sample.real())); + } + + float + costas_loop_cc_impl::phase_detector_snr_2(gr_complex sample) const + { + float snr = abs(sample)*abs(sample) / d_noise; + return blocks::tanhf_lut(snr*sample.real()) * sample.imag(); + } + + float costas_loop_cc_impl::error() const { return d_error; } + void + costas_loop_cc_impl::handle_set_noise(pmt::pmt_t msg) + { + if(pmt::is_real(msg)) { + d_noise = pmt::to_double(msg); + d_noise = powf(10.0f, d_noise/10.0f); + } + } + int costas_loop_cc_impl::work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-digital/lib/costas_loop_cc_impl.h b/gr-digital/lib/costas_loop_cc_impl.h index 665724236b..ebd05e2e93 100644 --- a/gr-digital/lib/costas_loop_cc_impl.h +++ b/gr-digital/lib/costas_loop_cc_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2011,2012 Free Software Foundation, Inc. + * Copyright 2006,2011,2012,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -34,33 +34,68 @@ namespace gr { private: int d_order; float d_error; + float d_noise; - /*! \brief the phase detector circuit for 8th-order PSK loops + /*! \brief the phase detector circuit for 8th-order PSK loops. + * * \param sample complex sample * \return the phase error */ float phase_detector_8(gr_complex sample) const; // for 8PSK - /*! \brief the phase detector circuit for fourth-order loops + /*! \brief the phase detector circuit for fourth-order loops. + * * \param sample complex sample * \return the phase error */ float phase_detector_4(gr_complex sample) const; // for QPSK - /*! \brief the phase detector circuit for second-order loops + /*! \brief the phase detector circuit for second-order loops. + * * \param sample a complex sample * \return the phase error */ float phase_detector_2(gr_complex sample) const; // for BPSK + + /*! \brief the phase detector circuit for 8th-order PSK + * loops. Uses tanh instead of slicing and the noise estimate + * from the message port to estimated SNR of the samples. + * + * \param sample complex sample + * \return the phase error + */ + float phase_detector_snr_8(gr_complex sample) const; // for 8PSK + + /*! \brief the phase detector circuit for fourth-order + * loops. Uses tanh instead of slicing and the noise estimate + * from the message port to estimated SNR of the samples. + * + * \param sample complex sample + * \return the phase error + */ + float phase_detector_snr_4(gr_complex sample) const; // for QPSK + + /*! \brief the phase detector circuit for second-order + * loops. Uses tanh instead of slicing and the noise estimate + * from the message port to estimated SNR of the samples. + * + * \param sample a complex sample + * \return the phase error + */ + float phase_detector_snr_2(gr_complex sample) const; // for BPSK + + float (costas_loop_cc_impl::*d_phase_detector)(gr_complex sample) const; public: - costas_loop_cc_impl(float loop_bw, int order); + costas_loop_cc_impl(float loop_bw, int order, bool use_snr=false); ~costas_loop_cc_impl(); float error() const; + void handle_set_noise(pmt::pmt_t msg); + void setup_rpc(); int work(int noutput_items, diff --git a/gr-digital/lib/header_payload_demux_impl.cc b/gr-digital/lib/header_payload_demux_impl.cc index 15308c0be1..160f54036d 100644 --- a/gr-digital/lib/header_payload_demux_impl.cc +++ b/gr-digital/lib/header_payload_demux_impl.cc @@ -1,5 +1,5 @@ /* -*- c++ -*- */ -/* Copyright 2012,2013 Free Software Foundation, Inc. +/* Copyright 2012-2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -300,20 +300,19 @@ namespace gr { } } if (d_uses_trigger_tag) { - std::vector<tag_t> tags; - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items, d_trigger_tag_key); - uint64_t min_offset = ULLONG_MAX; - int tag_index = -1; - for (unsigned i = 0; i < tags.size(); i++) { - if (tags[i].offset < min_offset) { - tag_index = (int) i; - min_offset = tags[i].offset; - } - } - if (tag_index != -1) { - remove_item_tag(0, tags[tag_index]); - return min_offset - nitems_read(0); - } + std::vector<tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items, d_trigger_tag_key); + uint64_t min_offset = ULLONG_MAX; + int tag_index = -1; + for (unsigned i = 0; i < tags.size(); i++) { + if (tags[i].offset < min_offset) { + tag_index = (int) i; + min_offset = tags[i].offset; + } + } + if (tag_index != -1) { + return min_offset - nitems_read(0); + } } return -1; } /* find_trigger_signal() */ @@ -388,26 +387,30 @@ namespace gr { // Copy tags std::vector<tag_t> tags; get_tags_in_range( - tags, 0, - nitems_read(0), - nitems_read(0) + n_symbols * (d_items_per_symbol + d_gi) + tags, 0, + nitems_read(0), + nitems_read(0) + n_symbols * (d_items_per_symbol + d_gi) ); - for (unsigned t = 0; t < tags.size(); t++) { - int new_offset = tags[t].offset - nitems_read(0); - if (d_output_symbols) { - new_offset /= (d_items_per_symbol + d_gi); - } else if (d_gi) { - int pos_on_symbol = (new_offset % (d_items_per_symbol + d_gi)) - d_gi; - if (pos_on_symbol < 0) { - pos_on_symbol = 0; - } - new_offset = (new_offset / (d_items_per_symbol + d_gi)) + pos_on_symbol; - } - add_item_tag(port, - nitems_written(port) + new_offset, - tags[t].key, - tags[t].value - ); + for (size_t t = 0; t < tags.size(); t++) { + // The trigger tag is *not* propagated + if (tags[t].key == d_trigger_tag_key) { + continue; + } + int new_offset = tags[t].offset - nitems_read(0); + if (d_output_symbols) { + new_offset /= (d_items_per_symbol + d_gi); + } else if (d_gi) { + int pos_on_symbol = (new_offset % (d_items_per_symbol + d_gi)) - d_gi; + if (pos_on_symbol < 0) { + pos_on_symbol = 0; + } + new_offset = (new_offset / (d_items_per_symbol + d_gi)) + pos_on_symbol; + } + add_item_tag(port, + nitems_written(port) + new_offset, + tags[t].key, + tags[t].value + ); } } /* copy_n_symbols() */ diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc index 4446306a8b..70e840d778 100644 --- a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc +++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc @@ -29,6 +29,9 @@ #define M_TWOPI (2*M_PI) +static const pmt::pmt_t CARR_OFFSET_KEY = pmt::mp("ofdm_sync_carr_offset"); +static const pmt::pmt_t CHAN_TAPS_KEY = pmt::mp("ofdm_sync_chan_taps"); + namespace gr { namespace digital { @@ -36,14 +39,14 @@ namespace gr { ofdm_frame_equalizer_vcvc::make( ofdm_equalizer_base::sptr equalizer, int cp_len, - const std::string &len_tag_key, + const std::string &tsb_key, bool propagate_channel_state, int fixed_frame_len ) { return gnuradio::get_initial_sptr ( new ofdm_frame_equalizer_vcvc_impl( - equalizer, cp_len, len_tag_key, propagate_channel_state, fixed_frame_len + equalizer, cp_len, tsb_key, propagate_channel_state, fixed_frame_len ) ); } @@ -51,13 +54,13 @@ namespace gr { ofdm_frame_equalizer_vcvc_impl::ofdm_frame_equalizer_vcvc_impl( ofdm_equalizer_base::sptr equalizer, int cp_len, - const std::string &len_tag_key, + const std::string &tsb_key, bool propagate_channel_state, int fixed_frame_len ) : tagged_stream_block("ofdm_frame_equalizer_vcvc", io_signature::make(1, 1, sizeof (gr_complex) * equalizer->fft_len()), io_signature::make(1, 1, sizeof (gr_complex) * equalizer->fft_len()), - len_tag_key), + tsb_key), d_fft_len(equalizer->fft_len()), d_cp_len(cp_len), d_eq(equalizer), @@ -65,16 +68,18 @@ namespace gr { d_fixed_frame_len(fixed_frame_len), d_channel_state(equalizer->fft_len(), gr_complex(1, 0)) { - if (len_tag_key.empty() && fixed_frame_len == 0) { - throw std::invalid_argument("Either specify a length tag or a frame length!"); + if (tsb_key.empty() && fixed_frame_len == 0) { + throw std::invalid_argument("Either specify a TSB tag or a fixed frame length!"); } if (d_fixed_frame_len < 0) { - throw std::invalid_argument("Invalid frame length!"); + throw std::invalid_argument("Invalid frame length!"); } if (d_fixed_frame_len) { - set_output_multiple(d_fixed_frame_len); + set_output_multiple(d_fixed_frame_len); } set_relative_rate(1.0); + // Really, we have TPP_ONE_TO_ONE, but the channel state is not propagated + set_tag_propagation_policy(TPP_DONT); } ofdm_frame_equalizer_vcvc_impl::~ofdm_frame_equalizer_vcvc_impl() @@ -83,18 +88,17 @@ namespace gr { void ofdm_frame_equalizer_vcvc_impl::parse_length_tags( - const std::vector<std::vector<tag_t> > &tags, - gr_vector_int &n_input_items_reqd - ){ + const std::vector<std::vector<tag_t> > &tags, + gr_vector_int &n_input_items_reqd + ) { if (d_fixed_frame_len) { - n_input_items_reqd[0] = d_fixed_frame_len; + n_input_items_reqd[0] = d_fixed_frame_len; } else { - for (unsigned k = 0; k < tags[0].size(); k++) { - if (tags[0][k].key == pmt::string_to_symbol(d_length_tag_key_str)) { - n_input_items_reqd[0] = pmt::to_long(tags[0][k].value); - remove_item_tag(0, tags[0][k]); - } - } + for (unsigned k = 0; k < tags[0].size(); k++) { + if (tags[0][k].key == pmt::string_to_symbol(d_length_tag_key_str)) { + n_input_items_reqd[0] = pmt::to_long(tags[0][k].value); + } + } } } @@ -114,15 +118,14 @@ namespace gr { } std::vector<tag_t> tags; - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); + get_tags_in_window(tags, 0, 0, 1); for (unsigned i = 0; i < tags.size(); i++) { - if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_chan_taps") { - d_channel_state = pmt::c32vector_elements(tags[i].value); - remove_item_tag(0, tags[i]); - } - if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_carr_offset") { - carrier_offset = pmt::to_long(tags[i].value); - } + if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_chan_taps") { + d_channel_state = pmt::c32vector_elements(tags[i].value); + } + if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_carr_offset") { + carrier_offset = pmt::to_long(tags[i].value); + } } // Copy the frame and the channel state vector such that the symbols are shifted to the correct position @@ -157,7 +160,16 @@ namespace gr { // Update the channel state regarding the frequency offset phase_correction = gr_expj(M_TWOPI * carrier_offset * d_cp_len / d_fft_len * frame_len); for (int k = 0; k < d_fft_len; k++) { - d_channel_state[k] *= phase_correction; + d_channel_state[k] *= phase_correction; + } + + // Propagate tags (except for the channel state and the TSB tag) + get_tags_in_window(tags, 0, 0, frame_len); + for (size_t i = 0; i < tags.size(); i++) { + if (tags[i].key != CHAN_TAPS_KEY + and tags[i].key != pmt::mp(d_length_tag_key_str)) { + add_item_tag(0, tags[i]); + } } // Housekeeping diff --git a/gr-digital/lib/ofdm_serializer_vcc_impl.cc b/gr-digital/lib/ofdm_serializer_vcc_impl.cc index f6c796d3c5..1398dcd2a1 100644 --- a/gr-digital/lib/ofdm_serializer_vcc_impl.cc +++ b/gr-digital/lib/ofdm_serializer_vcc_impl.cc @@ -1,5 +1,5 @@ /* -*- c++ -*- */ -/* Copyright 2012 Free Software Foundation, Inc. +/* Copyright 2012,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -157,55 +157,57 @@ namespace gr { std::vector<tag_t> tags; // Packet mode if (!d_length_tag_key_str.empty()) { - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); - for (unsigned i = 0; i < tags.size(); i++) { - if (tags[i].key == d_carr_offset_key) { - carr_offset = pmt::to_long(tags[i].value); - } - if (tags[i].key == d_packet_len_tag_key) { - packet_length = pmt::to_long(tags[i].value); - remove_item_tag(0, tags[i]); - } - } + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); + for (unsigned i = 0; i < tags.size(); i++) { + if (tags[i].key == d_carr_offset_key) { + carr_offset = pmt::to_long(tags[i].value); + } + if (tags[i].key == d_packet_len_tag_key) { + packet_length = pmt::to_long(tags[i].value); + } + } } else { - // recalc frame length from noutput_items - frame_length = 0; - int sym_per_frame = 0; - while ((sym_per_frame + d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size()) < (size_t)noutput_items) { - frame_length++; - sym_per_frame += d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size(); - } + // recalc frame length from noutput_items + frame_length = 0; + int sym_per_frame = 0; + while ((sym_per_frame + d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size()) < (size_t)noutput_items) { + frame_length++; + sym_per_frame += d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size(); + } } // Copy symbols int n_out_symbols = 0; for (int i = 0; i < frame_length; i++) { - // Copy all tags associated with this input OFDM symbol onto the first output symbol - get_tags_in_range(tags, 0, - nitems_read(0)+i, - nitems_read(0)+i+1 - ); - for (unsigned t = 0; t < tags.size(); t++) { - add_item_tag(0, nitems_written(0)+n_out_symbols, - tags[t].key, - tags[t].value - ); - } - for (unsigned k = 0; k < d_occupied_carriers[d_curr_set].size(); k++) { - out[n_out_symbols++] = in[i * d_fft_len + d_occupied_carriers[d_curr_set][k] + carr_offset]; - } - if (packet_length && n_out_symbols > packet_length) { - n_out_symbols = packet_length; - break; - } - d_curr_set = (d_curr_set + 1) % d_occupied_carriers.size(); + // Copy all tags associated with this input OFDM symbol onto the first output symbol + get_tags_in_range(tags, 0, + nitems_read(0)+i, + nitems_read(0)+i+1 + ); + for (size_t t = 0; t < tags.size(); t++) { + // The packet length tag is not propagated + if (tags[t].key != d_packet_len_tag_key) { + add_item_tag(0, nitems_written(0)+n_out_symbols, + tags[t].key, + tags[t].value + ); + } + } + for (unsigned k = 0; k < d_occupied_carriers[d_curr_set].size(); k++) { + out[n_out_symbols++] = in[i * d_fft_len + d_occupied_carriers[d_curr_set][k] + carr_offset]; + } + if (packet_length && n_out_symbols > packet_length) { + n_out_symbols = packet_length; + break; + } + d_curr_set = (d_curr_set + 1) % d_occupied_carriers.size(); } // Housekeeping if (d_length_tag_key_str.empty()) { - consume_each(frame_length); + consume_each(frame_length); } else { - d_curr_set = d_symbols_skipped; + d_curr_set = d_symbols_skipped; } return n_out_symbols; diff --git a/gr-digital/python/digital/qa_costas_loop_cc.py b/gr-digital/python/digital/qa_costas_loop_cc.py index 9ecb017599..e48f45cc22 100755 --- a/gr-digital/python/digital/qa_costas_loop_cc.py +++ b/gr-digital/python/digital/qa_costas_loop_cc.py @@ -1,24 +1,24 @@ #!/usr/bin/env python # # Copyright 2011,2013 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. -# +# import random import cmath @@ -46,7 +46,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): self.tb.connect(self.src, self.test, self.snk) self.tb.run() - + expected_result = data dst_data = self.snk.data() self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 5) @@ -77,7 +77,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): rot = cmath.exp(0.2j) # some small rotation data = [complex(2*random.randint(0,1)-1, 0) for i in xrange(100)] - + N = 40 # settling time expected_result = data[N:] data = [rot*d for d in data] @@ -89,7 +89,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): self.tb.run() dst_data = self.snk.data()[N:] - + # generously compare results; the loop will converge near to, but # not exactly on, the target data self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 2) @@ -103,7 +103,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): rot = cmath.exp(0.2j) # some small rotation data = [complex(2*random.randint(0,1)-1, 2*random.randint(0,1)-1) for i in xrange(100)] - + N = 40 # settling time expected_result = data[N:] data = [rot*d for d in data] @@ -130,7 +130,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): const = psk.psk_constellation(order) data = [random.randint(0,7) for i in xrange(100)] data = [2*rot*const.points()[d] for d in data] - + N = 40 # settling time expected_result = data[N:] @@ -144,7 +144,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): self.tb.run() dst_data = self.snk.data()[N:] - + # generously compare results; the loop will converge near to, but # not exactly on, the target data self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 2) diff --git a/gr-digital/python/digital/qa_header_payload_demux.py b/gr-digital/python/digital/qa_header_payload_demux.py index 0b754fe248..8006d4442e 100755 --- a/gr-digital/python/digital/qa_header_payload_demux.py +++ b/gr-digital/python/digital/qa_header_payload_demux.py @@ -113,6 +113,86 @@ class qa_header_payload_demux (gr_unittest.TestCase): ] self.assertEqual(expected_tags_payload, ptags_payload) + def test_001_t_tags (self): + """ Like the previous test, but use a trigger tag instead of + a trigger signal. + """ + n_zeros = 1 + header = (1, 2, 3) + payload = tuple(range(5, 20)) + data_signal = (0,) * n_zeros + header + payload + # Trigger tag + trigger_tag = gr.tag_t() + trigger_tag.offset = n_zeros + trigger_tag.key = pmt.string_to_symbol('detect') + trigger_tag.value = pmt.PMT_T + # This is dropped: + testtag1 = gr.tag_t() + testtag1.offset = 0 + testtag1.key = pmt.string_to_symbol('tag1') + testtag1.value = pmt.from_long(0) + # This goes on output 0, item 0: + testtag2 = gr.tag_t() + testtag2.offset = n_zeros + testtag2.key = pmt.string_to_symbol('tag2') + testtag2.value = pmt.from_long(23) + # This goes on output 0, item 2: + testtag3 = gr.tag_t() + testtag3.offset = n_zeros + len(header) - 1 + testtag3.key = pmt.string_to_symbol('tag3') + testtag3.value = pmt.from_long(42) + # This goes on output 1, item 3: + testtag4 = gr.tag_t() + testtag4.offset = n_zeros + len(header) + 3 + testtag4.key = pmt.string_to_symbol('tag4') + testtag4.value = pmt.from_long(314) + data_src = blocks.vector_source_f( + data_signal, + False, + tags=(trigger_tag, testtag1, testtag2, testtag3, testtag4) + ) + hpd = digital.header_payload_demux( + len(header), 1, 0, "frame_len", "detect", False, gr.sizeof_float + ) + self.assertEqual(pmt.length(hpd.message_ports_in()), 2) #extra system port defined for you + header_sink = blocks.vector_sink_f() + payload_sink = blocks.vector_sink_f() + + self.tb.connect(data_src, (hpd, 0)) + self.tb.connect((hpd, 0), header_sink) + self.tb.connect((hpd, 1), payload_sink) + self.tb.start() + time.sleep(.2) # Need this, otherwise, the next message is ignored + hpd.to_basic_block()._post( + pmt.intern('header_data'), + pmt.from_long(len(payload)) + ) + while len(payload_sink.data()) < len(payload): + time.sleep(.2) + self.tb.stop() + self.tb.wait() + + self.assertEqual(header_sink.data(), header) + self.assertEqual(payload_sink.data(), payload) + ptags_header = [] + for tag in header_sink.tags(): + ptag = gr.tag_to_python(tag) + ptags_header.append({'key': ptag.key, 'offset': ptag.offset}) + expected_tags_header = [ + {'key': 'tag2', 'offset': 0}, + {'key': 'tag3', 'offset': 2}, + ] + self.assertEqual(expected_tags_header, ptags_header) + ptags_payload = [] + for tag in payload_sink.tags(): + ptag = gr.tag_to_python(tag) + ptags_payload.append({'key': ptag.key, 'offset': ptag.offset}) + expected_tags_payload = [ + {'key': 'frame_len', 'offset': 0}, + {'key': 'tag4', 'offset': 3}, + ] + self.assertEqual(expected_tags_payload, ptags_payload) + def test_002_symbols (self): """ Same as before, but operate on symbols diff --git a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py index c42fb2b907..1b3ffb7738 100755 --- a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py +++ b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py @@ -72,7 +72,7 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) tag_dict[ptag.key] = ptag.value expected_dict = { - 'foo': 42 + 'foo': 42 } self.assertEqual(tag_dict, expected_dict) diff --git a/gr-fec/lib/decoder_impl.cc b/gr-fec/lib/decoder_impl.cc index ba8a7d000e..62c301d501 100644 --- a/gr-fec/lib/decoder_impl.cc +++ b/gr-fec/lib/decoder_impl.cc @@ -95,8 +95,8 @@ namespace gr { noutput_items/(output_multiple() - d_decoder->get_history()) : innum; - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ - % outnum % ninput_items[0] % items); + //GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ + // % outnum % ninput_items[0] % items); for(int i = 0; i < items; ++i) { d_decoder->generic_work((void*)(in+(i*d_decoder->get_input_size()*d_input_item_size)), @@ -109,8 +109,8 @@ namespace gr { int consumed = static_cast<int>(items/relative_rate()*(output_multiple() - d_decoder->get_history()) + 0.5); int returned = items*(output_multiple() - d_decoder->get_history()); - GR_LOG_DEBUG(d_debug_logger, boost::format("consumed %1%") % consumed); - GR_LOG_DEBUG(d_debug_logger, boost::format("returned %1%") % returned); + //GR_LOG_DEBUG(d_debug_logger, boost::format("consumed %1%") % consumed); + //GR_LOG_DEBUG(d_debug_logger, boost::format("returned %1%") % returned); consume_each(consumed); return returned; diff --git a/gr-fec/lib/encoder_impl.cc b/gr-fec/lib/encoder_impl.cc index 399bcc41cf..af72f31133 100644 --- a/gr-fec/lib/encoder_impl.cc +++ b/gr-fec/lib/encoder_impl.cc @@ -91,8 +91,8 @@ namespace gr { char *inbuffer = (char*)input_items[0]; char *outbuffer = (char*)output_items[0]; - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ - % noutput_items % ninput_items[0] % (noutput_items/output_multiple())); + //GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ + // % noutput_items % ninput_items[0] % (noutput_items/output_multiple())); for(int i = 0; i < noutput_items/output_multiple(); i++) { @@ -100,10 +100,10 @@ namespace gr { (void*)(outbuffer+(i*d_output_size))); } - GR_LOG_DEBUG(d_debug_logger, boost::format("consuming: %1%") \ - % (fixed_rate_noutput_to_ninput(noutput_items))); - GR_LOG_DEBUG(d_debug_logger, boost::format("returning: %1%") \ - % (noutput_items)); + //GR_LOG_DEBUG(d_debug_logger, boost::format("consuming: %1%") \ + // % (fixed_rate_noutput_to_ninput(noutput_items))); + //GR_LOG_DEBUG(d_debug_logger, boost::format("returning: %1%") \ + // % (noutput_items)); consume_each(fixed_rate_noutput_to_ninput(noutput_items)); return noutput_items; diff --git a/gr-fft/include/gnuradio/fft/window.h b/gr-fft/include/gnuradio/fft/window.h index c1de1814c7..4b13ddd5c3 100644 --- a/gr-fft/include/gnuradio/fft/window.h +++ b/gr-fft/include/gnuradio/fft/window.h @@ -179,32 +179,47 @@ namespace gr { static std::vector<float> blackmanharris(int ntaps, int atten=92); /*! - * \brief Build a Nuttal (or Blackman-Nuttal) window. + * \brief Build a Nuttall (or Blackman-Nuttall) window. * * See: http://en.wikipedia.org/wiki/Window_function#Blackman.E2.80.93Nuttall_window * * \param ntaps Number of coefficients in the window. */ + static std::vector<float> nuttall(int ntaps); + + /*! + * Deprecated: use nuttall window instead. + */ static std::vector<float> nuttal(int ntaps); /*! - * \brief Alias to the Nuttal window. + * \brief Alias to the Nuttall window. * * \param ntaps Number of coefficients in the window. */ + static std::vector<float> blackman_nuttall(int ntaps); + + /*! + * Deprecated: use blackman_nuttall window instead. + */ static std::vector<float> blackman_nuttal(int ntaps); /*! - * \brief Build a Nuttal continuous first derivative window. + * \brief Build a Nuttall continuous first derivative window. * * See: http://en.wikipedia.org/wiki/Window_function#Nuttall_window.2C_continuous_first_derivative * * \param ntaps Number of coefficients in the window. */ + static std::vector<float> nuttall_cfd(int ntaps); + + /*! + * Deprecated: use nuttall_cfd window instead. + */ static std::vector<float> nuttal_cfd(int ntaps); /*! - * \brief Build a Nuttal continuous first derivative window. + * \brief Build a flat top window. * * See: http://en.wikipedia.org/wiki/Window_function#Flat_top_window * diff --git a/gr-fft/lib/window.cc b/gr-fft/lib/window.cc index 965b11bf46..126b28978d 100644 --- a/gr-fft/lib/window.cc +++ b/gr-fft/lib/window.cc @@ -209,18 +209,36 @@ namespace gr { std::vector<float> window::nuttal(int ntaps) { + return nuttall(ntaps); + } + + std::vector<float> + window::nuttall(int ntaps) + { return coswindow(ntaps, 0.3635819, 0.4891775, 0.1365995, 0.0106411); } std::vector<float> window::blackman_nuttal(int ntaps) { - return nuttal(ntaps); + return nuttall(ntaps); + } + + std::vector<float> + window::blackman_nuttall(int ntaps) + { + return nuttall(ntaps); } std::vector<float> window::nuttal_cfd(int ntaps) { + return nuttall_cfd(ntaps); + } + + std::vector<float> + window::nuttall_cfd(int ntaps) + { return coswindow(ntaps, 0.355768, 0.487396, 0.144232, 0.012604); } diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml index 94989f5c68..aea46ab4e3 100644 --- a/gr-qtgui/grc/qtgui_freq_sink_x.xml +++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml @@ -22,10 +22,14 @@ qtgui.$(type.fcn)( ) self.$(id).set_update_time($update_time) self.$(id).set_y_axis($ymin, $ymax) +self.$(id).set_trigger_mode($tr_mode, $tr_level, $tr_chan, $tr_tag) self.$(id).enable_autoscale($autoscale) self.$(id).enable_grid($grid) self.$(id).set_fft_average($average) +if $type == type(float()): + self.$(id).set_plot_pos_half(not $freqhalf) + labels = [$label1, $label2, $label3, $label4, $label5, $label6, $label7, $label8, $label9, $label10] widths = [$width1, $width2, $width3, $width4, $width5, @@ -53,6 +57,7 @@ $(gui_hint()($win))</make> <param_tab_order> <tab>General</tab> + <tab>Trigger</tab> <tab>Config</tab> </param_tab_order> @@ -80,6 +85,25 @@ $(gui_hint()($win))</make> <type>int</type> </param> + + <param> + <name>Spectrum Width</name> + <key>freqhalf</key> + <value>True</value> + <type>enum</type> + <hide>#if $type() == "float" then 'part' else 'all'#</hide> + <option> + <name>Full</name> + <key>True</key> + </option> + <option> + <name>Half</name> + <key>False</key> + </option> + </param> + + + <param> <name>Window Type</name> <key>wintype</key> @@ -237,6 +261,63 @@ $(gui_hint()($win))</make> </option> </param> + + <!-- Begin Trigger Tab items --> + <param> + <name>Trigger Mode</name> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_FREE</value> + <type>enum</type> + <hide>part</hide> + <option> + <name>Free</name> + <key>qtgui.TRIG_MODE_FREE</key> + </option> + <option> + <name>Auto</name> + <key>qtgui.TRIG_MODE_AUTO</key> + </option> + <option> + <name>Normal</name> + <key>qtgui.TRIG_MODE_NORM</key> + </option> + <option> + <name>Tag</name> + <key>qtgui.TRIG_MODE_TAG</key> + </option> + <tab>Trigger</tab> + </param> + + <param> + <name>Trigger Level</name> + <key>tr_level</key> + <value>0.0</value> + <type>float</type> + <hide>part</hide> + <tab>Trigger</tab> + </param> + + <param> + <name>Trigger Channel</name> + <key>tr_chan</key> + <value>0</value> + <type>int</type> + <hide>part</hide> + <tab>Trigger</tab> + </param> + + <param> + <name>Trigger Tag Key</name> + <key>tr_tag</key> + <value>""</value> + <type>string</type> + <hide>part</hide> + <tab>Trigger</tab> + </param> + + + + <!-- Begin Config Tab items --> <param> <name>Line 1 Label</name> <key>label1</key> diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml index d6e0f5911b..3b6e37e16b 100644 --- a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml +++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml @@ -23,6 +23,9 @@ qtgui.$(type.fcn)( self.$(id).set_update_time($update_time) self.$(id).enable_grid($grid) +if $type == type(float()): + self.$(id).set_plot_pos_half(not $freqhalf) + labels = [$label1, $label2, $label3, $label4, $label5, $label6, $label7, $label8, $label9, $label10] colors = [$color1, $color2, $color3, $color4, $color5, @@ -77,6 +80,22 @@ $(gui_hint()($win))</make> </param> <param> + <name>Spectrum Width</name> + <key>freqhalf</key> + <value>True</value> + <type>enum</type> + <hide>#if $type() == "float" then 'part' else 'all'#</hide> + <option> + <name>Full</name> + <key>True</key> + </option> + <option> + <name>Half</name> + <key>False</key> + </option> + </param> + + <param> <name>Window Type</name> <key>wintype</key> <value>firdes.WIN_BLACKMAN_hARRIS</value> diff --git a/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h b/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h index ac7dfe8b6d..cb44fbe510 100644 --- a/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h +++ b/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h @@ -118,6 +118,8 @@ public slots: void setAutoScale(bool state); + void setPlotPosHalf(bool half); + private: void _resetXAxisPoints(); void _autoScale(double bottom, double top); @@ -143,6 +145,7 @@ private: double d_stop_frequency; double d_ymax; double d_ymin; + bool d_half_freq; QwtPlotMarker* d_lower_intensity_marker; QwtPlotMarker* d_upper_intensity_marker; diff --git a/gr-qtgui/include/gnuradio/qtgui/WaterfallDisplayPlot.h b/gr-qtgui/include/gnuradio/qtgui/WaterfallDisplayPlot.h index 4fdd065093..37c6183608 100644 --- a/gr-qtgui/include/gnuradio/qtgui/WaterfallDisplayPlot.h +++ b/gr-qtgui/include/gnuradio/qtgui/WaterfallDisplayPlot.h @@ -95,6 +95,7 @@ public slots: void setIntensityColorMapType1(int); void setUserDefinedLowIntensityColor(QColor); void setUserDefinedHighIntensityColor(QColor); + void setPlotPosHalf(bool half); signals: void updatedLowerIntensityLevel(const double); @@ -106,6 +107,7 @@ private: double d_start_frequency; double d_stop_frequency; int d_xaxis_multiplier; + bool d_half_freq; std::vector<WaterfallData*> d_data; diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h index d02505c6f6..f49e7b062f 100644 --- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h +++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h @@ -28,6 +28,7 @@ #endif #include <gnuradio/qtgui/api.h> +#include <gnuradio/qtgui/trigger_mode.h> #include <gnuradio/sync_block.h> #include <qapplication.h> #include <gnuradio/filter/firdes.h> @@ -118,6 +119,33 @@ namespace gr { virtual void set_line_marker(int which, int marker) = 0; virtual void set_line_alpha(int which, double alpha) = 0; + /*! + * Set up a trigger for the sink to know when to start + * plotting. Useful to isolate events and avoid noise. + * + * The trigger modes are Free, Auto, Normal, and Tag (see + * gr::qtgui::trigger_mode). The first three are like a normal + * trigger function. Free means free running with no trigger, + * auto will trigger if the trigger event is seen, but will + * still plot otherwise, and normal will hold until the trigger + * event is observed. The Tag trigger mode allows us to trigger + * off a specific stream tag. The tag trigger is based only on + * the name of the tag, so when a tag of the given name is seen, + * the trigger is activated. + * + * In auto and normal mode, we look to see if the magnitude of + * the any FFT point is over the set level. + * + * \param mode The trigger_mode: free, auto, normal, or tag. + * \param level The magnitude of the trigger even for auto or normal modes. + * \param channel Which input channel to use for the trigger events. + * \param tag_key The name (as a string) of the tag to trigger off + * of if using the tag mode. + */ + virtual void set_trigger_mode(trigger_mode mode, + float level, int channel, + const std::string &tag_key="") = 0; + virtual std::string title() = 0; virtual std::string line_label(int which) = 0; virtual std::string line_color(int which) = 0; diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h index 81f9c0c8c5..ed65d3136c 100644 --- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h +++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h @@ -28,6 +28,7 @@ #endif #include <gnuradio/qtgui/api.h> +#include <gnuradio/qtgui/trigger_mode.h> #include <gnuradio/sync_block.h> #include <qapplication.h> #include <gnuradio/filter/firdes.h> @@ -117,6 +118,40 @@ namespace gr { virtual void set_line_marker(int which, int marker) = 0; virtual void set_line_alpha(int which, double alpha) = 0; + /*! + * Pass "true" to this function to only show the positive half + * of the spectrum. By default, this plotter shows the full + * spectrum (positive and negative halves). + */ + virtual void set_plot_pos_half(bool half) = 0; + + /*! + * Set up a trigger for the sink to know when to start + * plotting. Useful to isolate events and avoid noise. + * + * The trigger modes are Free, Auto, Normal, and Tag (see + * gr::qtgui::trigger_mode). The first three are like a normal + * trigger function. Free means free running with no trigger, + * auto will trigger if the trigger event is seen, but will + * still plot otherwise, and normal will hold until the trigger + * event is observed. The Tag trigger mode allows us to trigger + * off a specific stream tag. The tag trigger is based only on + * the name of the tag, so when a tag of the given name is seen, + * the trigger is activated. + * + * In auto and normal mode, we look to see if the magnitude of + * the any FFT point is over the set level. + * + * \param mode The trigger_mode: free, auto, normal, or tag. + * \param level The magnitude of the trigger even for auto or normal modes. + * \param channel Which input channel to use for the trigger events. + * \param tag_key The name (as a string) of the tag to trigger off + * of if using the tag mode. + */ + virtual void set_trigger_mode(trigger_mode mode, + float level, int channel, + const std::string &tag_key="") = 0; + virtual std::string title() = 0; virtual std::string line_label(int which) = 0; virtual std::string line_color(int which) = 0; diff --git a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h index 7cd077e6f8..744ac3ee90 100644 --- a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h +++ b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h @@ -49,6 +49,13 @@ class FreqDisplayForm : public DisplayForm float getFFTAverage() const; gr::filter::firdes::win_type getFFTWindowType() const; + // Trigger methods + gr::qtgui::trigger_mode getTriggerMode() const; + float getTriggerLevel() const; + int getTriggerChannel() const; + std::string getTriggerTagKey() const; + + // returns the frequency that was last double-clicked on by the user float getClickedFreq() const; @@ -69,9 +76,19 @@ public slots: void setYMax(const QString &m); void setYMin(const QString &m); void autoScale(bool en); + void setPlotPosHalf(bool half); void clearMaxHold(); void clearMinHold(); + // Trigger slots + void updateTrigger(gr::qtgui::trigger_mode mode); + void setTriggerMode(gr::qtgui::trigger_mode mode); + void setTriggerLevel(QString s); + void setTriggerLevel(float level); + void setTriggerChannel(int chan); + void setTriggerTagKey(QString s); + void setTriggerTagKey(const std::string &s); + private slots: void newData(const QEvent *updateEvent); void onPlotPointSelected(const QPointF p); @@ -93,6 +110,17 @@ private: FFTAverageMenu *d_avgmenu; FFTWindowMenu *d_winmenu; QAction *d_clearmin_act, *d_clearmax_act; + + QMenu *d_triggermenu; + TriggerModeMenu *d_tr_mode_menu; + PopupMenu *d_tr_level_act; + TriggerChannelMenu *d_tr_channel_menu; + PopupMenu *d_tr_tag_key_act; + + gr::qtgui::trigger_mode d_trig_mode; + float d_trig_level; + int d_trig_channel; + std::string d_trig_tag_key; }; #endif /* FREQ_DISPLAY_FORM_H */ diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h index bbfcc33164..4570ef9d54 100644 --- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h +++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h @@ -124,6 +124,13 @@ namespace gr { virtual void set_line_alpha(int which, double alpha) = 0; virtual void set_color_map(int which, const int color) = 0; + /*! + * Pass "true" to this function to only show the positive half + * of the spectrum. By default, this plotter shows the full + * spectrum (positive and negative halves). + */ + virtual void set_plot_pos_half(bool half) = 0; + virtual std::string title() = 0; virtual std::string line_label(int which) = 0; virtual double line_alpha(int which) = 0; diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h index 8017d5ce8f..e885a525b0 100644 --- a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h +++ b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h @@ -86,6 +86,7 @@ public slots: const QColor highColor=QColor("white")); void autoScale(bool en=false); + void setPlotPosHalf(bool half); private slots: void newData(const QEvent *updateEvent); diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index 12835bcd27..41050edfc2 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008-2011 Free Software Foundation, Inc. + * Copyright 2008-2011,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -94,6 +94,7 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent) d_min_fft_data = new double[d_numPoints]; d_max_fft_data = new double[d_numPoints]; d_xdata = new double[d_numPoints]; + d_half_freq = false; setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0)); @@ -279,8 +280,13 @@ FrequencyDisplayPlot::setFrequencyRange(const double centerfreq, const double bandwidth, const double units, const std::string &strunits) { - double startFreq = (centerfreq - bandwidth/2.0f) / units; - double stopFreq = (centerfreq + bandwidth/2.0f) / units; + double startFreq; + double stopFreq = (centerfreq + bandwidth/2.0f) / units; + if(d_half_freq) + startFreq = 0; + else + startFreq = (centerfreq - bandwidth/2.0f) / units; + d_xdata_multiplier = units; @@ -346,10 +352,13 @@ FrequencyDisplayPlot::plotNewData(const std::vector<double*> dataPoints, const double noiseFloorAmplitude, const double peakFrequency, const double peakAmplitude, const double timeInterval) { + int64_t _npoints_in = d_half_freq ? numDataPoints/2 : numDataPoints; + int64_t _in_index = d_half_freq ? _npoints_in : 0; + if(!d_stop) { if(numDataPoints > 0) { - if(numDataPoints != d_numPoints) { - d_numPoints = numDataPoints; + if(_npoints_in != d_numPoints) { + d_numPoints = _npoints_in; delete[] d_min_fft_data; delete[] d_max_fft_data; @@ -383,9 +392,9 @@ FrequencyDisplayPlot::plotNewData(const std::vector<double*> dataPoints, double bottom=1e20, top=-1e20; for(int n = 0; n < d_nplots; n++) { - memcpy(d_ydata[n], dataPoints[n], numDataPoints*sizeof(double)); + memcpy(d_ydata[n], &(dataPoints[n][_in_index]), _npoints_in*sizeof(double)); - for(int64_t point = 0; point < numDataPoints; point++) { + for(int64_t point = 0; point < _npoints_in; point++) { if(dataPoints[n][point] < d_min_fft_data[point]) { d_min_fft_data[point] = dataPoints[n][point]; } @@ -462,6 +471,15 @@ FrequencyDisplayPlot::setAutoScale(bool state) } void +FrequencyDisplayPlot::setPlotPosHalf(bool half) +{ + d_half_freq = half; + if(half) + d_start_frequency = 0; +} + + +void FrequencyDisplayPlot::setMaxFFTVisible(const bool visibleFlag) { d_max_fft_visible = visibleFlag; @@ -491,7 +509,7 @@ void FrequencyDisplayPlot::_resetXAxisPoints() { double fft_bin_size = (d_stop_frequency - d_start_frequency) - / static_cast<double>(d_numPoints-1); + / static_cast<double>(d_numPoints); double freqValue = d_start_frequency; for(int64_t loc = 0; loc < d_numPoints; loc++) { d_xdata[loc] = freqValue; diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index eb33cba921..86724fe04d 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008-2012 Free Software Foundation, Inc. + * Copyright 2008-2012,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -139,6 +139,7 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(int nplots, QWidget* parent) resize(parent->width(), parent->height()); d_numPoints = 1024; + d_half_freq = false; setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0)); @@ -225,8 +226,13 @@ WaterfallDisplayPlot::setFrequencyRange(const double centerfreq, const double bandwidth, const double units, const std::string &strunits) { - double startFreq = (centerfreq - bandwidth/2.0f) / units; - double stopFreq = (centerfreq + bandwidth/2.0f) / units; + double startFreq; + double stopFreq = (centerfreq + bandwidth/2.0f) / units; + if(d_half_freq) + startFreq = 0; + else + startFreq = (centerfreq - bandwidth/2.0f) / units; + d_xaxis_multiplier = units; @@ -273,10 +279,13 @@ WaterfallDisplayPlot::plotNewData(const std::vector<double*> dataPoints, const gr::high_res_timer_type timestamp, const int droppedFrames) { + int64_t _npoints_in = d_half_freq ? numDataPoints/2 : numDataPoints; + int64_t _in_index = d_half_freq ? _npoints_in : 0; + if(!d_stop) { if(numDataPoints > 0){ - if(numDataPoints != d_numPoints){ - d_numPoints = numDataPoints; + if(_npoints_in != d_numPoints) { + d_numPoints = _npoints_in; resetAxis(); @@ -298,7 +307,8 @@ WaterfallDisplayPlot::plotNewData(const std::vector<double*> dataPoints, ((WaterfallZoomer*)d_zoomer)->setZeroTime(timestamp); for(int i = 0; i < d_nplots; i++) { - d_data[i]->addFFTData(dataPoints[i], numDataPoints, droppedFrames); + d_data[i]->addFFTData(&(dataPoints[i][_in_index]), + _npoints_in, droppedFrames); d_data[i]->incrementNumLinesToUpdate(); d_spectrogram[i]->invalidateCache(); d_spectrogram[i]->itemChanged(); @@ -596,4 +606,13 @@ WaterfallDisplayPlot::_updateIntensityRangeDisplay() replot(); } +void +WaterfallDisplayPlot::setPlotPosHalf(bool half) +{ + d_half_freq = half; + if(half) + d_start_frequency = 0; +} + + #endif /* WATERFALL_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/const_sink_c_impl.cc b/gr-qtgui/lib/const_sink_c_impl.cc index f7bdc01489..10b342dbf5 100644 --- a/gr-qtgui/lib/const_sink_c_impl.cc +++ b/gr-qtgui/lib/const_sink_c_impl.cc @@ -498,7 +498,7 @@ namespace gr { d_index += nitems; - // If we've have a trigger and a full d_size of items in the buffers, plot. + // If we have a trigger and a full d_size of items in the buffers, plot. if((d_triggered) && (d_index == d_end)) { // Copy data to be plotted to start of buffers. for(n = 0; n < d_nconnections; n++) { diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc index 11e8fc378f..e46b9db865 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.cc +++ b/gr-qtgui/lib/freq_sink_c_impl.cc @@ -54,8 +54,8 @@ namespace gr { int nconnections, QWidget *parent) : sync_block("freq_sink_c", - io_signature::make(1, -1, sizeof(gr_complex)), - io_signature::make(0, 0, 0)), + io_signature::make(nconnections, nconnections, sizeof(gr_complex)), + io_signature::make(0, 0, 0)), d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), @@ -87,6 +87,11 @@ namespace gr { volk_get_alignment()); memset(d_fbuf, 0, d_fftsize*sizeof(float)); + d_tmpbuflen = (unsigned int)(floor(d_fftsize/2.0)); + d_tmpbuf = (float*)volk_malloc(sizeof(float)*(d_tmpbuflen + 1), + volk_get_alignment()); + + d_index = 0; for(int i = 0; i < d_nconnections; i++) { d_residbufs.push_back((gr_complex*)volk_malloc(d_fftsize*sizeof(gr_complex), @@ -101,6 +106,8 @@ namespace gr { buildwindow(); initialize(); + + set_trigger_mode(TRIG_MODE_FREE, 0, 0); } freq_sink_c_impl::~freq_sink_c_impl() @@ -114,6 +121,7 @@ namespace gr { } delete d_fft; volk_free(d_fbuf); + volk_free(d_tmpbuf); delete d_argv; } @@ -125,15 +133,6 @@ namespace gr { } void - freq_sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - unsigned int ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = std::min(d_fftsize, 8191); - } - } - - void freq_sink_c_impl::initialize() { if(qApp != NULL) { @@ -162,6 +161,8 @@ namespace gr { if(d_name.size() > 0) set_title(d_name); + set_output_multiple(d_fftsize); + // initialize update time to 10 times a second set_update_time(0.1); } @@ -303,6 +304,29 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + void + freq_sink_c_impl::set_trigger_mode(trigger_mode mode, + float level, + int channel, + const std::string &tag_key) + { + gr::thread::scoped_lock lock(d_setlock); + + d_trigger_mode = mode; + d_trigger_level = level; + d_trigger_channel = channel; + d_trigger_tag_key = pmt::intern(tag_key); + d_triggered = false; + d_trigger_count = 0; + + d_main_gui->setTriggerMode(d_trigger_mode); + d_main_gui->setTriggerLevel(d_trigger_level); + d_main_gui->setTriggerChannel(d_trigger_channel); + d_main_gui->setTriggerTagKey(tag_key); + + _reset(); + } + std::string freq_sink_c_impl::title() { @@ -378,10 +402,26 @@ namespace gr { void freq_sink_c_impl::reset() { - d_index = 0; + gr::thread::scoped_lock lock(d_setlock); + _reset(); } void + freq_sink_c_impl::_reset() + { + d_trigger_count = 0; + + // Reset the trigger. + if(d_trigger_mode == TRIG_MODE_FREE) { + d_triggered = true; + } + else { + d_triggered = false; + } + } + + + void freq_sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size) { if(d_window.size()) { @@ -398,15 +438,12 @@ namespace gr { size, 1.0, size); // Perform shift operation - unsigned int len = (unsigned int)(floor(size/2.0)); - float *tmp = (float*)malloc(sizeof(float)*len); - memcpy(tmp, &data_out[0], sizeof(float)*len); - memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); - memcpy(&data_out[size - len], tmp, sizeof(float)*len); - free(tmp); + memcpy(d_tmpbuf, &data_out[0], sizeof(float)*(d_tmpbuflen + 1)); + memcpy(&data_out[0], &data_out[size - d_tmpbuflen], sizeof(float)*(d_tmpbuflen)); + memcpy(&data_out[d_tmpbuflen], d_tmpbuf, sizeof(float)*(d_tmpbuflen + 1)); } - void + bool freq_sink_c_impl::windowreset() { gr::thread::scoped_lock lock(d_setlock); @@ -416,7 +453,9 @@ namespace gr { if(d_wintype != newwintype) { d_wintype = newwintype; buildwindow(); + return true; } + return false; } void @@ -428,7 +467,7 @@ namespace gr { } } - void + bool freq_sink_c_impl::fftresize() { gr::thread::scoped_lock lock(d_setlock); @@ -467,7 +506,19 @@ namespace gr { d_fbuf = (float*)volk_malloc(d_fftsize*sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + volk_free(d_tmpbuf); + d_tmpbuflen = (unsigned int)(floor(d_fftsize/2.0)); + d_tmpbuf = (float*)volk_malloc(sizeof(float)*(d_tmpbuflen + 1), + volk_get_alignment()); + + d_last_time = 0; + + set_output_multiple(d_fftsize); + + return true; } + return false; } void @@ -494,59 +545,121 @@ namespace gr { } } + void + freq_sink_c_impl::_gui_update_trigger() + { + trigger_mode new_trigger_mode = d_main_gui->getTriggerMode(); + d_trigger_level = d_main_gui->getTriggerLevel(); + d_trigger_channel = d_main_gui->getTriggerChannel(); + + std::string tagkey = d_main_gui->getTriggerTagKey(); + d_trigger_tag_key = pmt::intern(tagkey); + + if(new_trigger_mode != d_trigger_mode) { + d_trigger_mode = new_trigger_mode; + _reset(); + } + } + + void + freq_sink_c_impl::_test_trigger_tags(int start, int nitems) + { + uint64_t nr = nitems_read(d_trigger_channel); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, d_trigger_channel, + nr+start, nr+start+nitems, + d_trigger_tag_key); + if(tags.size() > 0) { + d_triggered = true; + d_index = tags[0].offset - nr; + d_trigger_count = 0; + } + } + + void + freq_sink_c_impl::_test_trigger_norm(int nitems, std::vector<double*> inputs) + { + const double *in = (const double*)inputs[d_trigger_channel]; + for(int i = 0; i < nitems; i++) { + d_trigger_count++; + + // Test if trigger has occurred based on the FFT magnitude and + // channel number. Test if any value is > the level (in dBx). + if(in[i] > d_trigger_level) { + d_triggered = true; + d_trigger_count = 0; + break; + } + } + + // If using auto trigger mode, trigger periodically even + // without a trigger event. + if((d_trigger_mode == TRIG_MODE_AUTO) && (d_trigger_count > d_fftsize)) { + d_triggered = true; + d_trigger_count = 0; + } + } + int freq_sink_c_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - int j=0; const gr_complex *in = (const gr_complex*)input_items[0]; // Update the FFT size from the application - fftresize(); - windowreset(); - check_clicked(); + bool updated = false; + updated |= fftresize(); + updated |= windowreset(); + if(updated) + return 0; - for(int i=0; i < noutput_items; i+=d_fftsize) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_fftsize-d_index; + check_clicked(); + _gui_update_trigger(); - // If we have enough input for one full FFT, do it - if(datasize >= resid) { + gr::thread::scoped_lock lock(d_setlock); + for(d_index = 0; d_index < noutput_items; d_index+=d_fftsize) { - if(gr::high_res_timer_now() - d_last_time > d_update_time) { - for(int n = 0; n < d_nconnections; n++) { - // Fill up residbuf with d_fftsize number of items - in = (const gr_complex*)input_items[n]; - memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid); + if((gr::high_res_timer_now() - d_last_time) > d_update_time) { - fft(d_fbuf, d_residbufs[n], d_fftsize); - for(int x = 0; x < d_fftsize; x++) { - d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); - } - //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + // Trigger off tag, if active + if((d_trigger_mode == TRIG_MODE_TAG) && !d_triggered) { + _test_trigger_tags(d_index, d_fftsize); + if(d_triggered) { + // If not enough from tag position, early exit + if((d_index + d_fftsize) >= noutput_items) + return d_index; } + } - d_last_time = gr::high_res_timer_now(); - d_qApplication->postEvent(d_main_gui, - new FreqUpdateEvent(d_magbufs, d_fftsize)); - } + // Perform FFT and shift operations into d_magbufs + for(int n = 0; n < d_nconnections; n++) { + in = (const gr_complex*)input_items[n]; + memcpy(d_residbufs[n], &in[d_index], sizeof(gr_complex)*d_fftsize); - d_index = 0; - j += resid; - } - // Otherwise, copy what we received into the residbuf for next time - else { - for(int n = 0; n < d_nconnections; n++) { - in = (const gr_complex*)input_items[n]; - memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*datasize); - } - d_index += datasize; - j += datasize; - } + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); + } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + + // Test trigger off signal power in d_magbufs + if((d_trigger_mode == TRIG_MODE_NORM) || (d_trigger_mode == TRIG_MODE_AUTO)) { + _test_trigger_norm(d_fftsize, d_magbufs); + } + + // If a trigger (FREE always triggers), plot and reset state + if(d_triggered) { + d_last_time = gr::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new FreqUpdateEvent(d_magbufs, d_fftsize)); + _reset(); + } + } } - return j; + return noutput_items; } } /* namespace qtgui */ diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h index dc985c1a99..b5f9cd3d4d 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.h +++ b/gr-qtgui/lib/freq_sink_c_impl.h @@ -35,11 +35,10 @@ namespace gr { class QTGUI_API freq_sink_c_impl : public freq_sink_c { private: - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - void initialize(); int d_fftsize; + int d_tmpbuflen; float d_fftavg; filter::firdes::win_type d_wintype; std::vector<float> d_window; @@ -55,6 +54,7 @@ namespace gr { std::vector<gr_complex*> d_residbufs; std::vector<double*> d_magbufs; float *d_fbuf; + float *d_tmpbuf; int d_argc; char *d_argv; @@ -64,9 +64,9 @@ namespace gr { gr::high_res_timer_type d_update_time; gr::high_res_timer_type d_last_time; - void windowreset(); + bool windowreset(); void buildwindow(); - void fftresize(); + bool fftresize(); void check_clicked(); void fft(float *data_out, const gr_complex *data_in, int size); @@ -74,6 +74,19 @@ namespace gr { // The message is a PMT pair (intern('freq'), double(frequency)). void handle_set_freq(pmt::pmt_t msg); + // Members used for triggering scope + trigger_mode d_trigger_mode; + float d_trigger_level; + int d_trigger_channel; + pmt::pmt_t d_trigger_tag_key; + bool d_triggered; + int d_trigger_count; + + void _reset(); + void _gui_update_trigger(); + void _test_trigger_tags(int start, int nitems); + void _test_trigger_norm(int nitems, std::vector<double*> inputs); + public: freq_sink_c_impl(int size, int wintype, double fc, double bw, @@ -112,6 +125,9 @@ namespace gr { void set_line_style(int which, int style); void set_line_marker(int which, int marker); void set_line_alpha(int which, double alpha); + void set_trigger_mode(trigger_mode mode, + float level, int channel, + const std::string &tag_key=""); std::string title(); std::string line_label(int which); diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc index c0a29becd8..200b009d79 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.cc +++ b/gr-qtgui/lib/freq_sink_f_impl.cc @@ -54,8 +54,8 @@ namespace gr { int nconnections, QWidget *parent) : sync_block("freq_sink_f", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(0, 0, 0)), + io_signature::make(nconnections, nconnections, sizeof(float)), + io_signature::make(0, 0, 0)), d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), @@ -87,6 +87,10 @@ namespace gr { volk_get_alignment()); memset(d_fbuf, 0, d_fftsize*sizeof(float)); + d_tmpbuflen = (unsigned int)(floor(d_fftsize/2.0)); + d_tmpbuf = (float*)volk_malloc(sizeof(float)*(d_tmpbuflen + 1), + volk_get_alignment()); + d_index = 0; for(int i = 0; i < d_nconnections; i++) { d_residbufs.push_back((float*)volk_malloc(d_fftsize*sizeof(float), @@ -101,6 +105,8 @@ namespace gr { buildwindow(); initialize(); + + set_trigger_mode(TRIG_MODE_FREE, 0, 0); } freq_sink_f_impl::~freq_sink_f_impl() @@ -114,6 +120,7 @@ namespace gr { } delete d_fft; volk_free(d_fbuf); + volk_free(d_tmpbuf); delete d_argv; } @@ -125,15 +132,6 @@ namespace gr { } void - freq_sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - unsigned int ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = std::min(d_fftsize, 8191); - } - } - - void freq_sink_f_impl::initialize() { if(qApp != NULL) { @@ -162,6 +160,8 @@ namespace gr { if(d_name.size() > 0) set_title(d_name); + set_output_multiple(d_fftsize); + // initialize update time to 10 times a second set_update_time(0.1); } @@ -303,6 +303,35 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + void + freq_sink_f_impl::set_plot_pos_half(bool half) + { + d_main_gui->setPlotPosHalf(half); + } + + void + freq_sink_f_impl::set_trigger_mode(trigger_mode mode, + float level, + int channel, + const std::string &tag_key) + { + gr::thread::scoped_lock lock(d_setlock); + + d_trigger_mode = mode; + d_trigger_level = level; + d_trigger_channel = channel; + d_trigger_tag_key = pmt::intern(tag_key); + d_triggered = false; + d_trigger_count = 0; + + d_main_gui->setTriggerMode(d_trigger_mode); + d_main_gui->setTriggerLevel(d_trigger_level); + d_main_gui->setTriggerChannel(d_trigger_channel); + d_main_gui->setTriggerTagKey(tag_key); + + _reset(); + } + std::string freq_sink_f_impl::title() { @@ -378,10 +407,25 @@ namespace gr { void freq_sink_f_impl::reset() { - d_index = 0; + gr::thread::scoped_lock lock(d_setlock); + _reset(); } void + freq_sink_f_impl::_reset() + { + d_trigger_count = 0; + + // Reset the trigger. + if(d_trigger_mode == TRIG_MODE_FREE) { + d_triggered = true; + } + else { + d_triggered = false; + } + } + + void freq_sink_f_impl::fft(float *data_out, const float *data_in, int size) { // float to complex conversion @@ -399,15 +443,12 @@ namespace gr { size, 1.0, size); // Perform shift operation - unsigned int len = (unsigned int)(floor(size/2.0)); - float *tmp = (float*)malloc(sizeof(float)*len); - memcpy(tmp, &data_out[0], sizeof(float)*len); - memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); - memcpy(&data_out[size - len], tmp, sizeof(float)*len); - free(tmp); + memcpy(d_tmpbuf, &data_out[0], sizeof(float)*(d_tmpbuflen + 1)); + memcpy(&data_out[0], &data_out[size - d_tmpbuflen], sizeof(float)*d_tmpbuflen); + memcpy(&data_out[d_tmpbuflen], d_tmpbuf, sizeof(float)*(d_tmpbuflen + 1)); } - void + bool freq_sink_f_impl::windowreset() { gr::thread::scoped_lock lock(d_setlock); @@ -417,7 +458,9 @@ namespace gr { if(d_wintype != newwintype) { d_wintype = newwintype; buildwindow(); + return true; } + return false; } void @@ -429,7 +472,7 @@ namespace gr { } } - void + bool freq_sink_f_impl::fftresize() { gr::thread::scoped_lock lock(d_setlock); @@ -468,7 +511,19 @@ namespace gr { d_fbuf = (float*)volk_malloc(d_fftsize*sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + volk_free(d_tmpbuf); + d_tmpbuflen = (unsigned int)(floor(d_fftsize/2.0)); + d_tmpbuf = (float*)volk_malloc(sizeof(float)*(d_tmpbuflen + 1), + volk_get_alignment()); + + d_last_time = 0; + + set_output_multiple(d_fftsize); + + return true; } + return false; } void @@ -495,59 +550,121 @@ namespace gr { } } + void + freq_sink_f_impl::_gui_update_trigger() + { + trigger_mode new_trigger_mode = d_main_gui->getTriggerMode(); + d_trigger_level = d_main_gui->getTriggerLevel(); + d_trigger_channel = d_main_gui->getTriggerChannel(); + + std::string tagkey = d_main_gui->getTriggerTagKey(); + d_trigger_tag_key = pmt::intern(tagkey); + + if(new_trigger_mode != d_trigger_mode) { + d_trigger_mode = new_trigger_mode; + _reset(); + } + } + + void + freq_sink_f_impl::_test_trigger_tags(int start, int nitems) + { + uint64_t nr = nitems_read(d_trigger_channel); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, d_trigger_channel, + nr+start, nr+start+nitems, + d_trigger_tag_key); + if(tags.size() > 0) { + d_triggered = true; + d_index = tags[0].offset - nr; + d_trigger_count = 0; + } + } + + void + freq_sink_f_impl::_test_trigger_norm(int nitems, std::vector<double*> inputs) + { + const double *in = (const double*)inputs[d_trigger_channel]; + for(int i = 0; i < nitems; i++) { + d_trigger_count++; + + // Test if trigger has occurred based on the FFT magnitude and + // channel number. Test if any value is > the level (in dBx). + if(in[i] > d_trigger_level) { + d_triggered = true; + d_trigger_count = 0; + break; + } + } + + // If using auto trigger mode, trigger periodically even + // without a trigger event. + if((d_trigger_mode == TRIG_MODE_AUTO) && (d_trigger_count > d_fftsize)) { + d_triggered = true; + d_trigger_count = 0; + } + } + int freq_sink_f_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - int j=0; const float *in = (const float*)input_items[0]; // Update the FFT size from the application - fftresize(); - windowreset(); + bool updated = false; + updated |= fftresize(); + updated |= windowreset(); + if(updated) + return 0; + check_clicked(); + _gui_update_trigger(); + + gr::thread::scoped_lock lock(d_setlock); + for(d_index = 0; d_index < noutput_items; d_index+=d_fftsize) { - for(int i=0; i < noutput_items; i+=d_fftsize) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_fftsize-d_index; + if((gr::high_res_timer_now() - d_last_time) > d_update_time) { - // If we have enough input for one full FFT, do it - if(datasize >= resid) { + // Trigger off tag, if active + if((d_trigger_mode == TRIG_MODE_TAG) && !d_triggered) { + _test_trigger_tags(d_index, d_fftsize); + if(d_triggered) { + // If not enough from tag position, early exit + if((d_index + d_fftsize) >= noutput_items) + return d_index; + } + } - if(gr::high_res_timer_now() - d_last_time > d_update_time) { - for(int n = 0; n < d_nconnections; n++) { - // Fill up residbuf with d_fftsize number of items - in = (const float*)input_items[n]; - memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*resid); + for(int n = 0; n < d_nconnections; n++) { + // Fill up residbuf with d_fftsize number of items + in = (const float*)input_items[n]; + memcpy(d_residbufs[n], &in[d_index], sizeof(float)*d_fftsize); - fft(d_fbuf, d_residbufs[n], d_fftsize); - for(int x = 0; x < d_fftsize; x++) { - d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); - } - //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + // Test trigger off signal power in d_magbufs + if((d_trigger_mode == TRIG_MODE_NORM) || (d_trigger_mode == TRIG_MODE_AUTO)) { + _test_trigger_norm(d_fftsize, d_magbufs); + } + + // If a trigger (FREE always triggers), plot and reset state + if(d_triggered) { d_last_time = gr::high_res_timer_now(); d_qApplication->postEvent(d_main_gui, new FreqUpdateEvent(d_magbufs, d_fftsize)); + _reset(); } - - d_index = 0; - j += resid; - } - // Otherwise, copy what we received into the residbuf for next time - else { - for(int n = 0; n < d_nconnections; n++) { - in = (const float*)input_items[n]; - memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*datasize); - } - d_index += datasize; - j += datasize; } } - return j; + return noutput_items; } } /* namespace qtgui */ diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h index 9c4e1e3bcb..1463699319 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.h +++ b/gr-qtgui/lib/freq_sink_f_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2012 Free Software Foundation, Inc. + * Copyright 2012,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -35,11 +35,10 @@ namespace gr { class QTGUI_API freq_sink_f_impl : public freq_sink_f { private: - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - void initialize(); int d_fftsize; + int d_tmpbuflen; float d_fftavg; filter::firdes::win_type d_wintype; std::vector<float> d_window; @@ -55,6 +54,7 @@ namespace gr { std::vector<float*> d_residbufs; std::vector<double*> d_magbufs; float *d_fbuf; + float *d_tmpbuf; int d_argc; char *d_argv; @@ -64,9 +64,9 @@ namespace gr { gr::high_res_timer_type d_update_time; gr::high_res_timer_type d_last_time; - void windowreset(); + bool windowreset(); void buildwindow(); - void fftresize(); + bool fftresize(); void check_clicked(); void fft(float *data_out, const float *data_in, int size); @@ -74,6 +74,19 @@ namespace gr { // The message is a PMT pair (intern('freq'), double(frequency)). void handle_set_freq(pmt::pmt_t msg); + // Members used for triggering scope + trigger_mode d_trigger_mode; + float d_trigger_level; + int d_trigger_channel; + pmt::pmt_t d_trigger_tag_key; + bool d_triggered; + int d_trigger_count; + + void _reset(); + void _gui_update_trigger(); + void _test_trigger_tags(int start, int nitems); + void _test_trigger_norm(int nitems, std::vector<double*> inputs); + public: freq_sink_f_impl(int size, int wintype, double fc, double bw, @@ -111,6 +124,10 @@ namespace gr { void set_line_style(int which, int style); void set_line_marker(int which, int marker); void set_line_alpha(int which, double alpha); + void set_plot_pos_half(bool half); + void set_trigger_mode(trigger_mode mode, + float level, int channel, + const std::string &tag_key=""); std::string title(); std::string line_label(int which); diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc index ccc7fe9e07..d7fa1563fa 100644 --- a/gr-qtgui/lib/freqdisplayform.cc +++ b/gr-qtgui/lib/freqdisplayform.cc @@ -74,6 +74,37 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent) connect(d_clearmin_act, SIGNAL(triggered()), this, SLOT(clearMinHold())); + // Set up the trigger menu + d_triggermenu = new QMenu("Trigger", this); + d_tr_mode_menu = new TriggerModeMenu(this); + d_tr_level_act = new PopupMenu("Level", this); + d_tr_channel_menu = new TriggerChannelMenu(nplots, this); + d_tr_tag_key_act = new PopupMenu("Tag Key", this); + d_triggermenu->addMenu(d_tr_mode_menu); + d_triggermenu->addAction(d_tr_level_act); + d_triggermenu->addMenu(d_tr_channel_menu); + d_triggermenu->addAction(d_tr_tag_key_act); + d_menu->addMenu(d_triggermenu); + + setTriggerMode(gr::qtgui::TRIG_MODE_FREE); + connect(d_tr_mode_menu, SIGNAL(whichTrigger(gr::qtgui::trigger_mode)), + this, SLOT(setTriggerMode(gr::qtgui::trigger_mode))); + // updates trigger state by calling set level or set tag key. + connect(d_tr_mode_menu, SIGNAL(whichTrigger(gr::qtgui::trigger_mode)), + this, SLOT(updateTrigger(gr::qtgui::trigger_mode))); + + setTriggerLevel(0); + connect(d_tr_level_act, SIGNAL(whichTrigger(QString)), + this, SLOT(setTriggerLevel(QString))); + + setTriggerChannel(0); + connect(d_tr_channel_menu, SIGNAL(whichTrigger(int)), + this, SLOT(setTriggerChannel(int))); + + setTriggerTagKey(std::string("")); + connect(d_tr_tag_key_act, SIGNAL(whichTrigger(QString)), + this, SLOT(setTriggerTagKey(QString))); + Reset(); connect(d_display_plot, SIGNAL(plotPointSelected(const QPointF)), @@ -222,6 +253,13 @@ FreqDisplayForm::autoScale(bool en) } void +FreqDisplayForm::setPlotPosHalf(bool half) +{ + getPlot()->setPlotPosHalf(half); + getPlot()->replot(); +} + +void FreqDisplayForm::clearMaxHold() { getPlot()->clearMaxData(); @@ -257,3 +295,84 @@ FreqDisplayForm::getClickedFreq() const { return d_clicked_freq; } + + +/******************************************************************** + * TRIGGER METHODS + *******************************************************************/ + +void +FreqDisplayForm::setTriggerMode(gr::qtgui::trigger_mode mode) +{ + d_trig_mode = mode; + d_tr_mode_menu->getAction(mode)->setChecked(true); +} + +void +FreqDisplayForm::updateTrigger(gr::qtgui::trigger_mode mode) +{ + // If auto or normal mode, popup trigger level box to set + if((d_trig_mode == gr::qtgui::TRIG_MODE_AUTO) || (d_trig_mode == gr::qtgui::TRIG_MODE_NORM)) + d_tr_level_act->activate(QAction::Trigger); + + // if tag mode, popup tag key box to set + if(d_trig_mode == gr::qtgui::TRIG_MODE_TAG) + d_tr_tag_key_act->activate(QAction::Trigger); +} + +gr::qtgui::trigger_mode +FreqDisplayForm::getTriggerMode() const +{ + return d_trig_mode; +} + +void +FreqDisplayForm::setTriggerLevel(QString s) +{ + d_trig_level = s.toFloat(); +} + +void +FreqDisplayForm::setTriggerLevel(float level) +{ + d_trig_level = level; + d_tr_level_act->setText(QString().setNum(d_trig_level)); +} + +float +FreqDisplayForm::getTriggerLevel() const +{ + return d_trig_level; +} + +void +FreqDisplayForm::setTriggerChannel(int channel) +{ + d_trig_channel = channel; + d_tr_channel_menu->getAction(d_trig_channel)->setChecked(true); +} + +int +FreqDisplayForm::getTriggerChannel() const +{ + return d_trig_channel; +} + +void +FreqDisplayForm::setTriggerTagKey(QString s) +{ + d_trig_tag_key = s.toStdString(); +} + +void +FreqDisplayForm::setTriggerTagKey(const std::string &key) +{ + d_trig_tag_key = key; + d_tr_tag_key_act->setText(QString().fromStdString(d_trig_tag_key)); +} + +std::string +FreqDisplayForm::getTriggerTagKey() const +{ + return d_trig_tag_key; +} diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc index 5667acf2e7..0f7f9e0437 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc @@ -53,8 +53,8 @@ namespace gr { int nconnections, QWidget *parent) : sync_block("waterfall_sink_f", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(0, 0, 0)), + io_signature::make(1, -1, sizeof(float)), + io_signature::make(0, 0, 0)), d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), @@ -107,8 +107,8 @@ namespace gr { d_main_gui->close(); for(int i = 0; i < d_nconnections; i++) { - volk_free(d_residbufs[i]); - volk_free(d_magbufs[i]); + volk_free(d_residbufs[i]); + volk_free(d_magbufs[i]); } delete d_fft; volk_free(d_fbuf); @@ -127,7 +127,7 @@ namespace gr { { unsigned int ninputs = ninput_items_required.size(); for (unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = std::min(d_fftsize, 8191); + ninput_items_required[i] = std::min(d_fftsize, 8191); } } @@ -135,14 +135,14 @@ namespace gr { waterfall_sink_f_impl::initialize() { if(qApp != NULL) { - d_qApplication = qApp; + d_qApplication = qApp; } else { #if QT_VERSION >= 0x040500 std::string style = prefs::singleton()->get_string("qtgui", "style", "raster"); QApplication::setGraphicsSystem(QString(style.c_str())); #endif - d_qApplication = new QApplication(d_argc, &d_argv); + d_qApplication = new QApplication(d_argc, &d_argv); } // If a style sheet is set in the prefs file, enable it here. @@ -290,6 +290,12 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + void + waterfall_sink_f_impl::set_plot_pos_half(bool half) + { + d_main_gui->setPlotPosHalf(half); + } + std::string waterfall_sink_f_impl::title() { @@ -398,7 +404,8 @@ namespace gr { { gr::thread::scoped_lock lock(d_setlock); - int newfftsize = d_fftsize; + int newfftsize = d_main_gui->getFFTSize(); + d_fftavg = d_main_gui->getFFTAverage(); if(newfftsize != d_fftsize) { diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h index d783f31d14..ca6e3f4264 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.h +++ b/gr-qtgui/lib/waterfall_sink_f_impl.h @@ -110,6 +110,7 @@ namespace gr { void set_line_label(int which, const std::string &label); void set_line_alpha(int which, double alpha); void set_color_map(int which, const int color); + void set_plot_pos_half(bool half); std::string title(); std::string line_label(int which); diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc index fdf09d9180..c1dd8f7aab 100644 --- a/gr-qtgui/lib/waterfalldisplayform.cc +++ b/gr-qtgui/lib/waterfalldisplayform.cc @@ -330,3 +330,10 @@ WaterfallDisplayForm::getClickedFreq() const { return d_clicked_freq; } + +void +WaterfallDisplayForm::setPlotPosHalf(bool half) +{ + getPlot()->setPlotPosHalf(half); + getPlot()->replot(); +} diff --git a/gr-trellis/doc/gr-trellis.xml b/gr-trellis/doc/gr-trellis.xml index 6ffbb9ec2c..aabf9ad535 100644 --- a/gr-trellis/doc/gr-trellis.xml +++ b/gr-trellis/doc/gr-trellis.xml @@ -176,8 +176,8 @@ private: int d_O; std::vector<int> d_NS; std::vector<int> d_OS; - std::vector<int> d_PS; - std::vector<int> d_PI; + std::vector< std::vector< int> > d_PS; + std::vector< std::vector< int> > d_PI; std::vector<int> d_TMi; std::vector<int> d_TMl; void generate_PS_PI (); @@ -195,8 +195,8 @@ public: int O () const { return d_O; } const std::vector<int> & NS () const { return d_NS; } const std::vector<int> & OS () const { return d_OS; } - const std::vector<int> & PS () const { return d_PS; } - const std::vector<int> & PI () const { return d_PI; } + const std::vector< std::vector< int> > & PS () const { return d_PS; } + const std::vector< std::vector< int> > & PI () const { return d_PI; } const std::vector<int> & TMi () const { return d_TMi; } const std::vector<int> & TMl () const { return d_TMl; } }; diff --git a/gr-trellis/examples/grc/CMakeLists.txt b/gr-trellis/examples/grc/CMakeLists.txt index 35280d515f..c5d4fc8965 100644 --- a/gr-trellis/examples/grc/CMakeLists.txt +++ b/gr-trellis/examples/grc/CMakeLists.txt @@ -20,13 +20,18 @@ ## Configure GRC examples to point to the right fsm_files directory set(FSM_FILE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${GR_PKG_TRELLIS_EXAMPLES_DIR}/fsm_files/") configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/pccc.grc" - "${CMAKE_CURRENT_BINARY_DIR}/pccc.grc" + "${CMAKE_CURRENT_SOURCE_DIR}/tcm.grc" + "${CMAKE_CURRENT_BINARY_DIR}/tcm.grc" +) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/viterbi_equalization.grc" + "${CMAKE_CURRENT_BINARY_DIR}/viterbi_equalization.grc" ) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/pccc1.grc" - "${CMAKE_CURRENT_BINARY_DIR}/pccc1.grc" + "${CMAKE_CURRENT_SOURCE_DIR}/turbo_equalization.grc" + "${CMAKE_CURRENT_BINARY_DIR}/turbo_equalization.grc" ) configure_file( @@ -35,8 +40,8 @@ configure_file( ) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/sccc1.grc" - "${CMAKE_CURRENT_BINARY_DIR}/sccc1.grc" + "${CMAKE_CURRENT_SOURCE_DIR}/pccc.grc" + "${CMAKE_CURRENT_BINARY_DIR}/pccc.grc" ) configure_file( @@ -46,11 +51,12 @@ configure_file( install( FILES - ${CMAKE_CURRENT_BINARY_DIR}/interference_cancellation.grc - ${CMAKE_CURRENT_BINARY_DIR}/pccc.grc - ${CMAKE_CURRENT_BINARY_DIR}/pccc1.grc - ${CMAKE_CURRENT_BINARY_DIR}/sccc1.grc + ${CMAKE_CURRENT_BINARY_DIR}/tcm.grc + ${CMAKE_CURRENT_BINARY_DIR}/viterbi_equalization.grc + ${CMAKE_CURRENT_BINARY_DIR}/turbo_equalization.grc ${CMAKE_CURRENT_BINARY_DIR}/sccc.grc + ${CMAKE_CURRENT_BINARY_DIR}/pccc.grc + ${CMAKE_CURRENT_BINARY_DIR}/interference_cancellation.grc readme.txt DESTINATION ${GR_PKG_TRELLIS_EXAMPLES_DIR} COMPONENT "trellis-examples" diff --git a/gr-trellis/examples/grc/interference_cancellation.grc b/gr-trellis/examples/grc/interference_cancellation.grc index 2ccc723235..1dbcf69b86 100644 --- a/gr-trellis/examples/grc/interference_cancellation.grc +++ b/gr-trellis/examples/grc/interference_cancellation.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Mon Jul 28 14:00:18 2014</timestamp> + <timestamp>Fri Sep 26 18:21:00 2014</timestamp> <block> <key>options</key> <param> @@ -29,7 +29,7 @@ </param> <param> <key>generate_options</key> - <value>qt_gui</value> + <value>wx_gui</value> </param> <param> <key>category</key> @@ -52,10 +52,6 @@ <value></value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>_coordinate</key> <value>(10, 10)</value> </param> @@ -79,12 +75,8 @@ <value>"@FSM_FILE_INSTALL_DIR@"</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>_coordinate</key> - <value>(660, 11)</value> + <value>(871, 14)</value> </param> <param> <key>_rotation</key> @@ -95,7 +87,7 @@ <key>variable</key> <param> <key>id</key> - <value>block</value> + <value>R</value> </param> <param> <key>_enabled</key> @@ -103,15 +95,11 @@ </param> <param> <key>value</key> - <value>1000</value> - </param> - <param> - <key>alias</key> - <value></value> + <value>100e3</value> </param> <param> <key>_coordinate</key> - <value>(583, 10)</value> + <value>(748, 12)</value> </param> <param> <key>_rotation</key> @@ -122,7 +110,7 @@ <key>variable</key> <param> <key>id</key> - <value>R</value> + <value>noisevar</value> </param> <param> <key>_enabled</key> @@ -130,15 +118,11 @@ </param> <param> <key>value</key> - <value>100e3</value> - </param> - <param> - <key>alias</key> - <value></value> + <value>10**(-snr_db/10)</value> </param> <param> <key>_coordinate</key> - <value>(502, 10)</value> + <value>(637, 13)</value> </param> <param> <key>_rotation</key> @@ -149,7 +133,7 @@ <key>variable</key> <param> <key>id</key> - <value>noisevar</value> + <value>fsm1</value> </param> <param> <key>_enabled</key> @@ -157,15 +141,11 @@ </param> <param> <key>value</key> - <value>10**(-snr_db/10)</value> - </param> - <param> - <key>alias</key> - <value></value> + <value>"awgn1o2_16.fsm"</value> </param> <param> <key>_coordinate</key> - <value>(428, 10)</value> + <value>(849, 87)</value> </param> <param> <key>_rotation</key> @@ -173,54 +153,45 @@ </param> </block> <block> - <key>analog_random_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_random_source_x_0</value> + <value>fsm2</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>value</key> + <value>"awgn1o2_4.fsm"</value> </param> <param> - <key>min</key> - <value>0</value> + <key>_coordinate</key> + <value>(849, 153)</value> </param> <param> - <key>max</key> - <value>2</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>num_samps</key> - <value>1000</value> + <key>id</key> + <value>block</value> </param> <param> - <key>repeat</key> + <key>_enabled</key> <value>True</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>value</key> + <value>1000</value> </param> <param> <key>_coordinate</key> - <value>(21, 170)</value> + <value>(752, 85)</value> </param> <param> <key>_rotation</key> @@ -228,38 +199,34 @@ </param> </block> <block> - <key>analog_random_source_x</key> + <key>digital_chunks_to_symbols_xx</key> <param> <key>id</key> - <value>analog_random_source_x_1</value> + <value>digital_chunks_to_symbols_xx_0_0_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>min</key> - <value>0</value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>max</key> - <value>2</value> + <key>out_type</key> + <value>complex</value> </param> <param> - <key>num_samps</key> - <value>1000</value> + <key>symbol_table</key> + <value>1,1j,-1j,-1</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>dimension</key> + <value>1</value> </param> <param> - <key>alias</key> - <value></value> + <key>num_ports</key> + <value>1</value> </param> <param> <key>affinity</key> @@ -270,12 +237,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(25, 291)</value> + <value>(408, 1719)</value> </param> <param> <key>_rotation</key> @@ -283,46 +246,22 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_sub_xx_0</value> + <value>virtual_source_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>user1</value> </param> <param> <key>_coordinate</key> - <value>(536, 529)</value> + <value>(356, 1844)</value> </param> <param> <key>_rotation</key> @@ -330,46 +269,22 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_multiply_xx_0</value> + <value>virtual_source_0_2_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>user2_est</value> </param> <param> <key>_coordinate</key> - <value>(771, 525)</value> + <value>(10, 1649)</value> </param> <param> <key>_rotation</key> @@ -380,7 +295,7 @@ <key>blocks_sub_xx</key> <param> <key>id</key> - <value>blocks_sub_xx_3</value> + <value>blocks_sub_xx_2_0</value> </param> <param> <key>_enabled</key> @@ -388,7 +303,7 @@ </param> <param> <key>type</key> - <value>short</value> + <value>complex</value> </param> <param> <key>vlen</key> @@ -399,10 +314,6 @@ <value>2</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>affinity</key> <value></value> </param> @@ -411,12 +322,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(535, 792)</value> + <value>(963, 1695)</value> </param> <param> <key>_rotation</key> @@ -424,46 +331,22 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_sub_xx_2</value> + <value>virtual_source_0_1_2</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>observation</value> </param> <param> <key>_coordinate</key> - <value>(944, 978)</value> + <value>(705, 1660)</value> </param> <param> <key>_rotation</key> @@ -471,10 +354,10 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>blocks_multiply_const_vxx</key> <param> <key>id</key> - <value>blocks_sub_xx_1</value> + <value>blocks_multiply_const_vxx_2_0</value> </param> <param> <key>_enabled</key> @@ -482,19 +365,15 @@ </param> <param> <key>type</key> - <value>short</value> - </param> - <param> - <key>vlen</key> - <value>1</value> + <value>complex</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>const</key> + <value>(1-alpha)**0.5</value> </param> <param> - <key>alias</key> - <value></value> + <key>vlen</key> + <value>1</value> </param> <param> <key>affinity</key> @@ -505,12 +384,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(540, 1141)</value> + <value>(721, 1727)</value> </param> <param> <key>_rotation</key> @@ -518,30 +393,34 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>digital_chunks_to_symbols_xx</key> <param> <key>id</key> - <value>blocks_sub_xx_2_0</value> + <value>digital_chunks_to_symbols_xx_0_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> + <key>in_type</key> + <value>byte</value> + </param> + <param> + <key>out_type</key> <value>complex</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>symbol_table</key> + <value>1,1j,-1j,-1</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>dimension</key> + <value>1</value> </param> <param> - <key>alias</key> - <value></value> + <key>num_ports</key> + <value>1</value> </param> <param> <key>affinity</key> @@ -552,12 +431,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(975, 1342)</value> + <value>(416, 1251)</value> </param> <param> <key>_rotation</key> @@ -565,46 +440,22 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_sub_xx_1_0</value> + <value>virtual_source_0_4</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>user2</value> </param> <param> <key>_coordinate</key> - <value>(559, 1536)</value> + <value>(359, 1373)</value> </param> <param> <key>_rotation</key> @@ -612,46 +463,22 @@ </param> </block> <block> - <key>blocks_add_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_add_xx_0</value> + <value>virtual_source_0_2</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>user1_est</value> </param> <param> <key>_coordinate</key> - <value>(1224, 245)</value> + <value>(33, 1187)</value> </param> <param> <key>_rotation</key> @@ -659,10 +486,10 @@ </param> </block> <block> - <key>analog_noise_source_x</key> + <key>blocks_sub_xx</key> <param> <key>id</key> - <value>analog_noise_source_x_0</value> + <value>blocks_sub_xx_2</value> </param> <param> <key>_enabled</key> @@ -673,20 +500,12 @@ <value>complex</value> </param> <param> - <key>noise_type</key> - <value>analog.GR_GAUSSIAN</value> - </param> - <param> - <key>amp</key> - <value>noisevar</value> - </param> - <param> - <key>seed</key> - <value>-42</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>alias</key> - <value></value> + <key>num_inputs</key> + <value>2</value> </param> <param> <key>affinity</key> @@ -697,12 +516,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(1178, 321)</value> + <value>(942, 1229)</value> </param> <param> <key>_rotation</key> @@ -710,50 +525,22 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>virtual_source_0_1_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>samples_per_second</key> - <value>R</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>ignoretag</key> - <value>True</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>observation</value> </param> <param> <key>_coordinate</key> - <value>(579, 143)</value> + <value>(698, 1198)</value> </param> <param> <key>_rotation</key> @@ -764,7 +551,7 @@ <key>blocks_multiply_const_vxx</key> <param> <key>id</key> - <value>blocks_multiply_const_vxx_0</value> + <value>blocks_multiply_const_vxx_2</value> </param> <param> <key>_enabled</key> @@ -783,10 +570,6 @@ <value>1</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>affinity</key> <value></value> </param> @@ -795,12 +578,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(988, 196)</value> + <value>(708, 1259)</value> </param> <param> <key>_rotation</key> @@ -808,54 +587,45 @@ </param> </block> <block> - <key>digital_chunks_to_symbols_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>digital_chunks_to_symbols_xx_0</value> + <value>virtual_source_0_3</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>in_type</key> - <value>short</value> - </param> - <param> - <key>out_type</key> - <value>complex</value> - </param> - <param> - <key>symbol_table</key> - <value>1,1j,-1j,-1</value> - </param> - <param> - <key>dimension</key> - <value>1</value> + <key>stream_id</key> + <value>user2</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>_coordinate</key> + <value>(342, 928)</value> </param> <param> - <key>alias</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>affinity</key> - <value></value> + <key>id</key> + <value>virtual_sink_0_2_0</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>user2_est</value> </param> <param> <key>_coordinate</key> - <value>(703, 211)</value> + <value>(341, 1025)</value> </param> <param> <key>_rotation</key> @@ -863,46 +633,45 @@ </param> </block> <block> - <key>blocks_multiply_const_vxx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_multiply_const_vxx_1</value> + <value>virtual_source_0_1_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>const</key> - <value>(1-alpha)**0.5</value> + <key>stream_id</key> + <value>observation</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>_coordinate</key> + <value>(11, 873)</value> </param> <param> - <key>alias</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>affinity</key> - <value></value> + <key>id</key> + <value>virtual_source_0</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>user1</value> </param> <param> <key>_coordinate</key> - <value>(994, 319)</value> + <value>(348, 566)</value> </param> <param> <key>_rotation</key> @@ -910,54 +679,45 @@ </param> </block> <block> - <key>digital_chunks_to_symbols_xx</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>digital_chunks_to_symbols_xx_0_0</value> + <value>virtual_sink_0_2</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>in_type</key> - <value>short</value> - </param> - <param> - <key>out_type</key> - <value>complex</value> - </param> - <param> - <key>symbol_table</key> - <value>1,1j,-1j,-1</value> + <key>stream_id</key> + <value>user1_est</value> </param> <param> - <key>dimension</key> - <value>1</value> - </param> - <param> - <key>num_ports</key> - <value>1</value> + <key>_coordinate</key> + <value>(355, 687)</value> </param> <param> - <key>alias</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>affinity</key> - <value></value> + <key>id</key> + <value>virtual_source_0_1</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>observation</value> </param> <param> <key>_coordinate</key> - <value>(703, 311)</value> + <value>(13, 530)</value> </param> <param> <key>_rotation</key> @@ -965,84 +725,81 @@ </param> </block> <block> - <key>digital_chunks_to_symbols_xx</key> + <key>wxgui_numbersink2</key> <param> <key>id</key> - <value>digital_chunks_to_symbols_xx_0_0_0</value> + <value>wxgui_numbersink2_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>in_type</key> - <value>short</value> + <key>type</key> + <value>float</value> </param> <param> - <key>out_type</key> - <value>complex</value> + <key>title</key> + <value>BER 1 (raw)</value> </param> <param> - <key>symbol_table</key> - <value>1,1j,-1j,-1</value> + <key>units</key> + <value>BER</value> </param> <param> - <key>dimension</key> - <value>1</value> + <key>samp_rate</key> + <value>R</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>min_value</key> + <value>0</value> </param> <param> - <key>alias</key> - <value></value> + <key>max_value</key> + <value>1</value> </param> <param> - <key>affinity</key> - <value></value> + <key>factor</key> + <value>1.0</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>decimal_places</key> + <value>6</value> </param> <param> - <key>maxoutbuf</key> + <key>ref_level</key> <value>0</value> </param> <param> - <key>_coordinate</key> - <value>(418, 1000)</value> + <key>number_rate</key> + <value>15</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>peak_hold</key> + <value>False</value> </param> - </block> - <block> - <key>blocks_multiply_const_vxx</key> <param> - <key>id</key> - <value>blocks_multiply_const_vxx_2</value> + <key>average</key> + <value>False</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>type</key> - <value>complex</value> + <key>show_gauge</key> + <value>True</value> </param> <param> - <key>const</key> - <value>alpha**0.5</value> + <key>win_size</key> + <value></value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>grid_pos</key> + <value>0,0,1,1</value> </param> <param> - <key>alias</key> + <key>notebook</key> <value></value> </param> <param> @@ -1050,16 +807,8 @@ <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(710, 1008)</value> + <value>(944, 556)</value> </param> <param> <key>_rotation</key> @@ -1067,10 +816,10 @@ </param> </block> <block> - <key>blocks_multiply_const_vxx</key> + <key>wxgui_numbersink2</key> <param> <key>id</key> - <value>blocks_multiply_const_vxx_2_0</value> + <value>wxgui_numbersink2_2</value> </param> <param> <key>_enabled</key> @@ -1078,73 +827,70 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>float</value> </param> <param> - <key>const</key> - <value>(1-alpha)**0.5</value> + <key>title</key> + <value>BER 2 (raw)</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>units</key> + <value>BER</value> </param> <param> - <key>alias</key> - <value></value> + <key>samp_rate</key> + <value>R</value> </param> <param> - <key>affinity</key> - <value></value> + <key>min_value</key> + <value>0</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>max_value</key> + <value>1.0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>factor</key> + <value>1.0</value> </param> <param> - <key>_coordinate</key> - <value>(733, 1374)</value> + <key>decimal_places</key> + <value>6</value> </param> <param> - <key>_rotation</key> + <key>ref_level</key> <value>0</value> </param> - </block> - <block> - <key>digital_chunks_to_symbols_xx</key> <param> - <key>id</key> - <value>digital_chunks_to_symbols_xx_0_0_1</value> + <key>number_rate</key> + <value>15</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>in_type</key> - <value>short</value> + <key>average</key> + <value>False</value> </param> <param> - <key>out_type</key> - <value>complex</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>symbol_table</key> - <value>1,1j,-1j,-1</value> + <key>show_gauge</key> + <value>True</value> </param> <param> - <key>dimension</key> - <value>1</value> + <key>win_size</key> + <value></value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>grid_pos</key> + <value>0,1,1,1</value> </param> <param> - <key>alias</key> + <key>notebook</key> <value></value> </param> <param> @@ -1152,16 +898,8 @@ <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(420, 1366)</value> + <value>(944, 886)</value> </param> <param> <key>_rotation</key> @@ -1169,128 +907,101 @@ </param> </block> <block> - <key>variable_qtgui_range</key> + <key>wxgui_numbersink2</key> <param> <key>id</key> - <value>alpha</value> + <value>wxgui_numbersink2_3</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>P1/P</value> + <key>type</key> + <value>float</value> </param> <param> - <key>value</key> - <value>0.6</value> + <key>title</key> + <value>BER 2 (after cancelling user 1)</value> </param> <param> - <key>start</key> - <value>0</value> + <key>units</key> + <value>BER</value> </param> <param> - <key>stop</key> - <value>1</value> + <key>samp_rate</key> + <value>R</value> </param> <param> - <key>step</key> - <value>0.01</value> + <key>min_value</key> + <value>0</value> </param> <param> - <key>widget</key> - <value>counter_slider</value> + <key>max_value</key> + <value>1.0</value> </param> <param> - <key>orient</key> - <value>Qt.Horizontal</value> + <key>factor</key> + <value>1.0</value> </param> <param> - <key>min_len</key> - <value>200</value> + <key>decimal_places</key> + <value>6</value> </param> <param> - <key>gui_hint</key> - <value></value> + <key>ref_level</key> + <value>0</value> </param> <param> - <key>alias</key> - <value></value> + <key>number_rate</key> + <value>15</value> </param> <param> - <key>_coordinate</key> - <value>(177, 10)</value> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>_rotation</key> - <value>180</value> + <key>average</key> + <value>False</value> </param> - </block> - <block> - <key>variable_qtgui_range</key> <param> - <key>id</key> - <value>snr_db</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>_enabled</key> + <key>show_gauge</key> <value>True</value> </param> <param> - <key>label</key> - <value>P/sigma^2 (dB)</value> - </param> - <param> - <key>value</key> - <value>16</value> - </param> - <param> - <key>start</key> - <value>0</value> - </param> - <param> - <key>stop</key> - <value>20</value> - </param> - <param> - <key>step</key> - <value>0.01</value> - </param> - <param> - <key>widget</key> - <value>counter_slider</value> - </param> - <param> - <key>orient</key> - <value>Qt.Horizontal</value> + <key>win_size</key> + <value></value> </param> <param> - <key>min_len</key> - <value>200</value> + <key>grid_pos</key> + <value>1,1,1,1</value> </param> <param> - <key>gui_hint</key> + <key>notebook</key> <value></value> </param> <param> - <key>alias</key> + <key>affinity</key> <value></value> </param> <param> <key>_coordinate</key> - <value>(300, 10)</value> + <value>(945, 1351)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> - <key>blocks_add_xx</key> + <key>blocks_multiply_const_vxx</key> <param> <key>id</key> - <value>blocks_add_xx_1</value> + <value>blocks_multiply_const_vxx_1</value> </param> <param> <key>_enabled</key> @@ -1301,18 +1012,14 @@ <value>complex</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>const</key> + <value>(1-alpha)**0.5</value> </param> <param> <key>vlen</key> <value>1</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>affinity</key> <value></value> </param> @@ -1321,12 +1028,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(1400, 262)</value> + <value>(943, 402)</value> </param> <param> <key>_rotation</key> @@ -1334,10 +1037,10 @@ </param> </block> <block> - <key>qtgui_const_sink_x</key> + <key>blocks_multiply_const_vxx</key> <param> <key>id</key> - <value>qtgui_const_sink_x_0</value> + <value>blocks_multiply_const_vxx_0</value> </param> <param> <key>_enabled</key> @@ -1348,320 +1051,141 @@ <value>complex</value> </param> <param> - <key>name</key> - <value>Constellation</value> - </param> - <param> - <key>size</key> - <value>1024</value> - </param> - <param> - <key>grid</key> - <value>False</value> - </param> - <param> - <key>autoscale</key> - <value>False</value> - </param> - <param> - <key>ymin</key> - <value>-2</value> - </param> - <param> - <key>ymax</key> - <value>2</value> - </param> - <param> - <key>xmin</key> - <value>-2</value> - </param> - <param> - <key>xmax</key> - <value>2</value> + <key>const</key> + <value>alpha**0.5</value> </param> <param> - <key>nconnections</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>update_time</key> - <value>0.10</value> - </param> - <param> - <key>gui_hint</key> + <key>affinity</key> <value></value> </param> <param> - <key>tr_mode</key> - <value>qtgui.TRIG_MODE_FREE</value> - </param> - <param> - <key>tr_slope</key> - <value>qtgui.TRIG_SLOPE_POS</value> - </param> - <param> - <key>tr_level</key> - <value>0.0</value> - </param> - <param> - <key>tr_chan</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>tr_tag</key> - <value>""</value> - </param> - <param> - <key>label1</key> - <value></value> - </param> - <param> - <key>width1</key> - <value>1</value> - </param> - <param> - <key>color1</key> - <value>"blue"</value> - </param> - <param> - <key>style1</key> - <value>0</value> + <key>_coordinate</key> + <value>(947, 301)</value> </param> <param> - <key>marker1</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>alpha1</key> - <value>1.0</value> - </param> - <param> - <key>label2</key> - <value></value> + <key>id</key> + <value>virtual_sink_0_0</value> </param> <param> - <key>width2</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>color2</key> - <value>"red"</value> + <key>stream_id</key> + <value>user2</value> </param> <param> - <key>style2</key> - <value>0</value> + <key>_coordinate</key> + <value>(208, 340)</value> </param> <param> - <key>marker2</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>analog_random_source_x</key> <param> - <key>alpha2</key> - <value>1.0</value> - </param> - <param> - <key>label3</key> - <value></value> - </param> - <param> - <key>width3</key> - <value>1</value> + <key>id</key> + <value>analog_random_source_x_1</value> </param> <param> - <key>color3</key> - <value>"red"</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>style3</key> - <value>0</value> + <key>type</key> + <value>byte</value> </param> <param> - <key>marker3</key> + <key>min</key> <value>0</value> </param> <param> - <key>alpha3</key> - <value>1.0</value> - </param> - <param> - <key>label4</key> - <value></value> - </param> - <param> - <key>width4</key> - <value>1</value> - </param> - <param> - <key>color4</key> - <value>"red"</value> - </param> - <param> - <key>style4</key> - <value>0</value> + <key>max</key> + <value>2</value> </param> <param> - <key>marker4</key> - <value>0</value> + <key>num_samps</key> + <value>block</value> </param> <param> - <key>alpha4</key> - <value>1.0</value> + <key>repeat</key> + <value>True</value> </param> <param> - <key>label5</key> + <key>affinity</key> <value></value> </param> <param> - <key>width5</key> - <value>1</value> - </param> - <param> - <key>color5</key> - <value>"red"</value> - </param> - <param> - <key>style5</key> - <value>0</value> - </param> - <param> - <key>marker5</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>alpha5</key> - <value>1.0</value> - </param> - <param> - <key>label6</key> - <value></value> - </param> - <param> - <key>width6</key> - <value>1</value> - </param> - <param> - <key>color6</key> - <value>"red"</value> - </param> - <param> - <key>style6</key> - <value>0</value> + <key>_coordinate</key> + <value>(22, 374)</value> </param> <param> - <key>marker6</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> <param> - <key>alpha6</key> - <value>1.0</value> - </param> - <param> - <key>label7</key> - <value></value> - </param> - <param> - <key>width7</key> - <value>1</value> - </param> - <param> - <key>color7</key> - <value>"red"</value> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0</value> </param> <param> - <key>style7</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>marker7</key> - <value>0</value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>alpha7</key> - <value>1.0</value> + <key>out_type</key> + <value>complex</value> </param> <param> - <key>label8</key> - <value></value> + <key>symbol_table</key> + <value>1,1j,-1j,-1</value> </param> <param> - <key>width8</key> + <key>dimension</key> <value>1</value> </param> <param> - <key>color8</key> - <value>"red"</value> - </param> - <param> - <key>style8</key> - <value>0</value> - </param> - <param> - <key>marker8</key> - <value>0</value> - </param> - <param> - <key>alpha8</key> - <value>1.0</value> - </param> - <param> - <key>label9</key> - <value></value> - </param> - <param> - <key>width9</key> + <key>num_ports</key> <value>1</value> </param> <param> - <key>color9</key> - <value>"red"</value> - </param> - <param> - <key>style9</key> - <value>0</value> - </param> - <param> - <key>marker9</key> - <value>0</value> - </param> - <param> - <key>alpha9</key> - <value>1.0</value> - </param> - <param> - <key>label10</key> + <key>affinity</key> <value></value> </param> <param> - <key>width10</key> - <value>1</value> - </param> - <param> - <key>color10</key> - <value>"red"</value> - </param> - <param> - <key>style10</key> - <value>0</value> - </param> - <param> - <key>marker10</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>alpha10</key> - <value>1.0</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> <key>_coordinate</key> - <value>(0, 0)</value> + <value>(700, 294)</value> </param> <param> <key>_rotation</key> @@ -1669,26 +1193,26 @@ </param> </block> <block> - <key>blocks_short_to_float</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>blocks_short_to_float_0</value> + <value>blocks_throttle_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>type</key> + <value>byte</value> </param> <param> - <key>scale</key> - <value>1</value> + <key>samples_per_second</key> + <value>R</value> </param> <param> - <key>alias</key> - <value></value> + <key>vlen</key> + <value>1</value> </param> <param> <key>affinity</key> @@ -1699,12 +1223,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(1010, 1551)</value> + <value>(576, 226)</value> </param> <param> <key>_rotation</key> @@ -1712,226 +1232,194 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>analog_random_source_x</key> <param> <key>id</key> - <value>qtgui_number_sink_0</value> + <value>analog_random_source_x_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> - </param> - <param> <key>type</key> - <value>float</value> - </param> - <param> - <key>autoscale</key> - <value>False</value> - </param> - <param> - <key>avg</key> - <value>0.001</value> - </param> - <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> - </param> - <param> - <key>nconnections</key> - <value>1</value> + <value>byte</value> </param> <param> <key>min</key> - <value>-1</value> + <value>0</value> </param> <param> <key>max</key> - <value>1</value> - </param> - <param> - <key>update_time</key> - <value>0.10</value> + <value>2</value> </param> <param> - <key>gui_hint</key> - <value>0,0,1,1</value> + <key>num_samps</key> + <value>block</value> </param> <param> - <key>label1</key> - <value></value> + <key>repeat</key> + <value>True</value> </param> <param> - <key>unit1</key> + <key>affinity</key> <value></value> </param> <param> - <key>color1</key> - <value>("black", "black")</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>factor1</key> - <value>1</value> + <key>_coordinate</key> + <value>(18, 253)</value> </param> <param> - <key>label2</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>unit2</key> - <value></value> + <key>id</key> + <value>virtual_sink_0</value> </param> <param> - <key>color2</key> - <value>("black", "black")</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>factor2</key> - <value>1</value> + <key>stream_id</key> + <value>user1</value> </param> <param> - <key>label3</key> - <value></value> + <key>_coordinate</key> + <value>(208, 229)</value> </param> <param> - <key>unit3</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> <param> - <key>color3</key> - <value>("black", "black")</value> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0_0</value> </param> <param> - <key>factor3</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>label4</key> - <value></value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>unit4</key> - <value></value> + <key>out_type</key> + <value>complex</value> </param> <param> - <key>color4</key> - <value>("black", "black")</value> + <key>symbol_table</key> + <value>1,1j,-1j,-1</value> </param> <param> - <key>factor4</key> + <key>dimension</key> <value>1</value> </param> <param> - <key>label5</key> - <value></value> - </param> - <param> - <key>unit5</key> - <value></value> - </param> - <param> - <key>color5</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor5</key> + <key>num_ports</key> <value>1</value> </param> <param> - <key>label6</key> + <key>affinity</key> <value></value> </param> <param> - <key>unit6</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>color6</key> - <value>("black", "black")</value> + <key>_coordinate</key> + <value>(700, 394)</value> </param> <param> - <key>factor6</key> - <value>1</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_add_xx</key> <param> - <key>label7</key> - <value></value> + <key>id</key> + <value>blocks_add_xx_1</value> </param> <param> - <key>unit7</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>color7</key> - <value>("black", "black")</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>factor7</key> - <value>1</value> + <key>num_inputs</key> + <value>2</value> </param> <param> - <key>label8</key> - <value></value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>unit8</key> + <key>affinity</key> <value></value> </param> <param> - <key>color8</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor8</key> - <value>1</value> - </param> - <param> - <key>label9</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>unit9</key> - <value></value> + <key>_coordinate</key> + <value>(1400, 341)</value> </param> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_add_xx</key> <param> - <key>factor9</key> - <value>1</value> + <key>id</key> + <value>blocks_add_xx_0</value> </param> <param> - <key>label10</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit10</key> - <value></value> + <key>type</key> + <value>complex</value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>num_inputs</key> + <value>2</value> </param> <param> - <key>factor10</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>alias</key> + <key>affinity</key> <value></value> </param> <param> - <key>affinity</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(1257, 471)</value> + <value>(1224, 324)</value> </param> <param> <key>_rotation</key> @@ -1939,10 +1427,10 @@ </param> </block> <block> - <key>trellis_encoder_xx</key> + <key>analog_noise_source_x</key> <param> <key>id</key> - <value>trellis_encoder_xx_1</value> + <value>analog_noise_source_x_0</value> </param> <param> <key>_enabled</key> @@ -1950,19 +1438,19 @@ </param> <param> <key>type</key> - <value>ss</value> + <value>complex</value> </param> <param> - <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> </param> <param> - <key>init_state</key> - <value>0</value> + <key>amp</key> + <value>noisevar</value> </param> <param> - <key>alias</key> - <value></value> + <key>seed</key> + <value>-42</value> </param> <param> <key>affinity</key> @@ -1973,12 +1461,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(336, 311)</value> + <value>(1178, 400)</value> </param> <param> <key>_rotation</key> @@ -1986,46 +1470,22 @@ </param> </block> <block> - <key>trellis_encoder_xx</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>trellis_encoder_xx_0</value> + <value>virtual_sink_0_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>ss</value> - </param> - <param> - <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> - </param> - <param> - <key>init_state</key> - <value>0</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>observation</value> </param> <param> <key>_coordinate</key> - <value>(340, 187)</value> + <value>(1407, 453)</value> </param> <param> <key>_rotation</key> @@ -2033,10 +1493,10 @@ </param> </block> <block> - <key>trellis_viterbi_combined_xx</key> + <key>wxgui_scopesink2</key> <param> <key>id</key> - <value>trellis_viterbi_combined_xx_1</value> + <value>wxgui_scopesink2_0</value> </param> <param> <key>_enabled</key> @@ -2044,59 +1504,67 @@ </param> <param> <key>type</key> - <value>c</value> + <value>complex</value> </param> <param> - <key>out_type</key> - <value>s</value> + <key>title</key> + <value>Scope Plot</value> </param> <param> - <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> + <key>samp_rate</key> + <value>R</value> </param> <param> - <key>block_size</key> - <value>1000</value> + <key>v_scale</key> + <value>0</value> </param> <param> - <key>init_state</key> - <value>-1</value> + <key>v_offset</key> + <value>0</value> </param> <param> - <key>final_state</key> - <value>-1</value> + <key>t_scale</key> + <value>0</value> </param> <param> - <key>dim</key> - <value>1</value> + <key>ac_couple</key> + <value>False</value> </param> <param> - <key>table</key> - <value>alpha**0.5*1,alpha**0.5*1j,alpha**0.5*(-1j),alpha**0.5*(-1)</value> + <key>xy_mode</key> + <value>True</value> </param> <param> - <key>metric_type</key> - <value>digital.TRELLIS_EUCLIDEAN</value> + <key>num_inputs</key> + <value>1</value> </param> <param> - <key>alias</key> + <key>win_size</key> <value></value> </param> <param> - <key>affinity</key> + <key>grid_pos</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>notebook</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>trig_mode</key> + <value>wxgui.TRIG_MODE_AUTO</value> + </param> + <param> + <key>y_axis_label</key> + <value>Counts</value> + </param> + <param> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(79, 501)</value> + <value>(1383, 208)</value> </param> <param> <key>_rotation</key> @@ -2107,7 +1575,7 @@ <key>trellis_viterbi_combined_xx</key> <param> <key>id</key> - <value>trellis_viterbi_combined_xx_2</value> + <value>trellis_viterbi_combined_xx_1</value> </param> <param> <key>_enabled</key> @@ -2119,15 +1587,15 @@ </param> <param> <key>out_type</key> - <value>s</value> + <value>b</value> </param> <param> <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> + <value>prefix+fsm1</value> </param> <param> <key>block_size</key> - <value>1000</value> + <value>block</value> </param> <param> <key>init_state</key> @@ -2143,17 +1611,13 @@ </param> <param> <key>table</key> - <value>(1-alpha)**0.5*1,(1-alpha)**0.5*1j,(1-alpha)**0.5*(-1j),(1-alpha)**0.5*(-1)</value> + <value>alpha**0.5*1,alpha**0.5*1j,alpha**0.5*(-1j),alpha**0.5*(-1)</value> </param> <param> <key>metric_type</key> <value>digital.TRELLIS_EUCLIDEAN</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>affinity</key> <value></value> </param> @@ -2162,12 +1626,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(82, 766)</value> + <value>(75, 583)</value> </param> <param> <key>_rotation</key> @@ -2178,7 +1638,7 @@ <key>trellis_viterbi_combined_xx</key> <param> <key>id</key> - <value>trellis_viterbi_combined_xx_0</value> + <value>trellis_viterbi_combined_xx_0_0</value> </param> <param> <key>_enabled</key> @@ -2190,15 +1650,15 @@ </param> <param> <key>out_type</key> - <value>s</value> + <value>b</value> </param> <param> <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> + <value>prefix+fsm1</value> </param> <param> <key>block_size</key> - <value>1000</value> + <value>block</value> </param> <param> <key>init_state</key> @@ -2214,17 +1674,13 @@ </param> <param> <key>table</key> - <value>(1-alpha)**0.5*1,(1-alpha)**0.5*1j,(1-alpha)**0.5*(-1j),(1-alpha)**0.5*(-1)</value> + <value>alpha**0.5*1,alpha**0.5*1j,alpha**0.5*(-1j),alpha**0.5*(-1)</value> </param> <param> <key>metric_type</key> <value>digital.TRELLIS_EUCLIDEAN</value> </param> <param> - <key>alias</key> - <value></value> - </param> - <param> <key>affinity</key> <value></value> </param> @@ -2233,12 +1689,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(83, 1111)</value> + <value>(63, 1848)</value> </param> <param> <key>_rotation</key> @@ -2246,10 +1698,10 @@ </param> </block> <block> - <key>trellis_viterbi_combined_xx</key> + <key>trellis_encoder_xx</key> <param> <key>id</key> - <value>trellis_viterbi_combined_xx_0_0</value> + <value>trellis_encoder_xx_0</value> </param> <param> <key>_enabled</key> @@ -2257,43 +1709,15 @@ </param> <param> <key>type</key> - <value>c</value> - </param> - <param> - <key>out_type</key> - <value>s</value> + <value>bb</value> </param> <param> <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> - </param> - <param> - <key>block_size</key> - <value>1000</value> + <value>prefix+fsm1</value> </param> <param> <key>init_state</key> - <value>-1</value> - </param> - <param> - <key>final_state</key> - <value>-1</value> - </param> - <param> - <key>dim</key> - <value>1</value> - </param> - <param> - <key>table</key> - <value>alpha**0.5*1,alpha**0.5*1j,alpha**0.5*(-1j),alpha**0.5*(-1)</value> - </param> - <param> - <key>metric_type</key> - <value>digital.TRELLIS_EUCLIDEAN</value> - </param> - <param> - <key>alias</key> - <value></value> + <value>0</value> </param> <param> <key>affinity</key> @@ -2304,12 +1728,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(75, 1495)</value> + <value>(337, 270)</value> </param> <param> <key>_rotation</key> @@ -2317,10 +1737,10 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>trellis_encoder_xx</key> <param> <key>id</key> - <value>blocks_multiply_xx_2_0</value> + <value>trellis_encoder_xx_2</value> </param> <param> <key>_enabled</key> @@ -2328,19 +1748,15 @@ </param> <param> <key>type</key> - <value>short</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> + <value>bb</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>fsm_args</key> + <value>prefix+fsm1</value> </param> <param> - <key>alias</key> - <value></value> + <key>init_state</key> + <value>0</value> </param> <param> <key>affinity</key> @@ -2351,12 +1767,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(771, 1530)</value> + <value>(87, 1251)</value> </param> <param> <key>_rotation</key> @@ -2364,26 +1776,26 @@ </param> </block> <block> - <key>blocks_short_to_float</key> + <key>trellis_encoder_xx</key> <param> <key>id</key> - <value>blocks_short_to_float_1</value> + <value>trellis_encoder_xx_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>type</key> + <value>bb</value> </param> <param> - <key>scale</key> - <value>1</value> + <key>fsm_args</key> + <value>prefix+fsm2</value> </param> <param> - <key>alias</key> - <value></value> + <key>init_state</key> + <value>0</value> </param> <param> <key>affinity</key> @@ -2394,12 +1806,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(985, 1608)</value> + <value>(376, 381)</value> </param> <param> <key>_rotation</key> @@ -2407,226 +1815,62 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>trellis_viterbi_combined_xx</key> <param> <key>id</key> - <value>qtgui_number_sink_0_0_0_0</value> + <value>trellis_viterbi_combined_xx_2</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> - </param> - <param> <key>type</key> - <value>float</value> - </param> - <param> - <key>autoscale</key> - <value>False</value> + <value>c</value> </param> <param> - <key>avg</key> - <value>0.001</value> + <key>out_type</key> + <value>b</value> </param> <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> + <key>fsm_args</key> + <value>prefix+fsm2</value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>block_size</key> + <value>block</value> </param> <param> - <key>min</key> + <key>init_state</key> <value>-1</value> </param> <param> - <key>max</key> - <value>1</value> - </param> - <param> - <key>update_time</key> - <value>0.10</value> - </param> - <param> - <key>gui_hint</key> - <value>1,0,1,1</value> - </param> - <param> - <key>label1</key> - <value>BER 2 (raw)</value> - </param> - <param> - <key>unit1</key> - <value></value> - </param> - <param> - <key>color1</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor1</key> - <value>1</value> - </param> - <param> - <key>label2</key> - <value></value> - </param> - <param> - <key>unit2</key> - <value></value> - </param> - <param> - <key>color2</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor2</key> - <value>1</value> - </param> - <param> - <key>label3</key> - <value></value> - </param> - <param> - <key>unit3</key> - <value></value> - </param> - <param> - <key>color3</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor3</key> - <value>1</value> - </param> - <param> - <key>label4</key> - <value></value> - </param> - <param> - <key>unit4</key> - <value></value> - </param> - <param> - <key>color4</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor4</key> - <value>1</value> - </param> - <param> - <key>label5</key> - <value></value> - </param> - <param> - <key>unit5</key> - <value></value> - </param> - <param> - <key>color5</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor5</key> - <value>1</value> - </param> - <param> - <key>label6</key> - <value></value> - </param> - <param> - <key>unit6</key> - <value></value> - </param> - <param> - <key>color6</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor6</key> - <value>1</value> - </param> - <param> - <key>label7</key> - <value></value> - </param> - <param> - <key>unit7</key> - <value></value> - </param> - <param> - <key>color7</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor7</key> - <value>1</value> - </param> - <param> - <key>label8</key> - <value></value> - </param> - <param> - <key>unit8</key> - <value></value> - </param> - <param> - <key>color8</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor8</key> - <value>1</value> - </param> - <param> - <key>label9</key> - <value></value> - </param> - <param> - <key>unit9</key> - <value></value> - </param> - <param> - <key>color9</key> - <value>("black", "black")</value> + <key>final_state</key> + <value>-1</value> </param> <param> - <key>factor9</key> + <key>dim</key> <value>1</value> </param> <param> - <key>label10</key> - <value></value> - </param> - <param> - <key>unit10</key> - <value></value> - </param> - <param> - <key>color10</key> - <value>("black", "black")</value> + <key>table</key> + <value>(1-alpha)**0.5*1,(1-alpha)**0.5*1j,(1-alpha)**0.5*(-1j),(1-alpha)**0.5*(-1)</value> </param> <param> - <key>factor10</key> - <value>1</value> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> </param> <param> - <key>alias</key> + <key>affinity</key> <value></value> </param> <param> - <key>affinity</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(1272, 1551)</value> + <value>(85, 931)</value> </param> <param> <key>_rotation</key> @@ -2634,10 +1878,10 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>trellis_viterbi_combined_xx</key> <param> <key>id</key> - <value>blocks_multiply_xx_1</value> + <value>trellis_viterbi_combined_xx_0</value> </param> <param> <key>_enabled</key> @@ -2645,62 +1889,39 @@ </param> <param> <key>type</key> - <value>short</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> + <value>c</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>out_type</key> + <value>b</value> </param> <param> - <key>_coordinate</key> - <value>(785, 779)</value> + <key>fsm_args</key> + <value>prefix+fsm2</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>block_size</key> + <value>block</value> </param> - </block> - <block> - <key>blocks_short_to_float</key> <param> - <key>id</key> - <value>blocks_short_to_float_2</value> + <key>init_state</key> + <value>-1</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>final_state</key> + <value>-1</value> </param> <param> - <key>vlen</key> + <key>dim</key> <value>1</value> </param> <param> - <key>scale</key> - <value>1</value> + <key>table</key> + <value>(1-alpha)**0.5*1,(1-alpha)**0.5*1j,(1-alpha)**0.5*(-1j),(1-alpha)**0.5*(-1)</value> </param> <param> - <key>alias</key> - <value></value> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> </param> <param> <key>affinity</key> @@ -2711,12 +1932,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(1013, 735)</value> + <value>(81, 1362)</value> </param> <param> <key>_rotation</key> @@ -2724,10 +1941,10 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>trellis_encoder_xx</key> <param> <key>id</key> - <value>blocks_multiply_xx_2</value> + <value>trellis_encoder_xx_2_0</value> </param> <param> <key>_enabled</key> @@ -2735,63 +1952,16 @@ </param> <param> <key>type</key> - <value>short</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> - <param> - <key>affinity</key> - <value></value> - </param> - <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> + <value>bb</value> </param> <param> - <key>_coordinate</key> - <value>(796, 1136)</value> + <key>fsm_args</key> + <value>prefix+fsm2</value> </param> <param> - <key>_rotation</key> + <key>init_state</key> <value>0</value> </param> - </block> - <block> - <key>blocks_short_to_float</key> - <param> - <key>id</key> - <value>blocks_short_to_float_3</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> - <param> - <key>scale</key> - <value>1</value> - </param> - <param> - <key>alias</key> - <value></value> - </param> <param> <key>affinity</key> <value></value> @@ -2801,12 +1971,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(1002, 1149)</value> + <value>(91, 1719)</value> </param> <param> <key>_rotation</key> @@ -2814,226 +1980,200 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>wxgui_numbersink2</key> <param> <key>id</key> - <value>qtgui_number_sink_0_0</value> + <value>wxgui_numbersink2_3_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> - </param> - <param> <key>type</key> <value>float</value> </param> <param> - <key>autoscale</key> - <value>False</value> - </param> - <param> - <key>avg</key> - <value>0.001</value> - </param> - <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> - </param> - <param> - <key>nconnections</key> - <value>1</value> - </param> - <param> - <key>min</key> - <value>-1</value> + <key>title</key> + <value>BER 1 (after cancelling user 2)</value> </param> <param> - <key>max</key> - <value>1</value> + <key>units</key> + <value>BER</value> </param> <param> - <key>update_time</key> - <value>0.10</value> + <key>samp_rate</key> + <value>R</value> </param> <param> - <key>gui_hint</key> - <value>0,1,1,1</value> + <key>min_value</key> + <value>0</value> </param> <param> - <key>label1</key> - <value>BER 2 (raw)</value> + <key>max_value</key> + <value>1.0</value> </param> <param> - <key>unit1</key> - <value></value> + <key>factor</key> + <value>1.0</value> </param> <param> - <key>color1</key> - <value>("black", "black")</value> + <key>decimal_places</key> + <value>6</value> </param> <param> - <key>factor1</key> - <value>1</value> + <key>ref_level</key> + <value>0</value> </param> <param> - <key>label2</key> - <value></value> + <key>number_rate</key> + <value>15</value> </param> <param> - <key>unit2</key> - <value></value> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>color2</key> - <value>("black", "black")</value> + <key>average</key> + <value>False</value> </param> <param> - <key>factor2</key> - <value>1</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>label3</key> - <value></value> + <key>show_gauge</key> + <value>True</value> </param> <param> - <key>unit3</key> + <key>win_size</key> <value></value> </param> <param> - <key>color3</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor3</key> - <value>1</value> + <key>grid_pos</key> + <value>1,0,1,1</value> </param> <param> - <key>label4</key> + <key>notebook</key> <value></value> </param> <param> - <key>unit4</key> + <key>affinity</key> <value></value> </param> <param> - <key>color4</key> - <value>("black", "black")</value> + <key>_coordinate</key> + <value>(929, 1816)</value> </param> <param> - <key>factor4</key> - <value>1</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable_slider</key> <param> - <key>label5</key> - <value></value> + <key>id</key> + <value>alpha</value> </param> <param> - <key>unit5</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>color5</key> - <value>("black", "black")</value> + <key>label</key> + <value>P1/P</value> </param> <param> - <key>factor5</key> - <value>1</value> + <key>value</key> + <value>0.1</value> </param> <param> - <key>label6</key> - <value></value> + <key>min</key> + <value>0</value> </param> <param> - <key>unit6</key> - <value></value> + <key>max</key> + <value>1.0</value> </param> <param> - <key>color6</key> - <value>("black", "black")</value> + <key>num_steps</key> + <value>100</value> </param> <param> - <key>factor6</key> - <value>1</value> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> </param> <param> - <key>label7</key> - <value></value> + <key>converver</key> + <value>float_converter</value> </param> <param> - <key>unit7</key> + <key>grid_pos</key> <value></value> </param> <param> - <key>color7</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor7</key> - <value>1</value> - </param> - <param> - <key>label8</key> + <key>notebook</key> <value></value> </param> <param> - <key>unit8</key> - <value></value> + <key>_coordinate</key> + <value>(243, 11)</value> </param> <param> - <key>color8</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable_slider</key> <param> - <key>factor8</key> - <value>1</value> + <key>id</key> + <value>snr_db</value> </param> <param> - <key>label9</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit9</key> - <value></value> + <key>label</key> + <value>P/sigma^2 (dB)</value> </param> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>value</key> + <value>10</value> </param> <param> - <key>factor9</key> - <value>1</value> + <key>min</key> + <value>0</value> </param> <param> - <key>label10</key> - <value></value> + <key>max</key> + <value>20</value> </param> <param> - <key>unit10</key> - <value></value> + <key>num_steps</key> + <value>100</value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> </param> <param> - <key>factor10</key> - <value>1</value> + <key>converver</key> + <value>float_converter</value> </param> <param> - <key>alias</key> + <key>grid_pos</key> <value></value> </param> <param> - <key>affinity</key> + <key>notebook</key> <value></value> </param> <param> <key>_coordinate</key> - <value>(1223, 1133)</value> + <value>(447, 14)</value> </param> <param> <key>_rotation</key> @@ -3041,10 +2181,10 @@ </param> </block> <block> - <key>trellis_encoder_xx</key> + <key>blks2_error_rate</key> <param> <key>id</key> - <value>trellis_encoder_xx_2_0</value> + <value>blks2_error_rate_0</value> </param> <param> <key>_enabled</key> @@ -3052,19 +2192,15 @@ </param> <param> <key>type</key> - <value>ss</value> + <value>'BER'</value> </param> <param> - <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> + <key>win_size</key> + <value>block*100</value> </param> <param> - <key>init_state</key> - <value>0</value> - </param> - <param> - <key>alias</key> - <value></value> + <key>bits_per_symbol</key> + <value>2</value> </param> <param> <key>affinity</key> @@ -3075,12 +2211,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(103, 1366)</value> + <value>(724, 613)</value> </param> <param> <key>_rotation</key> @@ -3088,10 +2220,10 @@ </param> </block> <block> - <key>trellis_encoder_xx</key> + <key>blks2_error_rate</key> <param> <key>id</key> - <value>trellis_encoder_xx_2</value> + <value>blks2_error_rate_0_0</value> </param> <param> <key>_enabled</key> @@ -3099,19 +2231,15 @@ </param> <param> <key>type</key> - <value>ss</value> + <value>'BER'</value> </param> <param> - <key>fsm_args</key> - <value>prefix+"/awgn1o2_16.fsm"</value> - </param> - <param> - <key>init_state</key> - <value>0</value> + <key>win_size</key> + <value>block*100</value> </param> <param> - <key>alias</key> - <value></value> + <key>bits_per_symbol</key> + <value>2</value> </param> <param> <key>affinity</key> @@ -3122,12 +2250,8 @@ <value>0</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(89, 1000)</value> + <value>(719, 943)</value> </param> <param> <key>_rotation</key> @@ -3135,226 +2259,77 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>blks2_error_rate</key> <param> <key>id</key> - <value>qtgui_number_sink_0_0_0</value> + <value>blks2_error_rate_0_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> - </param> - <param> <key>type</key> - <value>float</value> - </param> - <param> - <key>autoscale</key> - <value>False</value> - </param> - <param> - <key>avg</key> - <value>0.001</value> - </param> - <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> - </param> - <param> - <key>nconnections</key> - <value>1</value> - </param> - <param> - <key>min</key> - <value>-1</value> - </param> - <param> - <key>max</key> - <value>1</value> - </param> - <param> - <key>update_time</key> - <value>0.10</value> - </param> - <param> - <key>gui_hint</key> - <value>1,1,1,1</value> - </param> - <param> - <key>label1</key> - <value></value> - </param> - <param> - <key>unit1</key> - <value></value> - </param> - <param> - <key>color1</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor1</key> - <value>1</value> - </param> - <param> - <key>label2</key> - <value></value> - </param> - <param> - <key>unit2</key> - <value></value> - </param> - <param> - <key>color2</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor2</key> - <value>1</value> - </param> - <param> - <key>label3</key> - <value></value> - </param> - <param> - <key>unit3</key> - <value></value> - </param> - <param> - <key>color3</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor3</key> - <value>1</value> - </param> - <param> - <key>label4</key> - <value></value> - </param> - <param> - <key>unit4</key> - <value></value> - </param> - <param> - <key>color4</key> - <value>("black", "black")</value> + <value>'BER'</value> </param> <param> - <key>factor4</key> - <value>1</value> - </param> - <param> - <key>label5</key> - <value></value> - </param> - <param> - <key>unit5</key> - <value></value> - </param> - <param> - <key>color5</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor5</key> - <value>1</value> - </param> - <param> - <key>label6</key> - <value></value> - </param> - <param> - <key>unit6</key> - <value></value> - </param> - <param> - <key>color6</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor6</key> - <value>1</value> - </param> - <param> - <key>label7</key> - <value></value> - </param> - <param> - <key>unit7</key> - <value></value> - </param> - <param> - <key>color7</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor7</key> - <value>1</value> + <key>win_size</key> + <value>block*100</value> </param> <param> - <key>label8</key> - <value></value> + <key>bits_per_symbol</key> + <value>2</value> </param> <param> - <key>unit8</key> + <key>affinity</key> <value></value> </param> <param> - <key>color8</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor8</key> - <value>1</value> - </param> - <param> - <key>label9</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>unit9</key> - <value></value> + <key>_coordinate</key> + <value>(725, 1399)</value> </param> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blks2_error_rate</key> <param> - <key>factor9</key> - <value>1</value> + <key>id</key> + <value>blks2_error_rate_0_0_0_0</value> </param> <param> - <key>label10</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit10</key> - <value></value> + <key>type</key> + <value>'BER'</value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>win_size</key> + <value>block*100</value> </param> <param> - <key>factor10</key> - <value>1</value> + <key>bits_per_symbol</key> + <value>2</value> </param> <param> - <key>alias</key> + <key>affinity</key> <value></value> </param> <param> - <key>affinity</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(1266, 720)</value> + <value>(724, 1880)</value> </param> <param> <key>_rotation</key> @@ -3362,218 +2337,194 @@ </param> </block> <connection> - <source_block_id>analog_random_source_x_1</source_block_id> - <sink_block_id>trellis_encoder_xx_1</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> - </connection> - <connection> - <source_block_id>blocks_multiply_const_vxx_0</source_block_id> - <sink_block_id>blocks_add_xx_0</sink_block_id> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>wxgui_scopesink2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_const_vxx_1</source_block_id> - <sink_block_id>blocks_add_xx_0</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0_0</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_0</sink_block_id> + <source_block_id>virtual_source_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_0</sink_block_id> + <source_block_id>blks2_error_rate_0_0_0_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_0</source_block_id> - <sink_block_id>blocks_short_to_float_0</sink_block_id> + <source_block_id>virtual_source_0_2_0</source_block_id> + <sink_block_id>trellis_encoder_xx_2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>trellis_encoder_xx_0</sink_block_id> + <source_block_id>virtual_source_0_1_2</source_block_id> + <sink_block_id>blocks_sub_xx_2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>trellis_viterbi_combined_xx_1</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0_0_1</source_block_id> + <sink_block_id>blocks_multiply_const_vxx_2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>trellis_encoder_xx_2_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_viterbi_combined_xx_1</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>blocks_multiply_const_vxx_2_0</source_block_id> + <sink_block_id>blocks_sub_xx_2_0</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>trellis_viterbi_combined_xx_0</source_block_id> - <sink_block_id>blocks_sub_xx_1</sink_block_id> + <source_block_id>blocks_sub_xx_2_0</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_0_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_random_source_x_1</source_block_id> - <sink_block_id>blocks_sub_xx_1</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_1</source_block_id> - <sink_block_id>blocks_multiply_xx_2</sink_block_id> + <source_block_id>virtual_source_0_4</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_1</source_block_id> - <sink_block_id>blocks_multiply_xx_2</sink_block_id> + <source_block_id>blks2_error_rate_0_0_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_2</source_block_id> - <sink_block_id>trellis_viterbi_combined_xx_0</sink_block_id> + <source_block_id>virtual_source_0_2</source_block_id> + <sink_block_id>trellis_encoder_xx_2</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> + <source_block_id>virtual_source_0_1_1</source_block_id> <sink_block_id>blocks_sub_xx_2</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_const_vxx_2</source_block_id> - <sink_block_id>blocks_sub_xx_2</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0_0_0</source_block_id> + <sink_block_id>blocks_multiply_const_vxx_2</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_viterbi_combined_xx_1</source_block_id> - <sink_block_id>trellis_encoder_xx_2</sink_block_id> + <source_block_id>trellis_encoder_xx_2</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_viterbi_combined_xx_2</source_block_id> - <sink_block_id>blocks_sub_xx_3</sink_block_id> + <source_block_id>blocks_multiply_const_vxx_2</source_block_id> + <sink_block_id>blocks_sub_xx_2</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_3</source_block_id> - <sink_block_id>blocks_multiply_xx_1</sink_block_id> + <source_block_id>blocks_sub_xx_2</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_3</source_block_id> - <sink_block_id>blocks_multiply_xx_1</sink_block_id> - <source_key>0</source_key> - <sink_key>1</sink_key> - </connection> - <connection> - <source_block_id>analog_random_source_x_1</source_block_id> - <sink_block_id>blocks_sub_xx_3</sink_block_id> + <source_block_id>blks2_error_rate_0_0</source_block_id> + <sink_block_id>wxgui_numbersink2_2</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_viterbi_combined_xx_2</source_block_id> - <sink_block_id>trellis_encoder_xx_2_0</sink_block_id> + <source_block_id>virtual_source_0_3</source_block_id> + <sink_block_id>blks2_error_rate_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_viterbi_combined_xx_0_0</source_block_id> - <sink_block_id>blocks_sub_xx_1_0</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_2</source_block_id> + <sink_block_id>blks2_error_rate_0_0</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_1_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_2</source_block_id> + <sink_block_id>virtual_sink_0_2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_1_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> - <source_key>0</source_key> - <sink_key>1</sink_key> - </connection> - <connection> - <source_block_id>blocks_sub_xx_2_0</source_block_id> - <sink_block_id>trellis_viterbi_combined_xx_0_0</sink_block_id> + <source_block_id>virtual_source_0_1_0</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_2</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>blocks_sub_xx_2_0</sink_block_id> + <source_block_id>blks2_error_rate_0</source_block_id> + <sink_block_id>wxgui_numbersink2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_1_0</sink_block_id> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_const_vxx_2_0</source_block_id> - <sink_block_id>blocks_sub_xx_2_0</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_1</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>trellis_encoder_xx_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_1</source_block_id> + <sink_block_id>virtual_sink_0_2</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_noise_source_x_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> - <source_key>0</source_key> - <sink_key>1</sink_key> - </connection> - <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> + <source_block_id>virtual_source_0_1</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> - <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id> + <source_block_id>analog_random_source_x_1</source_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> - <sink_block_id>blocks_multiply_const_vxx_1</sink_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> @@ -3584,80 +2535,62 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_encoder_xx_2</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0_0_0</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> - </connection> - <connection> - <source_block_id>digital_chunks_to_symbols_xx_0_0_0</source_block_id> - <sink_block_id>blocks_multiply_const_vxx_2</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> - </connection> - <connection> - <source_block_id>trellis_encoder_xx_2_0</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0_0_1</sink_block_id> - <source_key>0</source_key> - <sink_key>0</sink_key> - </connection> - <connection> - <source_block_id>digital_chunks_to_symbols_xx_0_0_1</source_block_id> - <sink_block_id>blocks_multiply_const_vxx_2_0</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> + <sink_block_id>blocks_multiply_const_vxx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>qtgui_const_sink_x_0</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> + <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>trellis_viterbi_combined_xx_2</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_0</source_block_id> - <sink_block_id>qtgui_number_sink_0</sink_block_id> + <source_block_id>trellis_encoder_xx_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_2_0</source_block_id> - <sink_block_id>blocks_short_to_float_1</sink_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>trellis_encoder_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_1</source_block_id> - <sink_block_id>qtgui_number_sink_0_0_0_0</sink_block_id> + <source_block_id>analog_random_source_x_1</source_block_id> + <sink_block_id>trellis_encoder_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_1</source_block_id> - <sink_block_id>blocks_short_to_float_2</sink_block_id> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_2</source_block_id> - <sink_block_id>qtgui_number_sink_0_0_0</sink_block_id> + <source_block_id>blocks_multiply_const_vxx_1</source_block_id> + <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_2</source_block_id> - <sink_block_id>blocks_short_to_float_3</sink_block_id> + <source_block_id>blocks_add_xx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_3</source_block_id> - <sink_block_id>qtgui_number_sink_0_0</sink_block_id> + <source_block_id>blocks_multiply_const_vxx_0</source_block_id> + <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-trellis/examples/grc/pccc.grc b/gr-trellis/examples/grc/pccc.grc index c642a71940..e10c70a614 100644 --- a/gr-trellis/examples/grc/pccc.grc +++ b/gr-trellis/examples/grc/pccc.grc @@ -1,6 +1,7 @@ <?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> <flow_graph> - <timestamp>Mon Jul 28 14:02:43 2014</timestamp> + <timestamp>Fri Sep 26 12:26:16 2014</timestamp> <block> <key>options</key> <param> @@ -29,7 +30,7 @@ </param> <param> <key>generate_options</key> - <value>qt_gui</value> + <value>wx_gui</value> </param> <param> <key>category</key> @@ -84,7 +85,7 @@ </param> <param> <key>_coordinate</key> - <value>(520, 11)</value> + <value>(320, 21)</value> </param> <param> <key>_rotation</key> @@ -95,7 +96,7 @@ <key>variable</key> <param> <key>id</key> - <value>noisevar</value> + <value>R</value> </param> <param> <key>_enabled</key> @@ -103,7 +104,7 @@ </param> <param> <key>value</key> - <value>10**(-snr_db/10)</value> + <value>100e3</value> </param> <param> <key>alias</key> @@ -111,7 +112,7 @@ </param> <param> <key>_coordinate</key> - <value>(279, 10)</value> + <value>(200, 101)</value> </param> <param> <key>_rotation</key> @@ -122,7 +123,7 @@ <key>variable</key> <param> <key>id</key> - <value>R</value> + <value>block</value> </param> <param> <key>_enabled</key> @@ -130,7 +131,7 @@ </param> <param> <key>value</key> - <value>100e3</value> + <value>1000</value> </param> <param> <key>alias</key> @@ -138,7 +139,7 @@ </param> <param> <key>_coordinate</key> - <value>(358, 10)</value> + <value>(200, 37)</value> </param> <param> <key>_rotation</key> @@ -149,7 +150,7 @@ <key>variable</key> <param> <key>id</key> - <value>block</value> + <value>dim</value> </param> <param> <key>_enabled</key> @@ -157,7 +158,7 @@ </param> <param> <key>value</key> - <value>1000</value> + <value>mod[0]</value> </param> <param> <key>alias</key> @@ -165,7 +166,7 @@ </param> <param> <key>_coordinate</key> - <value>(438, 10)</value> + <value>(688, 317)</value> </param> <param> <key>_rotation</key> @@ -173,54 +174,53 @@ </param> </block> <block> - <key>analog_random_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_random_source_x_0</value> + <value>constellation</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>min</key> - <value>0</value> + <key>value</key> + <value>mod[1]</value> </param> <param> - <key>max</key> - <value>2</value> + <key>alias</key> + <value></value> </param> <param> - <key>num_samps</key> - <value>1000</value> + <key>_coordinate</key> + <value>(528, 317)</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>alias</key> - <value></value> + <key>id</key> + <value>dim</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_enabled</key> + <value>False</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>value</key> + <value>2</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(21, 170)</value> + <value>(688, 189)</value> </param> <param> <key>_rotation</key> @@ -228,50 +228,53 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>variable</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>constellation</value> </param> <param> <key>_enabled</key> - <value>True</value> + <value>False</value> </param> <param> - <key>type</key> - <value>short</value> + <key>value</key> + <value>-3,-3,-1,-3,1,-3,3,-3, -3,-1,-1,-1,1,-1,3,-1, -3,1,-1,1,1,1,3,1, -3,3,-1,3,1,3,3,3 </value> </param> <param> - <key>samples_per_second</key> - <value>R</value> + <key>alias</key> + <value></value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>_coordinate</key> + <value>(528, 189)</value> </param> <param> - <key>ignoretag</key> - <value>True</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>alias</key> - <value></value> + <key>id</key> + <value>Es</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>value</key> + <value>sum(numpy.square(constellation))/(len(constellation)/(1.0*dim))</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(559, 104)</value> + <value>(776, 141)</value> </param> <param> <key>_rotation</key> @@ -279,50 +282,45 @@ </param> </block> <block> - <key>variable_qtgui_range</key> + <key>variable</key> <param> <key>id</key> - <value>snr_db</value> + <value>noisevar</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>SNR (dB)</value> - </param> - <param> <key>value</key> - <value>5</value> - </param> - <param> - <key>start</key> - <value>-10</value> + <value>10**(-EsN0_dB/10.0) * Es /2.0</value> </param> <param> - <key>stop</key> - <value>10</value> + <key>alias</key> + <value></value> </param> <param> - <key>step</key> - <value>0.01</value> + <key>_coordinate</key> + <value>(1032, 149)</value> </param> <param> - <key>widget</key> - <value>counter_slider</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>orient</key> - <value>Qt.Horizontal</value> + <key>id</key> + <value>interleaver</value> </param> <param> - <key>min_len</key> - <value>200</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gui_hint</key> - <value></value> + <key>value</key> + <value>trellis.interleaver(block,666)</value> </param> <param> <key>alias</key> @@ -330,62 +328,61 @@ </param> <param> <key>_coordinate</key> - <value>(177, 10)</value> + <value>(320, 213)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> - <key>digital_chunks_to_symbols_xx</key> + <key>variable</key> <param> <key>id</key> - <value>digital_chunks_to_symbols_xx_0</value> + <value>fsm1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>in_type</key> - <value>short</value> - </param> - <param> - <key>out_type</key> - <value>complex</value> + <key>value</key> + <value>trellis.fsm(prefix+"awgn1o2_4rsc.fsm")</value> </param> <param> - <key>symbol_table</key> - <value>-7,0, -5,0, -3,0, -1,0, 1,0, 3,0, 5,0, 7,0, 0,-7,0, -5,0, -3,0, -1,0, 1,0, 3,0, 5,0, 7,0</value> + <key>alias</key> + <value></value> </param> <param> - <key>dimension</key> - <value>2</value> + <key>_coordinate</key> + <value>(320, 85)</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>alias</key> - <value></value> + <key>id</key> + <value>fsm2</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>value</key> + <value>trellis.fsm(prefix+"awgn1o1_4rsc.fsm")</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(559, 180)</value> + <value>(320, 149)</value> </param> <param> <key>_rotation</key> @@ -393,62 +390,72 @@ </param> </block> <block> - <key>trellis_pccc_encoder_xx</key> + <key>variable</key> <param> <key>id</key> - <value>trellis_pccc_encoder_xx_0</value> + <value>mod</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>ss</value> + <key>value</key> + <value>fu.psk2x3</value> </param> <param> - <key>o_fsm_args</key> - <value>prefix + "/awgn1o2_4.fsm"</value> + <key>alias</key> + <value></value> </param> <param> - <key>o_init_state</key> + <key>_coordinate</key> + <value>(576, 253)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>i_fsm_args</key> - <value>prefix + "/awgn1o2_4.fsm"</value> + <key>id</key> + <value>virtual_source_0_0</value> </param> <param> - <key>i_init_state</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>interleaver_args</key> - <value>trellis.interleaver(block,666)</value> + <key>stream_id</key> + <value>info</value> </param> <param> - <key>bl</key> - <value>block</value> + <key>_coordinate</key> + <value>(104, 1220)</value> </param> <param> - <key>alias</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>affinity</key> - <value></value> + <key>id</key> + <value>virtual_source_0_0_0</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>estimate</value> </param> <param> <key>_coordinate</key> - <value>(234, 154)</value> + <value>(88, 1292)</value> </param> <param> <key>_rotation</key> @@ -456,10 +463,10 @@ </param> </block> <block> - <key>trellis_pccc_decoder_combined_xx</key> + <key>wxgui_numbersink2</key> <param> <key>id</key> - <value>trellis_pccc_decoder_combined_xx_0</value> + <value>wxgui_numbersink2_3_0_0</value> </param> <param> <key>_enabled</key> @@ -467,67 +474,71 @@ </param> <param> <key>type</key> - <value>c</value> + <value>float</value> </param> <param> - <key>out_type</key> - <value>s</value> + <key>title</key> + <value>BER</value> </param> <param> - <key>o_fsm_args</key> - <value>prefix + "/awgn1o2_4.fsm"</value> + <key>units</key> + <value>BER</value> </param> <param> - <key>o_init_state</key> + <key>samp_rate</key> + <value>R</value> + </param> + <param> + <key>min_value</key> <value>0</value> </param> <param> - <key>o_final_state</key> - <value>-1</value> + <key>max_value</key> + <value>1.0</value> </param> <param> - <key>i_fsm_args</key> - <value>prefix + "/awgn1o2_4.fsm"</value> + <key>factor</key> + <value>1.0</value> </param> <param> - <key>i_init_state</key> - <value>0</value> + <key>decimal_places</key> + <value>6</value> </param> <param> - <key>i_final_state</key> - <value>-1</value> + <key>ref_level</key> + <value>0</value> </param> <param> - <key>interleaver</key> - <value>trellis.interleaver(block,666)</value> + <key>number_rate</key> + <value>15</value> </param> <param> - <key>block_size</key> - <value>block</value> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>iterations</key> - <value>10</value> + <key>average</key> + <value>False</value> </param> <param> - <key>dim</key> - <value>2</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>table</key> - <value>-7,0, -5,0, -3,0, -1,0, 1,0, 3,0, 5,0, 7,0, 0,-7,0, -5,0, -3,0, -1,0, 1,0, 3,0, 5,0, 7,0</value> + <key>show_gauge</key> + <value>False</value> </param> <param> - <key>metric_type</key> - <value>digital.TRELLIS_EUCLIDEAN</value> + <key>win_size</key> + <value></value> </param> <param> - <key>siso_type</key> - <value>trellis.TRELLIS_MIN_SUM</value> + <key>grid_pos</key> + <value></value> </param> <param> - <key>scaling</key> - <value>1.0</value> + <key>notebook</key> + <value></value> </param> <param> <key>alias</key> @@ -538,27 +549,19 @@ <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> - </param> - <param> - <key>maxoutbuf</key> - <value>0</value> - </param> - <param> <key>_coordinate</key> - <value>(234, 299)</value> + <value>(680, 1205)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>blks2_error_rate</key> <param> <key>id</key> - <value>blocks_multiply_xx_2_0</value> + <value>blks2_error_rate_0</value> </param> <param> <key>_enabled</key> @@ -566,14 +569,14 @@ </param> <param> <key>type</key> - <value>short</value> + <value>'SER'</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>win_size</key> + <value>block*100</value> </param> <param> - <key>vlen</key> + <key>bits_per_symbol</key> <value>1</value> </param> <param> @@ -594,7 +597,7 @@ </param> <param> <key>_coordinate</key> - <value>(421, 574)</value> + <value>(304, 1256)</value> </param> <param> <key>_rotation</key> @@ -602,46 +605,68 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>blocks_sub_xx_0</value> + <value>virtual_sink_0_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>stream_id</key> + <value>estimate</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>_coordinate</key> + <value>(768, 940)</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>alias</key> - <value></value> + <key>id</key> + <value>virtual_source_0</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>stream_id</key> + <value>observation</value> </param> <param> - <key>maxoutbuf</key> + <key>_coordinate</key> + <value>(104, 940)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> <param> <key>_coordinate</key> - <value>(246, 580)</value> + <value>(224, 412)</value> </param> <param> <key>_rotation</key> @@ -649,22 +674,30 @@ </param> </block> <block> - <key>blocks_short_to_float</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>blocks_short_to_float_1_0</value> + <value>blocks_throttle_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>samples_per_second</key> + <value>R</value> + </param> + <param> <key>vlen</key> <value>1</value> </param> <param> - <key>scale</key> - <value>1</value> + <key>ignoretag</key> + <value>True</value> </param> <param> <key>alias</key> @@ -684,7 +717,7 @@ </param> <param> <key>_coordinate</key> - <value>(564, 592)</value> + <value>(208, 492)</value> </param> <param> <key>_rotation</key> @@ -703,7 +736,7 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>float</value> </param> <param> <key>noise_type</key> @@ -711,7 +744,7 @@ </param> <param> <key>amp</key> - <value>noisevar</value> + <value>noisevar**0.5</value> </param> <param> <key>seed</key> @@ -735,7 +768,7 @@ </param> <param> <key>_coordinate</key> - <value>(520, 309)</value> + <value>(656, 646)</value> </param> <param> <key>_rotation</key> @@ -754,7 +787,7 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>float</value> </param> <param> <key>num_inputs</key> @@ -782,7 +815,7 @@ </param> <param> <key>_coordinate</key> - <value>(816, 192)</value> + <value>(880, 552)</value> </param> <param> <key>_rotation</key> @@ -790,214 +823,360 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>qtgui_number_sink_0</value> + <value>virtual_sink_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> + <key>stream_id</key> + <value>observation</value> </param> <param> - <key>type</key> - <value>float</value> + <key>_coordinate</key> + <value>(896, 676)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0_0</value> </param> <param> - <key>autoscale</key> + <key>_enabled</key> <value>True</value> </param> <param> - <key>avg</key> - <value>0.001</value> + <key>import</key> + <value>import gnuradio.trellis.fsm_utils as fu</value> </param> <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> + <key>alias</key> + <value></value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>_coordinate</key> + <value>(48, 132)</value> </param> <param> - <key>min</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>trellis_pccc_encoder_xx</key> <param> - <key>max</key> - <value>1</value> + <key>id</key> + <value>trellis_pccc_encoder_xx_0</value> </param> <param> - <key>update_time</key> - <value>0.01</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gui_hint</key> - <value></value> + <key>type</key> + <value>bb</value> </param> <param> - <key>label1</key> - <value></value> + <key>o_fsm_args</key> + <value>fsm1</value> </param> <param> - <key>unit1</key> - <value></value> + <key>o_init_state</key> + <value>0</value> </param> <param> - <key>color1</key> - <value>("black", "black")</value> + <key>i_fsm_args</key> + <value>fsm2</value> </param> <param> - <key>factor1</key> - <value>1</value> + <key>i_init_state</key> + <value>0</value> + </param> + <param> + <key>interleaver_args</key> + <value>interleaver</value> </param> <param> - <key>label2</key> + <key>bl</key> + <value>block</value> + </param> + <param> + <key>alias</key> <value></value> </param> <param> - <key>unit2</key> + <key>affinity</key> <value></value> </param> <param> - <key>color2</key> - <value>("black", "black")</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>factor2</key> - <value>1</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>label3</key> - <value></value> + <key>_coordinate</key> + <value>(400, 457)</value> </param> <param> - <key>unit3</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> <param> - <key>color3</key> - <value>("black", "black")</value> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0</value> </param> <param> - <key>factor3</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>label4</key> - <value></value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>unit4</key> - <value></value> + <key>out_type</key> + <value>float</value> + </param> + <param> + <key>symbol_table</key> + <value>constellation</value> </param> <param> - <key>color4</key> - <value>("black", "black")</value> + <key>dimension</key> + <value>dim</value> </param> <param> - <key>factor4</key> + <key>num_ports</key> <value>1</value> </param> <param> - <key>label5</key> + <key>alias</key> <value></value> </param> <param> - <key>unit5</key> + <key>affinity</key> <value></value> </param> <param> - <key>color5</key> - <value>("black", "black")</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>factor5</key> - <value>1</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>label6</key> - <value></value> + <key>_coordinate</key> + <value>(632, 485)</value> </param> <param> - <key>unit6</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>analog_random_source_x</key> <param> - <key>color6</key> - <value>("black", "black")</value> + <key>id</key> + <value>analog_random_source_x_0_0</value> </param> <param> - <key>factor6</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>label7</key> - <value></value> + <key>type</key> + <value>byte</value> </param> <param> - <key>unit7</key> - <value></value> + <key>min</key> + <value>0</value> </param> <param> - <key>color7</key> - <value>("black", "black")</value> + <key>max</key> + <value>2</value> </param> <param> - <key>factor7</key> - <value>1</value> + <key>num_samps</key> + <value>block</value> + </param> + <param> + <key>repeat</key> + <value>True</value> </param> <param> - <key>label8</key> + <key>alias</key> <value></value> </param> <param> - <key>unit8</key> + <key>affinity</key> <value></value> </param> <param> - <key>color8</key> - <value>("black", "black")</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>factor8</key> - <value>1</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>label9</key> - <value></value> + <key>_coordinate</key> + <value>(8, 471)</value> </param> <param> - <key>unit9</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable_slider</key> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>id</key> + <value>EsN0_dB</value> </param> <param> - <key>factor9</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>EsN0 (dB)</value> + </param> + <param> + <key>value</key> + <value>2</value> + </param> + <param> + <key>min</key> + <value>-10</value> + </param> + <param> + <key>max</key> + <value>20</value> + </param> + <param> + <key>num_steps</key> + <value>1000</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> </param> <param> - <key>label10</key> + <key>grid_pos</key> <value></value> </param> <param> - <key>unit10</key> + <key>notebook</key> <value></value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>alias</key> + <value></value> </param> <param> - <key>factor10</key> - <value>1</value> + <key>_coordinate</key> + <value>(896, 129)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_pccc_decoder_combined_xx</key> + <param> + <key>id</key> + <value>trellis_pccc_decoder_combined_xx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>f</value> + </param> + <param> + <key>out_type</key> + <value>b</value> + </param> + <param> + <key>o_fsm_args</key> + <value>fsm1</value> + </param> + <param> + <key>o_init_state</key> + <value>0</value> + </param> + <param> + <key>o_final_state</key> + <value>-1</value> + </param> + <param> + <key>i_fsm_args</key> + <value>fsm2</value> + </param> + <param> + <key>i_init_state</key> + <value>0</value> + </param> + <param> + <key>i_final_state</key> + <value>-1</value> + </param> + <param> + <key>interleaver</key> + <value>interleaver</value> + </param> + <param> + <key>block_size</key> + <value>block</value> + </param> + <param> + <key>iterations</key> + <value>10</value> + </param> + <param> + <key>dim</key> + <value>dim</value> + </param> + <param> + <key>table</key> + <value>constellation</value> + </param> + <param> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> + </param> + <param> + <key>siso_type</key> + <value>trellis.TRELLIS_MIN_SUM</value> + </param> + <param> + <key>scaling</key> + <value>0.5/noisevar</value> </param> <param> <key>alias</key> @@ -1008,8 +1187,16 @@ <value></value> </param> <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(571, 477)</value> + <value>(400, 849)</value> </param> <param> <key>_rotation</key> @@ -1017,75 +1204,75 @@ </param> </block> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>trellis_pccc_encoder_xx_0</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>trellis_pccc_decoder_combined_xx_0</sink_block_id> + <source_block_id>blks2_error_rate_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_noise_source_x_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>virtual_source_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>virtual_source_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_pccc_encoder_xx_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>trellis_pccc_decoder_combined_xx_0</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_pccc_decoder_combined_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_1_0</source_block_id> - <sink_block_id>qtgui_number_sink_0</sink_block_id> + <source_block_id>trellis_pccc_encoder_xx_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_pccc_decoder_combined_xx_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>blocks_throttle_0_0</source_block_id> + <sink_block_id>trellis_pccc_encoder_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>analog_random_source_x_0_0</source_block_id> + <sink_block_id>blocks_throttle_0_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>analog_random_source_x_0_0</source_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_2_0</source_block_id> - <sink_block_id>blocks_short_to_float_1_0</sink_block_id> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> </flow_graph> diff --git a/gr-trellis/examples/grc/readme.txt b/gr-trellis/examples/grc/readme.txt index a5261ac0b2..3d32e046dd 100644 --- a/gr-trellis/examples/grc/readme.txt +++ b/gr-trellis/examples/grc/readme.txt @@ -1,6 +1,6 @@ These are examples of using gr-trellis in grc. -INTERFERENCE CANCELLATION +Interference Cancellation ------------------------- Two users are transmitting simultaneously using convolutionally encoded QPSK, each with power P1=alpha*P and P2=(1-alpha)*P. The combined signal is observed in noise and four different receivers are considered: @@ -20,13 +20,13 @@ Serially Concatenated Convolutional Codes ----------------------------------------- An SCCC can be defined by an outer and an inner FSM together with an interleaver and a modulation type. You can change the SNR and observe the estimated BER. -In sccc.grc the decoding and metric calculation are combined; in sccc1.grc they are separate. Parallel Concatenated Convolutional Codes ----------------------------------------- A PCCC can be defined by two FSMs together with an interleaver and a modulation type. You can change the SNR and observe the estimated BER. -In pccc1.grc the decoding and metric calculation are separate. + +...and a few other examples including turbo equalization, etc Enjoy. diff --git a/gr-trellis/examples/grc/sccc.grc b/gr-trellis/examples/grc/sccc.grc index 9d516743b6..f31f3ce86d 100644 --- a/gr-trellis/examples/grc/sccc.grc +++ b/gr-trellis/examples/grc/sccc.grc @@ -1,6 +1,7 @@ <?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> <flow_graph> - <timestamp>Mon Jul 28 14:09:50 2014</timestamp> + <timestamp>Wed Oct 1 11:04:18 2014</timestamp> <block> <key>options</key> <param> @@ -29,7 +30,7 @@ </param> <param> <key>generate_options</key> - <value>qt_gui</value> + <value>wx_gui</value> </param> <param> <key>category</key> @@ -84,7 +85,7 @@ </param> <param> <key>_coordinate</key> - <value>(514, 10)</value> + <value>(344, 13)</value> </param> <param> <key>_rotation</key> @@ -95,7 +96,7 @@ <key>variable</key> <param> <key>id</key> - <value>block</value> + <value>mod</value> </param> <param> <key>_enabled</key> @@ -103,7 +104,7 @@ </param> <param> <key>value</key> - <value>1000</value> + <value>fu.psk2x3</value> </param> <param> <key>alias</key> @@ -111,7 +112,7 @@ </param> <param> <key>_coordinate</key> - <value>(441, 10)</value> + <value>(632, 101)</value> </param> <param> <key>_rotation</key> @@ -122,7 +123,7 @@ <key>variable</key> <param> <key>id</key> - <value>R</value> + <value>interleaver</value> </param> <param> <key>_enabled</key> @@ -130,7 +131,7 @@ </param> <param> <key>value</key> - <value>100e3</value> + <value>trellis.interleaver(block,666)</value> </param> <param> <key>alias</key> @@ -138,7 +139,7 @@ </param> <param> <key>_coordinate</key> - <value>(358, 10)</value> + <value>(344, 205)</value> </param> <param> <key>_rotation</key> @@ -149,7 +150,7 @@ <key>variable</key> <param> <key>id</key> - <value>noisevar</value> + <value>Es</value> </param> <param> <key>_enabled</key> @@ -157,7 +158,7 @@ </param> <param> <key>value</key> - <value>10**(-snr_db/10)</value> + <value>sum(numpy.square(constellation))/(len(constellation)/(1.0*dim))</value> </param> <param> <key>alias</key> @@ -165,7 +166,7 @@ </param> <param> <key>_coordinate</key> - <value>(279, 10)</value> + <value>(800, 133)</value> </param> <param> <key>_rotation</key> @@ -173,54 +174,80 @@ </param> </block> <block> - <key>analog_random_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_random_source_x_0</value> + <value>noisevar</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>value</key> + <value>10**(-EsN0_dB/10.0) * Es /2.0</value> </param> <param> - <key>min</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> - <key>max</key> - <value>2</value> + <key>_coordinate</key> + <value>(1056, 141)</value> </param> <param> - <key>num_samps</key> - <value>1000</value> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>block</value> </param> <param> - <key>repeat</key> + <key>_enabled</key> <value>True</value> </param> <param> + <key>value</key> + <value>1000</value> + </param> + <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> - <value></value> + <key>_coordinate</key> + <value>(224, 29)</value> </param> <param> - <key>minoutbuf</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>id</key> + <value>fsm_o</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>trellis.fsm(prefix+"awgn1o2_4.fsm")</value> + </param> + <param> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(21, 170)</value> + <value>(344, 77)</value> </param> <param> <key>_rotation</key> @@ -228,46 +255,80 @@ </param> </block> <block> - <key>blocks_add_xx</key> + <key>variable</key> <param> <key>id</key> - <value>blocks_add_xx_1</value> + <value>fsm_i</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> + <key>value</key> + <value>trellis.fsm(prefix+"/awgn2o3_4.fsm")</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>alias</key> + <value></value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>_coordinate</key> + <value>(344, 141)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>constellation</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>mod[1]</value> </param> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> - <value></value> + <key>_coordinate</key> + <value>(568, 173)</value> </param> <param> - <key>minoutbuf</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>id</key> + <value>dim</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>mod[0]</value> + </param> + <param> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(951, 256)</value> + <value>(720, 173)</value> </param> <param> <key>_rotation</key> @@ -275,50 +336,76 @@ </param> </block> <block> - <key>analog_noise_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_noise_source_x_0</value> + <value>R</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> + <key>value</key> + <value>100e3</value> </param> <param> - <key>noise_type</key> - <value>analog.GR_GAUSSIAN</value> + <key>alias</key> + <value></value> </param> <param> - <key>amp</key> - <value>noisevar</value> + <key>_coordinate</key> + <value>(224, 93)</value> </param> <param> - <key>seed</key> - <value>-42</value> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import numpy</value> </param> <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> - <value></value> + <key>_coordinate</key> + <value>(32, 148)</value> </param> <param> - <key>minoutbuf</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>id</key> + <value>virtual_sink_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> </param> <param> <key>_coordinate</key> - <value>(549, 250)</value> + <value>(192, 332)</value> </param> <param> <key>_rotation</key> @@ -326,10 +413,10 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>analog_random_source_x</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>analog_random_source_x_0</value> </param> <param> <key>_enabled</key> @@ -337,18 +424,22 @@ </param> <param> <key>type</key> - <value>short</value> + <value>byte</value> </param> <param> - <key>samples_per_second</key> - <value>R</value> + <key>min</key> + <value>0</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>max</key> + <value>2</value> </param> <param> - <key>ignoretag</key> + <key>num_samps</key> + <value>1007</value> + </param> + <param> + <key>repeat</key> <value>True</value> </param> <param> @@ -369,7 +460,7 @@ </param> <param> <key>_coordinate</key> - <value>(551, 116)</value> + <value>(5, 384)</value> </param> <param> <key>_rotation</key> @@ -377,10 +468,10 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>blocks_sub_xx_0</value> + <value>blocks_throttle_0</value> </param> <param> <key>_enabled</key> @@ -388,15 +479,19 @@ </param> <param> <key>type</key> - <value>short</value> + <value>byte</value> + </param> + <param> + <key>samples_per_second</key> + <value>R</value> </param> <param> <key>vlen</key> <value>1</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>ignoretag</key> + <value>True</value> </param> <param> <key>alias</key> @@ -416,7 +511,7 @@ </param> <param> <key>_coordinate</key> - <value>(239, 548)</value> + <value>(232, 404)</value> </param> <param> <key>_rotation</key> @@ -424,25 +519,33 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>digital_chunks_to_symbols_xx</key> <param> <key>id</key> - <value>blocks_multiply_xx_2_0</value> + <value>digital_chunks_to_symbols_xx_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>out_type</key> + <value>float</value> </param> <param> - <key>vlen</key> + <key>symbol_table</key> + <value>constellation</value> + </param> + <param> + <key>dimension</key> + <value>dim</value> + </param> + <param> + <key>num_ports</key> <value>1</value> </param> <param> @@ -463,7 +566,7 @@ </param> <param> <key>_coordinate</key> - <value>(418, 551)</value> + <value>(672, 397)</value> </param> <param> <key>_rotation</key> @@ -471,21 +574,25 @@ </param> </block> <block> - <key>blocks_short_to_float</key> + <key>blocks_add_xx</key> <param> <key>id</key> - <value>blocks_short_to_float_1_0</value> + <value>blocks_add_xx_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>type</key> + <value>float</value> + </param> + <param> + <key>num_inputs</key> + <value>2</value> </param> <param> - <key>scale</key> + <key>vlen</key> <value>1</value> </param> <param> @@ -506,7 +613,7 @@ </param> <param> <key>_coordinate</key> - <value>(605, 564)</value> + <value>(960, 472)</value> </param> <param> <key>_rotation</key> @@ -514,33 +621,25 @@ </param> </block> <block> - <key>digital_chunks_to_symbols_xx</key> + <key>blks2_error_rate</key> <param> <key>id</key> - <value>digital_chunks_to_symbols_xx_0</value> + <value>blks2_error_rate_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>in_type</key> - <value>short</value> - </param> - <param> - <key>out_type</key> - <value>complex</value> - </param> - <param> - <key>symbol_table</key> - <value>1,0,1j,0,-1j,0,-1,0,1,0,1j,0,-1j,0,-1,0</value> + <key>type</key> + <value>'SER'</value> </param> <param> - <key>dimension</key> - <value>2</value> + <key>win_size</key> + <value>block*100</value> </param> <param> - <key>num_ports</key> + <key>bits_per_symbol</key> <value>1</value> </param> <param> @@ -561,7 +660,7 @@ </param> <param> <key>_coordinate</key> - <value>(551, 181)</value> + <value>(312, 1168)</value> </param> <param> <key>_rotation</key> @@ -569,226 +668,260 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>virtual_source</key> <param> <key>id</key> - <value>qtgui_number_sink_0</value> + <value>virtual_source_0_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> + <key>stream_id</key> + <value>estimate</value> </param> <param> - <key>type</key> - <value>float</value> + <key>_coordinate</key> + <value>(96, 1204)</value> </param> <param> - <key>autoscale</key> - <value>False</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>avg</key> - <value>0.001</value> + <key>id</key> + <value>virtual_source_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> + <key>stream_id</key> + <value>info</value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>_coordinate</key> + <value>(112, 1132)</value> </param> <param> - <key>min</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>wxgui_numbersink2</key> <param> - <key>max</key> - <value>1</value> + <key>id</key> + <value>wxgui_numbersink2_3_0_0</value> </param> <param> - <key>update_time</key> - <value>0.10</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gui_hint</key> - <value>1,0,1,1</value> + <key>type</key> + <value>float</value> </param> <param> - <key>label1</key> - <value></value> + <key>title</key> + <value>BER</value> </param> <param> - <key>unit1</key> - <value></value> + <key>units</key> + <value>BER</value> </param> <param> - <key>color1</key> - <value>("black", "black")</value> + <key>samp_rate</key> + <value>R</value> </param> <param> - <key>factor1</key> - <value>1</value> + <key>min_value</key> + <value>0</value> </param> <param> - <key>label2</key> - <value></value> + <key>max_value</key> + <value>1.0</value> </param> <param> - <key>unit2</key> - <value></value> + <key>factor</key> + <value>1.0</value> </param> <param> - <key>color2</key> - <value>("black", "black")</value> + <key>decimal_places</key> + <value>6</value> </param> <param> - <key>factor2</key> - <value>1</value> + <key>ref_level</key> + <value>0</value> </param> <param> - <key>label3</key> - <value></value> + <key>number_rate</key> + <value>15</value> </param> <param> - <key>unit3</key> - <value></value> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>color3</key> - <value>("black", "black")</value> + <key>average</key> + <value>False</value> </param> <param> - <key>factor3</key> - <value>1</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>label4</key> - <value></value> + <key>show_gauge</key> + <value>False</value> </param> <param> - <key>unit4</key> + <key>win_size</key> <value></value> </param> <param> - <key>color4</key> - <value>("black", "black")</value> + <key>grid_pos</key> + <value></value> </param> <param> - <key>factor4</key> - <value>1</value> + <key>notebook</key> + <value></value> </param> <param> - <key>label5</key> + <key>alias</key> <value></value> </param> <param> - <key>unit5</key> + <key>affinity</key> <value></value> </param> <param> - <key>color5</key> - <value>("black", "black")</value> + <key>_coordinate</key> + <value>(688, 1117)</value> </param> <param> - <key>factor5</key> - <value>1</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>label6</key> - <value></value> + <key>id</key> + <value>virtual_source_0</value> </param> <param> - <key>unit6</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>color6</key> - <value>("black", "black")</value> + <key>stream_id</key> + <value>observation</value> </param> <param> - <key>factor6</key> - <value>1</value> + <key>_coordinate</key> + <value>(88, 836)</value> </param> <param> - <key>label7</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>unit7</key> - <value></value> + <key>id</key> + <value>virtual_sink_0_1</value> </param> <param> - <key>color7</key> - <value>("black", "black")</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>factor7</key> - <value>1</value> + <key>stream_id</key> + <value>estimate</value> </param> <param> - <key>label8</key> - <value></value> + <key>_coordinate</key> + <value>(744, 836)</value> </param> <param> - <key>unit8</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>analog_noise_source_x</key> <param> - <key>color8</key> - <value>("black", "black")</value> + <key>id</key> + <value>analog_noise_source_x_0</value> </param> <param> - <key>factor8</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>label9</key> - <value></value> + <key>type</key> + <value>float</value> </param> <param> - <key>unit9</key> - <value></value> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> </param> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>amp</key> + <value>noisevar**0.5</value> </param> <param> - <key>factor9</key> - <value>1</value> + <key>seed</key> + <value>-42</value> </param> <param> - <key>label10</key> + <key>alias</key> <value></value> </param> <param> - <key>unit10</key> + <key>affinity</key> <value></value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>factor10</key> - <value>1</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>alias</key> - <value></value> + <key>_coordinate</key> + <value>(608, 510)</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> </param> <param> <key>_coordinate</key> - <value>(788, 548)</value> + <value>(1064, 484)</value> </param> <param> <key>_rotation</key> @@ -796,10 +929,10 @@ </param> </block> <block> - <key>variable_qtgui_range</key> + <key>variable_slider</key> <param> <key>id</key> - <value>snr_db</value> + <value>EsN0_dB</value> </param> <param> <key>_enabled</key> @@ -807,38 +940,38 @@ </param> <param> <key>label</key> - <value>SNR (dB)</value> + <value>EsN0 (dB)</value> </param> <param> <key>value</key> - <value>5</value> + <value>2</value> </param> <param> - <key>start</key> + <key>min</key> <value>-10</value> </param> <param> - <key>stop</key> + <key>max</key> <value>10</value> </param> <param> - <key>step</key> - <value>0.01</value> + <key>num_steps</key> + <value>1000</value> </param> <param> - <key>widget</key> - <value>counter_slider</value> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> </param> <param> - <key>orient</key> - <value>Qt.Horizontal</value> + <key>converver</key> + <value>float_converter</value> </param> <param> - <key>min_len</key> - <value>200</value> + <key>grid_pos</key> + <value></value> </param> <param> - <key>gui_hint</key> + <key>notebook</key> <value></value> </param> <param> @@ -847,11 +980,11 @@ </param> <param> <key>_coordinate</key> - <value>(177, 10)</value> + <value>(920, 113)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> @@ -866,11 +999,11 @@ </param> <param> <key>type</key> - <value>ss</value> + <value>bb</value> </param> <param> <key>o_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> + <value>fsm_o</value> </param> <param> <key>o_init_state</key> @@ -878,7 +1011,7 @@ </param> <param> <key>i_fsm_args</key> - <value>prefix+"/awgn2o3_4.fsm"</value> + <value>fsm_i</value> </param> <param> <key>i_init_state</key> @@ -886,7 +1019,7 @@ </param> <param> <key>interleaver_args</key> - <value>trellis.interleaver(block,666)</value> + <value>interleaver</value> </param> <param> <key>bl</key> @@ -910,11 +1043,38 @@ </param> <param> <key>_coordinate</key> - <value>(242, 154)</value> + <value>(416, 369)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import gnuradio.trellis.fsm_utils as fu</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(40, 204)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> </param> </block> <block> @@ -929,15 +1089,15 @@ </param> <param> <key>type</key> - <value>c</value> + <value>f</value> </param> <param> <key>out_type</key> - <value>s</value> + <value>b</value> </param> <param> <key>o_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> + <value>fsm_o</value> </param> <param> <key>o_init_state</key> @@ -949,7 +1109,7 @@ </param> <param> <key>i_fsm_args</key> - <value>prefix+"/awgn2o3_4.fsm"</value> + <value>fsm_i</value> </param> <param> <key>i_init_state</key> @@ -961,7 +1121,7 @@ </param> <param> <key>interleaver</key> - <value>trellis.interleaver(block,666)</value> + <value>interleaver</value> </param> <param> <key>block_size</key> @@ -973,11 +1133,11 @@ </param> <param> <key>dim</key> - <value>2</value> + <value>dim</value> </param> <param> <key>table</key> - <value>1,0,1j,0,-1j,0,-1,0,1,0,1j,0,-1j,0,-1,0</value> + <value>constellation</value> </param> <param> <key>metric_type</key> @@ -985,11 +1145,11 @@ </param> <param> <key>siso_type</key> - <value>trellis.TRELLIS_SUM_PRODUCT</value> + <value>trellis.TRELLIS_MIN_SUM</value> </param> <param> <key>scaling</key> - <value>1.0</value> + <value>1.0/noisevar</value> </param> <param> <key>alias</key> @@ -1009,7 +1169,7 @@ </param> <param> <key>_coordinate</key> - <value>(241, 287)</value> + <value>(400, 745)</value> </param> <param> <key>_rotation</key> @@ -1017,74 +1177,74 @@ </param> </block> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>trellis_sccc_encoder_xx_0</sink_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_sccc_encoder_xx_0</source_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>trellis_sccc_decoder_combined_xx_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>trellis_sccc_encoder_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_sccc_decoder_combined_xx_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>trellis_sccc_encoder_xx_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_noise_source_x_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>virtual_source_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>virtual_source_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> - <source_key>0</source_key> - <sink_key>1</sink_key> - </connection> - <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>blks2_error_rate_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_2_0</source_block_id> - <sink_block_id>blocks_short_to_float_1_0</sink_block_id> + <source_block_id>trellis_sccc_decoder_combined_xx_0</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_1_0</source_block_id> - <sink_block_id>qtgui_number_sink_0</sink_block_id> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_sccc_decoder_combined_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-trellis/examples/grc/pccc1.grc b/gr-trellis/examples/grc/tcm.grc index acb112d255..451d940962 100644 --- a/gr-trellis/examples/grc/pccc1.grc +++ b/gr-trellis/examples/grc/tcm.grc @@ -1,11 +1,12 @@ <?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> <flow_graph> - <timestamp>Mon Jul 28 14:09:00 2014</timestamp> + <timestamp>Wed Oct 1 11:04:18 2014</timestamp> <block> <key>options</key> <param> <key>id</key> - <value>sccc1</value> + <value>tcm</value> </param> <param> <key>_enabled</key> @@ -13,7 +14,7 @@ </param> <param> <key>title</key> - <value>Parallel Concatenated Convolutional Code</value> + <value>Trellis Coded Modulation</value> </param> <param> <key>author</key> @@ -29,7 +30,7 @@ </param> <param> <key>generate_options</key> - <value>qt_gui</value> + <value>wx_gui</value> </param> <param> <key>category</key> @@ -84,7 +85,7 @@ </param> <param> <key>_coordinate</key> - <value>(513, 10)</value> + <value>(320, 13)</value> </param> <param> <key>_rotation</key> @@ -95,7 +96,7 @@ <key>variable</key> <param> <key>id</key> - <value>block</value> + <value>dim</value> </param> <param> <key>_enabled</key> @@ -103,7 +104,7 @@ </param> <param> <key>value</key> - <value>1000</value> + <value>mod[0]</value> </param> <param> <key>alias</key> @@ -111,7 +112,7 @@ </param> <param> <key>_coordinate</key> - <value>(441, 10)</value> + <value>(464, 229)</value> </param> <param> <key>_rotation</key> @@ -122,7 +123,7 @@ <key>variable</key> <param> <key>id</key> - <value>R</value> + <value>constellation</value> </param> <param> <key>_enabled</key> @@ -130,7 +131,7 @@ </param> <param> <key>value</key> - <value>100e3</value> + <value>mod[1]</value> </param> <param> <key>alias</key> @@ -138,7 +139,7 @@ </param> <param> <key>_coordinate</key> - <value>(358, 10)</value> + <value>(312, 229)</value> </param> <param> <key>_rotation</key> @@ -149,7 +150,7 @@ <key>variable</key> <param> <key>id</key> - <value>noisevar</value> + <value>mod</value> </param> <param> <key>_enabled</key> @@ -157,7 +158,7 @@ </param> <param> <key>value</key> - <value>10**(-snr_db/10)</value> + <value>fu.psk4</value> </param> <param> <key>alias</key> @@ -165,7 +166,7 @@ </param> <param> <key>_coordinate</key> - <value>(279, 10)</value> + <value>(336, 157)</value> </param> <param> <key>_rotation</key> @@ -173,54 +174,53 @@ </param> </block> <block> - <key>analog_random_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_random_source_x_0</value> + <value>fsm</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> - </param> - <param> - <key>min</key> - <value>0</value> + <key>value</key> + <value>"awgn1o2_4.fsm"</value> </param> <param> - <key>max</key> - <value>2</value> + <key>alias</key> + <value></value> </param> <param> - <key>num_samps</key> - <value>1000</value> + <key>_coordinate</key> + <value>(320, 77)</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>alias</key> - <value></value> + <key>id</key> + <value>R</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>value</key> + <value>100e3</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(21, 170)</value> + <value>(216, 109)</value> </param> <param> <key>_rotation</key> @@ -228,226 +228,270 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>variable</key> <param> <key>id</key> - <value>qtgui_number_sink_0</value> + <value>noisevar</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>name</key> - <value>""</value> + <key>value</key> + <value>10**(-EsN0_dB/10.0) * Es /2.0</value> </param> <param> - <key>type</key> - <value>float</value> + <key>alias</key> + <value></value> </param> <param> - <key>autoscale</key> - <value>False</value> + <key>_coordinate</key> + <value>(728, 157)</value> </param> <param> - <key>avg</key> - <value>0.001</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> + <key>id</key> + <value>Es</value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>min</key> + <key>value</key> + <value>sum(numpy.square(numpy.abs(constellation)))/(len(constellation)/(1.0*dim))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(528, 157)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>max</key> - <value>1</value> + <key>id</key> + <value>block</value> </param> <param> - <key>update_time</key> - <value>0.10</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gui_hint</key> - <value>1,0,1,1</value> + <key>value</key> + <value>500*16</value> </param> <param> - <key>label1</key> + <key>alias</key> <value></value> </param> <param> - <key>unit1</key> - <value></value> + <key>_coordinate</key> + <value>(216, 29)</value> </param> <param> - <key>color1</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_throttle</key> <param> - <key>factor1</key> - <value>1</value> + <key>id</key> + <value>blocks_throttle_0</value> </param> <param> - <key>label2</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit2</key> - <value></value> + <key>type</key> + <value>byte</value> </param> <param> - <key>color2</key> - <value>("black", "black")</value> + <key>samples_per_second</key> + <value>R</value> </param> <param> - <key>factor2</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>label3</key> - <value></value> + <key>ignoretag</key> + <value>True</value> </param> <param> - <key>unit3</key> + <key>alias</key> <value></value> </param> <param> - <key>color3</key> - <value>("black", "black")</value> + <key>affinity</key> + <value></value> </param> <param> - <key>factor3</key> - <value>1</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>label4</key> - <value></value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>unit4</key> - <value></value> + <key>_coordinate</key> + <value>(208, 380)</value> </param> <param> - <key>color4</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_add_xx</key> <param> - <key>factor4</key> - <value>1</value> + <key>id</key> + <value>blocks_add_xx_1</value> </param> <param> - <key>label5</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit5</key> - <value></value> + <key>type</key> + <value>float</value> </param> <param> - <key>color5</key> - <value>("black", "black")</value> + <key>num_inputs</key> + <value>2</value> </param> <param> - <key>factor5</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>label6</key> + <key>alias</key> <value></value> </param> <param> - <key>unit6</key> + <key>affinity</key> <value></value> </param> <param> - <key>color6</key> - <value>("black", "black")</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>factor6</key> - <value>1</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>label7</key> - <value></value> + <key>_coordinate</key> + <value>(912, 488)</value> </param> <param> - <key>unit7</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>color7</key> - <value>("black", "black")</value> + <key>id</key> + <value>virtual_sink_0_0</value> </param> <param> - <key>factor7</key> - <value>1</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>label8</key> - <value></value> + <key>stream_id</key> + <value>info</value> </param> <param> - <key>unit8</key> - <value></value> + <key>_coordinate</key> + <value>(224, 316)</value> </param> <param> - <key>color8</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>factor8</key> - <value>1</value> + <key>id</key> + <value>virtual_sink_0</value> </param> <param> - <key>label9</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit9</key> - <value></value> + <key>stream_id</key> + <value>observation</value> </param> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>_coordinate</key> + <value>(832, 620)</value> </param> <param> - <key>factor9</key> - <value>1</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>label10</key> - <value></value> + <key>id</key> + <value>virtual_source_0</value> </param> <param> - <key>unit10</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>stream_id</key> + <value>observation</value> </param> <param> - <key>factor10</key> - <value>1</value> + <key>_coordinate</key> + <value>(64, 732)</value> </param> <param> - <key>alias</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>affinity</key> - <value></value> + <key>id</key> + <value>virtual_sink_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate</value> </param> <param> <key>_coordinate</key> - <value>(632, 509)</value> + <value>(800, 732)</value> </param> <param> <key>_rotation</key> @@ -455,22 +499,30 @@ </param> </block> <block> - <key>blocks_short_to_float</key> + <key>analog_noise_source_x</key> <param> <key>id</key> - <value>blocks_short_to_float_1_0</value> + <value>analog_noise_source_x_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>type</key> + <value>float</value> </param> <param> - <key>scale</key> - <value>1</value> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> + </param> + <param> + <key>amp</key> + <value>noisevar**0.5</value> + </param> + <param> + <key>seed</key> + <value>-42</value> </param> <param> <key>alias</key> @@ -490,7 +542,7 @@ </param> <param> <key>_coordinate</key> - <value>(375, 525)</value> + <value>(384, 502)</value> </param> <param> <key>_rotation</key> @@ -498,46 +550,58 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>variable_slider</key> <param> <key>id</key> - <value>blocks_multiply_xx_2_0</value> + <value>EsN0_dB</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>label</key> + <value>Es/N0 (dB)</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>value</key> + <value>4.0</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>min</key> + <value>-10</value> </param> <param> - <key>alias</key> - <value></value> + <key>max</key> + <value>30</value> </param> <param> - <key>affinity</key> + <key>num_steps</key> + <value>1000</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>notebook</key> + <value></value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(232, 507)</value> + <value>(608, 105)</value> </param> <param> <key>_rotation</key> @@ -545,10 +609,10 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>analog_random_source_x</key> <param> <key>id</key> - <value>blocks_sub_xx_0</value> + <value>analog_random_source_x_0</value> </param> <param> <key>_enabled</key> @@ -556,17 +620,25 @@ </param> <param> <key>type</key> - <value>short</value> + <value>byte</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>min</key> + <value>0</value> </param> <param> - <key>num_inputs</key> + <key>max</key> <value>2</value> </param> <param> + <key>num_samps</key> + <value>1007</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> <key>alias</key> <value></value> </param> @@ -584,7 +656,7 @@ </param> <param> <key>_coordinate</key> - <value>(57, 513)</value> + <value>(8, 359)</value> </param> <param> <key>_rotation</key> @@ -592,49 +664,81 @@ </param> </block> <block> - <key>variable_qtgui_range</key> + <key>wxgui_numbersink2</key> <param> <key>id</key> - <value>snr_db</value> + <value>wxgui_numbersink2_3_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>SNR (dB)</value> + <key>type</key> + <value>float</value> </param> <param> - <key>value</key> - <value>5</value> + <key>title</key> + <value>BER</value> </param> <param> - <key>start</key> - <value>-10</value> + <key>units</key> + <value>BER</value> + </param> + <param> + <key>samp_rate</key> + <value>R</value> + </param> + <param> + <key>min_value</key> + <value>0</value> + </param> + <param> + <key>max_value</key> + <value>1.0</value> + </param> + <param> + <key>factor</key> + <value>1.0</value> + </param> + <param> + <key>decimal_places</key> + <value>6</value> + </param> + <param> + <key>ref_level</key> + <value>0</value> + </param> + <param> + <key>number_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>stop</key> - <value>10</value> + <key>average</key> + <value>False</value> </param> <param> - <key>step</key> - <value>0.01</value> + <key>avg_alpha</key> + <value>0.001</value> </param> <param> - <key>widget</key> - <value>counter_slider</value> + <key>show_gauge</key> + <value>False</value> </param> <param> - <key>orient</key> - <value>Qt.Horizontal</value> + <key>win_size</key> + <value></value> </param> <param> - <key>min_len</key> - <value>200</value> + <key>grid_pos</key> + <value></value> </param> <param> - <key>gui_hint</key> + <key>notebook</key> <value></value> </param> <param> @@ -642,51 +746,85 @@ <value></value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> <key>_coordinate</key> - <value>(177, 10)</value> + <value>(728, 1133)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> - <key>trellis_pccc_encoder_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>trellis_pccc_encoder_xx_0</value> + <value>virtual_source_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>ss</value> + <key>stream_id</key> + <value>info</value> </param> <param> - <key>o_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> + <key>_coordinate</key> + <value>(80, 1148)</value> </param> <param> - <key>o_init_state</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>i_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> + <key>id</key> + <value>virtual_source_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate</value> </param> <param> - <key>i_init_state</key> + <key>_coordinate</key> + <value>(72, 1244)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blks2_error_rate</key> <param> - <key>interleaver_args</key> - <value>trellis.interleaver(block,666)</value> + <key>id</key> + <value>blks2_error_rate_0</value> </param> <param> - <key>bl</key> - <value>block</value> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>'SER'</value> + </param> + <param> + <key>win_size</key> + <value>block*100</value> + </param> + <param> + <key>bits_per_symbol</key> + <value>1</value> </param> <param> <key>alias</key> @@ -706,7 +844,34 @@ </param> <param> <key>_coordinate</key> - <value>(235, 154)</value> + <value>(312, 1184)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>note</key> + <param> + <key>id</key> + <value>note_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>note</key> + <value>Substititue the metrics/Viterbi block with Viterbi_combo</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(712, 868)</value> </param> <param> <key>_rotation</key> @@ -721,7 +886,7 @@ </param> <param> <key>_enabled</key> - <value>True</value> + <value>False</value> </param> <param> <key>type</key> @@ -729,15 +894,15 @@ </param> <param> <key>card</key> - <value>16</value> + <value>trellis.fsm(prefix+fsm).O()</value> </param> <param> <key>dim</key> - <value>2</value> + <value>dim</value> </param> <param> <key>table</key> - <value>-7,0, -5,0, -3,0, -1,0, 1,0, 3,0, 5,0, 7,0, 0,-7,0, -5,0, -3,0, -1,0, 1,0, 3,0, 5,0, 7,0</value> + <value>constellation</value> </param> <param> <key>metric_type</key> @@ -761,7 +926,7 @@ </param> <param> <key>_coordinate</key> - <value>(89, 380)</value> + <value>(304, 711)</value> </param> <param> <key>_rotation</key> @@ -769,58 +934,34 @@ </param> </block> <block> - <key>trellis_pccc_decoder_x</key> + <key>trellis_viterbi_x</key> <param> <key>id</key> - <value>trellis_pccc_decoder_x_0</value> + <value>trellis_viterbi_x_0</value> </param> <param> <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>out_type</key> - <value>s</value> - </param> - <param> - <key>o_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> - </param> - <param> - <key>o_init_state</key> - <value>0</value> - </param> - <param> - <key>o_final_state</key> - <value>-1</value> - </param> - <param> - <key>i_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> - </param> - <param> - <key>i_init_state</key> - <value>0</value> + <value>False</value> </param> <param> - <key>i_final_state</key> - <value>-1</value> + <key>type</key> + <value>b</value> </param> <param> - <key>interleaver</key> - <value>trellis.interleaver(block,666)</value> + <key>fsm_args</key> + <value>prefix+fsm</value> </param> <param> <key>block_size</key> <value>block</value> </param> <param> - <key>iterations</key> - <value>10</value> + <key>init_state</key> + <value>-1</value> </param> <param> - <key>siso_type</key> - <value>trellis.TRELLIS_MIN_SUM</value> + <key>final_state</key> + <value>-1</value> </param> <param> <key>alias</key> @@ -840,7 +981,7 @@ </param> <param> <key>_coordinate</key> - <value>(379, 332)</value> + <value>(544, 711)</value> </param> <param> <key>_rotation</key> @@ -848,34 +989,50 @@ </param> </block> <block> - <key>digital_chunks_to_symbols_xx</key> + <key>trellis_viterbi_combined_xx</key> <param> <key>id</key> - <value>digital_chunks_to_symbols_xx_0</value> + <value>trellis_viterbi_combined_xx_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>in_type</key> - <value>short</value> + <key>type</key> + <value>f</value> </param> <param> <key>out_type</key> - <value>float</value> + <value>b</value> </param> <param> - <key>symbol_table</key> - <value>-7,0,-5,0,-3,0,-1,0,1,0,3,0,5,0,7,0,-7,0,-5,0,-3,0,-1,0,1,0,3,0,5,0,7,0</value> + <key>fsm_args</key> + <value>prefix+fsm</value> </param> <param> - <key>dimension</key> - <value>2</value> + <key>block_size</key> + <value>block</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>init_state</key> + <value>-1</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> + </param> + <param> + <key>dim</key> + <value>dim</value> + </param> + <param> + <key>table</key> + <value>constellation</value> + </param> + <param> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> </param> <param> <key>alias</key> @@ -895,7 +1052,7 @@ </param> <param> <key>_coordinate</key> - <value>(552, 164)</value> + <value>(440, 866)</value> </param> <param> <key>_rotation</key> @@ -903,50 +1060,53 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>import</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>import_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>import</key> + <value>import numpy</value> </param> <param> - <key>samples_per_second</key> - <value>R</value> + <key>alias</key> + <value></value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>_coordinate</key> + <value>(16, 140)</value> </param> <param> - <key>ignoretag</key> - <value>True</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>import</key> <param> - <key>alias</key> - <value></value> + <key>id</key> + <value>import_0_0</value> </param> <param> - <key>affinity</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>import</key> + <value>import gnuradio.trellis.fsm_utils as fu</value> </param> <param> - <key>maxoutbuf</key> - <value>0</value> + <key>alias</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(553, 89)</value> + <value>(24, 196)</value> </param> <param> <key>_rotation</key> @@ -954,30 +1114,34 @@ </param> </block> <block> - <key>analog_noise_source_x</key> + <key>digital_chunks_to_symbols_xx</key> <param> <key>id</key> - <value>analog_noise_source_x_0</value> + <value>digital_chunks_to_symbols_xx_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> + <key>in_type</key> + <value>byte</value> + </param> + <param> + <key>out_type</key> <value>float</value> </param> <param> - <key>noise_type</key> - <value>analog.GR_GAUSSIAN</value> + <key>symbol_table</key> + <value>constellation</value> </param> <param> - <key>amp</key> - <value>noisevar</value> + <key>dimension</key> + <value>dim</value> </param> <param> - <key>seed</key> - <value>-42</value> + <key>num_ports</key> + <value>1</value> </param> <param> <key>alias</key> @@ -997,7 +1161,7 @@ </param> <param> <key>_coordinate</key> - <value>(551, 230)</value> + <value>(696, 373)</value> </param> <param> <key>_rotation</key> @@ -1005,10 +1169,10 @@ </param> </block> <block> - <key>blocks_add_xx</key> + <key>trellis_encoder_xx</key> <param> <key>id</key> - <value>blocks_add_xx_1</value> + <value>trellis_encoder_xx_0</value> </param> <param> <key>_enabled</key> @@ -1016,15 +1180,23 @@ </param> <param> <key>type</key> - <value>float</value> + <value>bb</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>fsm_args</key> + <value>prefix+fsm</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>init_state</key> + <value>0</value> + </param> + <param> + <key>blockwise</key> + <value>False</value> + </param> + <param> + <key>blocklength</key> + <value>0</value> </param> <param> <key>alias</key> @@ -1044,7 +1216,7 @@ </param> <param> <key>_coordinate</key> - <value>(839, 176)</value> + <value>(424, 373)</value> </param> <param> <key>_rotation</key> @@ -1052,81 +1224,93 @@ </param> </block> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>trellis_metrics_x_0</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>trellis_pccc_encoder_xx_0</sink_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_pccc_encoder_xx_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>trellis_encoder_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_metrics_x_0</source_block_id> - <sink_block_id>trellis_pccc_decoder_x_0</sink_block_id> + <source_block_id>trellis_encoder_xx_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_pccc_decoder_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_1_0</source_block_id> - <sink_block_id>qtgui_number_sink_0</sink_block_id> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_metrics_x_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>trellis_metrics_x_0</source_block_id> + <sink_block_id>trellis_viterbi_x_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_2_0</source_block_id> - <sink_block_id>blocks_short_to_float_1_0</sink_block_id> + <source_block_id>trellis_viterbi_x_0</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_noise_source_x_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_0</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> + <source_block_id>blks2_error_rate_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> + <connection> + <source_block_id>virtual_source_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> </flow_graph> diff --git a/gr-trellis/examples/grc/turbo_equalization.grc b/gr-trellis/examples/grc/turbo_equalization.grc new file mode 100644 index 0000000000..c83c59db20 --- /dev/null +++ b/gr-trellis/examples/grc/turbo_equalization.grc @@ -0,0 +1,2766 @@ +<?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> +<flow_graph> + <timestamp>Wed Oct 1 11:04:18 2014</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>turbo_equalization</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value>Hard/Soft/Turbo Equalization</value> + </param> + <param> + <key>author</key> + <value>AA</value> + </param> + <param> + <key>description</key> + <value>gnuradio flow graph</value> + </param> + <param> + <key>window_size</key> + <value>2048, 3048</value> + </param> + <param> + <key>generate_options</key> + <value>wx_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>fsm_o</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>trellis.fsm(prefix+"/awgn1o2_4.fsm")</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(344, 21)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>block_b</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>bpsym*1000</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(216, 21)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>interleaver</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>trellis.interleaver(block_b/bpsym,666)</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(528, 117)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>Es</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>numpy.mean((numpy.square(numpy.abs(tot_mod[1]))))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(776, 181)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>noisevar</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>10**(-EsN0_dB/10.0) * Es /2.0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(1080, 181)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>bpsym</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>int(round(math.log(fsm_o.I())/math.log(2)))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(528, 29)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>channel</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>fu.c_channel</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 205)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>modulation</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>fu.pam4</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 117)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>R</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>100e3</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(216, 109)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>tot_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>fu.make_isi_lookup(modulation,channel,False)</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 381)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>prefix</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>"@FSM_FILE_INSTALL_DIR@"</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(768, 21)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>fsm_i</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>trellis.fsm(len(modulation[1]),len(channel))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 293)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import gnuradio.trellis.fsm_utils as fu</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(24, 252)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import numpy</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 140)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import math</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(24, 188)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> + </param> + <param> + <key>_coordinate</key> + <value>(608, 1076)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_add_xx</key> + <param> + <key>id</key> + <value>blocks_add_xx_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>num_inputs</key> + <value>2</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(688, 944)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>analog_noise_source_x</key> + <param> + <key>id</key> + <value>analog_noise_source_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> + </param> + <param> + <key>amp</key> + <value>noisevar**0.5</value> + </param> + <param> + <key>seed</key> + <value>-42</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(288, 958)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>fir_filter_xxx</key> + <param> + <key>id</key> + <value>fir_filter_xxx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>fff</value> + </param> + <param> + <key>decim</key> + <value>1</value> + </param> + <param> + <key>taps</key> + <value>fu.c_channel</value> + </param> + <param> + <key>samp_delay</key> + <value>0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(448, 861)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> + <param> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>in_type</key> + <value>byte</value> + </param> + <param> + <key>out_type</key> + <value>float</value> + </param> + <param> + <key>symbol_table</key> + <value>modulation[1]</value> + </param> + <param> + <key>dimension</key> + <value>modulation[0]</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(480, 733)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_permutation</key> + <param> + <key>id</key> + <value>trellis_permutation_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>interleaver_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>table</key> + <value>interleaver.INTER()</value> + </param> + <param> + <key>syms_per_block</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(208, 726)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info_i</value> + </param> + <param> + <key>_coordinate</key> + <value>(968, 572)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>samples_per_second</key> + <value>R</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>ignoretag</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(256, 580)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>analog_random_source_x</key> + <param> + <key>id</key> + <value>analog_random_source_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>min</key> + <value>0</value> + </param> + <param> + <key>max</key> + <value>2</value> + </param> + <param> + <key>num_samps</key> + <value>1007</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 559)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_pack_k_bits_bb</key> + <param> + <key>id</key> + <value>blocks_pack_k_bits_bb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>k</key> + <value>bpsym</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(440, 580)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_encoder_xx</key> + <param> + <key>id</key> + <value>trellis_encoder_xx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>bb</value> + </param> + <param> + <key>fsm_args</key> + <value>fsm_o</value> + </param> + <param> + <key>init_state</key> + <value>0</value> + </param> + <param> + <key>blockwise</key> + <value>False</value> + </param> + <param> + <key>blocklength</key> + <value>0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(672, 573)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> + <param> + <key>_coordinate</key> + <value>(248, 524)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate</value> + </param> + <param> + <key>_coordinate</key> + <value>(864, 1380)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_unpack_k_bits_bb</key> + <param> + <key>id</key> + <value>blocks_unpack_k_bits_bb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>k</key> + <value>bpsym</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(552, 1380)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_char_to_float</key> + <param> + <key>id</key> + <value>blocks_char_to_float_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>scale</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(72, 1380)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_permutation</key> + <param> + <key>id</key> + <value>trellis_permutation_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>interleaver_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>table</key> + <value>interleaver.DEINTER()</value> + </param> + <param> + <key>syms_per_block</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(568, 1222)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_viterbi_combined_xx</key> + <param> + <key>id</key> + <value>trellis_viterbi_combined_xx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>f</value> + </param> + <param> + <key>out_type</key> + <value>b</value> + </param> + <param> + <key>fsm_args</key> + <value>fsm_i</value> + </param> + <param> + <key>block_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>init_state</key> + <value>-1</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> + </param> + <param> + <key>dim</key> + <value>tot_mod[0]</value> + </param> + <param> + <key>table</key> + <value>tot_mod[1]</value> + </param> + <param> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(288, 1194)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_1_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate_i</value> + </param> + <param> + <key>_coordinate</key> + <value>(896, 1228)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> + </param> + <param> + <key>_coordinate</key> + <value>(40, 1236)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>analog_const_source_x</key> + <param> + <key>id</key> + <value>analog_const_source_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>const</key> + <value>0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(88, 1788)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_viterbi_combined_xx</key> + <param> + <key>id</key> + <value>trellis_viterbi_combined_xx_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>f</value> + </param> + <param> + <key>out_type</key> + <value>b</value> + </param> + <param> + <key>fsm_args</key> + <value>fsm_o</value> + </param> + <param> + <key>block_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>init_state</key> + <value>-1</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> + </param> + <param> + <key>dim</key> + <value>1</value> + </param> + <param> + <key>table</key> + <value>0,1,2,3</value> + </param> + <param> + <key>metric_type</key> + <value>digital.TRELLIS_HARD_SYMBOL</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(256, 1338)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_siso_combined_f</key> + <param> + <key>id</key> + <value>trellis_siso_combined_f_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fsm_args</key> + <value>fsm_i</value> + </param> + <param> + <key>block_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>init_state</key> + <value>-1</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> + </param> + <param> + <key>a_post_in</key> + <value>True</value> + </param> + <param> + <key>a_post_out</key> + <value>False</value> + </param> + <param> + <key>siso_type</key> + <value>trellis.TRELLIS_MIN_SUM</value> + </param> + <param> + <key>dim</key> + <value>tot_mod[0]</value> + </param> + <param> + <key>table</key> + <value>tot_mod[1]</value> + </param> + <param> + <key>metric_type</key> + <value>trellis.TRELLIS_EUCLIDEAN</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(280, 1765)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_permutation</key> + <param> + <key>id</key> + <value>trellis_permutation_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>interleaver_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>table</key> + <value>interleaver.DEINTER()</value> + </param> + <param> + <key>syms_per_block</key> + <value>fsm_o.O()</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(616, 1814)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_viterbi_x</key> + <param> + <key>id</key> + <value>trellis_viterbi_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>b</value> + </param> + <param> + <key>fsm_args</key> + <value>fsm_o</value> + </param> + <param> + <key>block_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>init_state</key> + <value>0</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(288, 2023)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> + </param> + <param> + <key>_coordinate</key> + <value>(72, 1860)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_1_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> + </param> + <param> + <key>_coordinate</key> + <value>(88, 2564)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_unpack_k_bits_bb</key> + <param> + <key>id</key> + <value>blocks_unpack_k_bits_bb_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>k</key> + <value>bpsym</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(584, 2044)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_1_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate1</value> + </param> + <param> + <key>_coordinate</key> + <value>(896, 2044)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate1</value> + </param> + <param> + <key>_coordinate</key> + <value>(144, 2284)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_1_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> + <param> + <key>_coordinate</key> + <value>(152, 2188)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_1_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> + <param> + <key>_coordinate</key> + <value>(176, 2732)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_0_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate2</value> + </param> + <param> + <key>_coordinate</key> + <value>(168, 2828)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> + <param> + <key>_coordinate</key> + <value>(80, 1556)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate</value> + </param> + <param> + <key>_coordinate</key> + <value>(72, 1652)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_numbersink2</key> + <param> + <key>id</key> + <value>wxgui_numbersink2_3_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>title</key> + <value>BER_hard</value> + </param> + <param> + <key>units</key> + <value>BER</value> + </param> + <param> + <key>samp_rate</key> + <value>R</value> + </param> + <param> + <key>min_value</key> + <value>0</value> + </param> + <param> + <key>max_value</key> + <value>1.0</value> + </param> + <param> + <key>factor</key> + <value>1.0</value> + </param> + <param> + <key>decimal_places</key> + <value>6</value> + </param> + <param> + <key>ref_level</key> + <value>0</value> + </param> + <param> + <key>number_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0.001</value> + </param> + <param> + <key>show_gauge</key> + <value>False</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(504, 1549)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_numbersink2</key> + <param> + <key>id</key> + <value>wxgui_numbersink2_3_0_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>title</key> + <value>BER_soft</value> + </param> + <param> + <key>units</key> + <value>BER</value> + </param> + <param> + <key>samp_rate</key> + <value>R</value> + </param> + <param> + <key>min_value</key> + <value>0</value> + </param> + <param> + <key>max_value</key> + <value>1.0</value> + </param> + <param> + <key>factor</key> + <value>1.0</value> + </param> + <param> + <key>decimal_places</key> + <value>6</value> + </param> + <param> + <key>ref_level</key> + <value>0</value> + </param> + <param> + <key>number_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0.001</value> + </param> + <param> + <key>show_gauge</key> + <value>False</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(576, 2181)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_numbersink2</key> + <param> + <key>id</key> + <value>wxgui_numbersink2_3_0_0_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>title</key> + <value>BER_turbo</value> + </param> + <param> + <key>units</key> + <value>BER</value> + </param> + <param> + <key>samp_rate</key> + <value>R</value> + </param> + <param> + <key>min_value</key> + <value>0</value> + </param> + <param> + <key>max_value</key> + <value>1.0</value> + </param> + <param> + <key>factor</key> + <value>1.0</value> + </param> + <param> + <key>decimal_places</key> + <value>6</value> + </param> + <param> + <key>ref_level</key> + <value>0</value> + </param> + <param> + <key>number_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0.001</value> + </param> + <param> + <key>show_gauge</key> + <value>False</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(600, 2725)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>trellis_sccc_decoder_combined_xx</key> + <param> + <key>id</key> + <value>trellis_sccc_decoder_combined_xx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>f</value> + </param> + <param> + <key>out_type</key> + <value>b</value> + </param> + <param> + <key>o_fsm_args</key> + <value>fsm_o</value> + </param> + <param> + <key>o_init_state</key> + <value>-1</value> + </param> + <param> + <key>o_final_state</key> + <value>-1</value> + </param> + <param> + <key>i_fsm_args</key> + <value>fsm_i</value> + </param> + <param> + <key>i_init_state</key> + <value>-1</value> + </param> + <param> + <key>i_final_state</key> + <value>-1</value> + </param> + <param> + <key>interleaver</key> + <value>interleaver</value> + </param> + <param> + <key>block_size</key> + <value>interleaver.K()</value> + </param> + <param> + <key>iterations</key> + <value>5</value> + </param> + <param> + <key>dim</key> + <value>tot_mod[0]</value> + </param> + <param> + <key>table</key> + <value>tot_mod[1]</value> + </param> + <param> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> + </param> + <param> + <key>siso_type</key> + <value>trellis.TRELLIS_MIN_SUM</value> + </param> + <param> + <key>scaling</key> + <value>1.0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(456, 2481)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blks2_error_rate</key> + <param> + <key>id</key> + <value>blks2_error_rate_0_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>'BER'</value> + </param> + <param> + <key>win_size</key> + <value>block_b*100</value> + </param> + <param> + <key>bits_per_symbol</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(408, 2766)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blks2_error_rate</key> + <param> + <key>id</key> + <value>blks2_error_rate_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>'BER'</value> + </param> + <param> + <key>win_size</key> + <value>block_b*100</value> + </param> + <param> + <key>bits_per_symbol</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(384, 2230)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blks2_error_rate</key> + <param> + <key>id</key> + <value>blks2_error_rate_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>'BER'</value> + </param> + <param> + <key>win_size</key> + <value>block_b*100</value> + </param> + <param> + <key>bits_per_symbol</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(312, 1598)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_slider</key> + <param> + <key>id</key> + <value>EsN0_dB</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Es/N0 (dB)</value> + </param> + <param> + <key>value</key> + <value>13.0</value> + </param> + <param> + <key>min</key> + <value>-10</value> + </param> + <param> + <key>max</key> + <value>30</value> + </param> + <param> + <key>num_steps</key> + <value>1000</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(936, 129)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_unpack_k_bits_bb</key> + <param> + <key>id</key> + <value>blocks_unpack_k_bits_bb_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>k</key> + <value>bpsym</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(720, 2572)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_1_1_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate2</value> + </param> + <param> + <key>_coordinate</key> + <value>(920, 2572)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>note</key> + <param> + <key>id</key> + <value>note_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>note</key> + <value>This is the full-fledged turbo equalizer/decoder</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(1144, 2572)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>note</key> + <param> + <key>id</key> + <value>note_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>note</key> + <value>This is a better soft-equalizer/Viterbi decoder</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(1016, 1908)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>note</key> + <param> + <key>id</key> + <value>note_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>note</key> + <value>This is the simplest hard Viterbi equalizer/hard Viterbi decoder</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(1096, 1316)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> + <sink_block_id>fir_filter_xxx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fir_filter_xxx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_pack_k_bits_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_pack_k_bits_bb_0</source_block_id> + <sink_block_id>trellis_encoder_xx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_encoder_xx_0</source_block_id> + <sink_block_id>trellis_permutation_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_permutation_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_encoder_xx_0</source_block_id> + <sink_block_id>virtual_sink_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_char_to_float_0</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_permutation_0_0</source_block_id> + <sink_block_id>blocks_char_to_float_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_permutation_0_0</source_block_id> + <sink_block_id>virtual_sink_0_1_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_unpack_k_bits_bb_0</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_viterbi_combined_xx_1</source_block_id> + <sink_block_id>blocks_unpack_k_bits_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_viterbi_combined_xx_0</source_block_id> + <sink_block_id>trellis_permutation_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_unpack_k_bits_bb_0_0</source_block_id> + <sink_block_id>virtual_sink_0_1_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_1</source_block_id> + <sink_block_id>trellis_siso_combined_f_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>analog_const_source_x_0</source_block_id> + <sink_block_id>trellis_siso_combined_f_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_siso_combined_f_0</source_block_id> + <sink_block_id>trellis_permutation_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_permutation_0_0_0</source_block_id> + <sink_block_id>trellis_viterbi_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_viterbi_x_0</source_block_id> + <sink_block_id>blocks_unpack_k_bits_bb_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_1_0</source_block_id> + <sink_block_id>trellis_sccc_decoder_combined_xx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_unpack_k_bits_bb_0_0_0</source_block_id> + <sink_block_id>virtual_sink_0_1_1_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_sccc_decoder_combined_xx_0</source_block_id> + <sink_block_id>blocks_unpack_k_bits_bb_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blks2_error_rate_0_0_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_1_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>blks2_error_rate_0_0_0_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_1_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_0_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>blks2_error_rate_0_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_1</source_block_id> + <sink_block_id>blks2_error_rate_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> +</flow_graph> diff --git a/gr-trellis/examples/grc/sccc1.grc b/gr-trellis/examples/grc/viterbi_equalization.grc index 71b3f76625..2f69ead429 100644 --- a/gr-trellis/examples/grc/sccc1.grc +++ b/gr-trellis/examples/grc/viterbi_equalization.grc @@ -1,11 +1,12 @@ <?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> <flow_graph> - <timestamp>Mon Jul 28 14:10:35 2014</timestamp> + <timestamp>Wed Oct 1 11:04:18 2014</timestamp> <block> <key>options</key> <param> <key>id</key> - <value>sccc1</value> + <value>viterbi_equalization</value> </param> <param> <key>_enabled</key> @@ -13,7 +14,7 @@ </param> <param> <key>title</key> - <value>Serially Concatenated Convolutional Code</value> + <value>Viterbi Equalization</value> </param> <param> <key>author</key> @@ -29,7 +30,7 @@ </param> <param> <key>generate_options</key> - <value>qt_gui</value> + <value>wx_gui</value> </param> <param> <key>category</key> @@ -68,7 +69,7 @@ <key>variable</key> <param> <key>id</key> - <value>prefix</value> + <value>noisevar</value> </param> <param> <key>_enabled</key> @@ -76,7 +77,7 @@ </param> <param> <key>value</key> - <value>"@FSM_FILE_INSTALL_DIR@"</value> + <value>10**(-EsN0_dB/10.0) * Es /2.0</value> </param> <param> <key>alias</key> @@ -84,7 +85,7 @@ </param> <param> <key>_coordinate</key> - <value>(513, 10)</value> + <value>(872, 157)</value> </param> <param> <key>_rotation</key> @@ -95,7 +96,7 @@ <key>variable</key> <param> <key>id</key> - <value>block</value> + <value>bpsym</value> </param> <param> <key>_enabled</key> @@ -103,7 +104,7 @@ </param> <param> <key>value</key> - <value>1000</value> + <value>int(round(math.log(fsm.I())/math.log(2)))</value> </param> <param> <key>alias</key> @@ -111,7 +112,34 @@ </param> <param> <key>_coordinate</key> - <value>(441, 10)</value> + <value>(528, 13)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>channel</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>fu.c_channel</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 85)</value> </param> <param> <key>_rotation</key> @@ -138,7 +166,7 @@ </param> <param> <key>_coordinate</key> - <value>(358, 10)</value> + <value>(216, 109)</value> </param> <param> <key>_rotation</key> @@ -149,7 +177,7 @@ <key>variable</key> <param> <key>id</key> - <value>noisevar</value> + <value>block</value> </param> <param> <key>_enabled</key> @@ -157,7 +185,7 @@ </param> <param> <key>value</key> - <value>10**(-snr_db/10)</value> + <value>bpsym*1000</value> </param> <param> <key>alias</key> @@ -165,7 +193,7 @@ </param> <param> <key>_coordinate</key> - <value>(279, 10)</value> + <value>(216, 21)</value> </param> <param> <key>_rotation</key> @@ -173,54 +201,161 @@ </param> </block> <block> - <key>analog_random_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_random_source_x_0</value> + <value>fsm</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>value</key> + <value>trellis.fsm(len(modulation[1]),len(channel))</value> </param> <param> - <key>min</key> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 157)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>variable</key> <param> - <key>max</key> - <value>2</value> + <key>id</key> + <value>tot_mod</value> </param> <param> - <key>num_samps</key> - <value>1000</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>repeat</key> + <key>value</key> + <value>fu.make_isi_lookup(modulation,channel,False)</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(320, 229)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>modulation</value> + </param> + <param> + <key>_enabled</key> <value>True</value> </param> <param> + <key>value</key> + <value>fu.pam4</value> + </param> + <param> <key>alias</key> <value></value> </param> <param> - <key>affinity</key> + <key>_coordinate</key> + <value>(320, 21)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>Es</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>numpy.mean((numpy.square(numpy.abs(tot_mod[1]))))</value> + </param> + <param> + <key>alias</key> <value></value> </param> <param> - <key>minoutbuf</key> + <key>_coordinate</key> + <value>(568, 157)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0_0</value> + </param> <param> - <key>maxoutbuf</key> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import gnuradio.trellis.fsm_utils as fu</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(24, 252)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import numpy</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> <param> <key>_coordinate</key> - <value>(21, 170)</value> + <value>(16, 140)</value> </param> <param> <key>_rotation</key> @@ -228,32 +363,55 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>import</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>import_0_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>short</value> + <key>import</key> + <value>import math</value> </param> <param> - <key>samples_per_second</key> - <value>R</value> + <key>alias</key> + <value></value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>_coordinate</key> + <value>(24, 188)</value> </param> <param> - <key>ignoretag</key> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blks2_error_rate</key> + <param> + <key>id</key> + <value>blks2_error_rate_0</value> + </param> + <param> + <key>_enabled</key> <value>True</value> </param> <param> + <key>type</key> + <value>'BER'</value> + </param> + <param> + <key>win_size</key> + <value>block*100</value> + </param> + <param> + <key>bits_per_symbol</key> + <value>1</value> + </param> + <param> <key>alias</key> <value></value> </param> @@ -271,7 +429,7 @@ </param> <param> <key>_coordinate</key> - <value>(607, 110)</value> + <value>(312, 1766)</value> </param> <param> <key>_rotation</key> @@ -279,10 +437,56 @@ </param> </block> <block> - <key>blocks_add_xx</key> + <key>virtual_source</key> <param> <key>id</key> - <value>blocks_add_xx_1</value> + <value>virtual_source_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> + <param> + <key>_coordinate</key> + <value>(80, 1724)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>estimate</value> + </param> + <param> + <key>_coordinate</key> + <value>(72, 1820)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_numbersink2</key> + <param> + <key>id</key> + <value>wxgui_numbersink2_3_0_0</value> </param> <param> <key>_enabled</key> @@ -293,12 +497,68 @@ <value>float</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>title</key> + <value>BER</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>units</key> + <value>BER</value> + </param> + <param> + <key>samp_rate</key> + <value>R</value> + </param> + <param> + <key>min_value</key> + <value>0</value> + </param> + <param> + <key>max_value</key> + <value>1.0</value> + </param> + <param> + <key>factor</key> + <value>1.0</value> + </param> + <param> + <key>decimal_places</key> + <value>6</value> + </param> + <param> + <key>ref_level</key> + <value>0</value> + </param> + <param> + <key>number_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0.001</value> + </param> + <param> + <key>show_gauge</key> + <value>False</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> </param> <param> <key>alias</key> @@ -309,16 +569,81 @@ <value></value> </param> <param> - <key>minoutbuf</key> + <key>_coordinate</key> + <value>(728, 1709)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>note</key> <param> - <key>maxoutbuf</key> + <key>id</key> + <value>note_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>note</key> + <value>Substititue the metrics/Viterbi block with Viterbi_combo</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(704, 1468)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> + <param> + <key>id</key> + <value>virtual_source_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> + </param> + <param> + <key>_coordinate</key> + <value>(40, 1236)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>info</value> + </param> <param> <key>_coordinate</key> - <value>(932, 187)</value> + <value>(232, 524)</value> </param> <param> <key>_rotation</key> @@ -326,10 +651,10 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>analog_random_source_x</key> <param> <key>id</key> - <value>blocks_multiply_xx_2_0</value> + <value>analog_random_source_x_0</value> </param> <param> <key>_enabled</key> @@ -337,15 +662,23 @@ </param> <param> <key>type</key> - <value>short</value> + <value>byte</value> </param> <param> - <key>num_inputs</key> + <key>min</key> + <value>0</value> + </param> + <param> + <key>max</key> <value>2</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>num_samps</key> + <value>1007</value> + </param> + <param> + <key>repeat</key> + <value>True</value> </param> <param> <key>alias</key> @@ -365,7 +698,7 @@ </param> <param> <key>_coordinate</key> - <value>(233, 480)</value> + <value>(16, 559)</value> </param> <param> <key>_rotation</key> @@ -373,10 +706,10 @@ </param> </block> <block> - <key>blocks_sub_xx</key> + <key>blocks_null_sink</key> <param> <key>id</key> - <value>blocks_sub_xx_0</value> + <value>blocks_null_sink_1</value> </param> <param> <key>_enabled</key> @@ -384,7 +717,7 @@ </param> <param> <key>type</key> - <value>short</value> + <value>float</value> </param> <param> <key>vlen</key> @@ -392,7 +725,11 @@ </param> <param> <key>num_inputs</key> - <value>2</value> + <value>1</value> + </param> + <param> + <key>bus_conns</key> + <value>[[0,],]</value> </param> <param> <key>alias</key> @@ -403,16 +740,31 @@ <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>_coordinate</key> + <value>(800, 1008)</value> </param> <param> - <key>maxoutbuf</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> + <param> + <key>id</key> + <value>virtual_sink_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>stream_id</key> + <value>observation</value> + </param> <param> <key>_coordinate</key> - <value>(58, 486)</value> + <value>(608, 1076)</value> </param> <param> <key>_rotation</key> @@ -420,24 +772,32 @@ </param> </block> <block> - <key>blocks_short_to_float</key> + <key>fir_filter_xxx</key> <param> <key>id</key> - <value>blocks_short_to_float_1_0</value> + <value>fir_filter_xxx_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>type</key> + <value>fff</value> </param> <param> - <key>scale</key> + <key>decim</key> <value>1</value> </param> <param> + <key>taps</key> + <value>fu.c_channel</value> + </param> + <param> + <key>samp_delay</key> + <value>0</value> + </param> + <param> <key>alias</key> <value></value> </param> @@ -455,7 +815,7 @@ </param> <param> <key>_coordinate</key> - <value>(376, 498)</value> + <value>(904, 613)</value> </param> <param> <key>_rotation</key> @@ -463,10 +823,10 @@ </param> </block> <block> - <key>trellis_metrics_x</key> + <key>blocks_add_xx</key> <param> <key>id</key> - <value>trellis_metrics_x_0</value> + <value>blocks_add_xx_1</value> </param> <param> <key>_enabled</key> @@ -474,25 +834,17 @@ </param> <param> <key>type</key> - <value>f</value> + <value>float</value> </param> <param> - <key>card</key> - <value>8</value> + <key>num_inputs</key> + <value>2</value> </param> <param> - <key>dim</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>table</key> - <value>-7, -5, -3, -1, 1, 3, 5, 7</value> - </param> - <param> - <key>metric_type</key> - <value>digital.TRELLIS_EUCLIDEAN</value> - </param> - <param> <key>alias</key> <value></value> </param> @@ -510,7 +862,7 @@ </param> <param> <key>_coordinate</key> - <value>(63, 328)</value> + <value>(688, 944)</value> </param> <param> <key>_rotation</key> @@ -525,7 +877,7 @@ </param> <param> <key>_enabled</key> - <value>True</value> + <value>False</value> </param> <param> <key>in_type</key> @@ -537,11 +889,11 @@ </param> <param> <key>symbol_table</key> - <value>-7,-5,-3,-1,1,3,5,7</value> + <value>tot_mod[1]</value> </param> <param> <key>dimension</key> - <value>1</value> + <value>tot_mod[0]</value> </param> <param> <key>num_ports</key> @@ -565,7 +917,7 @@ </param> <param> <key>_coordinate</key> - <value>(607, 175)</value> + <value>(944, 461)</value> </param> <param> <key>_rotation</key> @@ -592,7 +944,7 @@ </param> <param> <key>amp</key> - <value>noisevar</value> + <value>noisevar**0.5</value> </param> <param> <key>seed</key> @@ -616,7 +968,7 @@ </param> <param> <key>_coordinate</key> - <value>(606, 242)</value> + <value>(288, 958)</value> </param> <param> <key>_rotation</key> @@ -624,213 +976,198 @@ </param> </block> <block> - <key>qtgui_number_sink</key> + <key>trellis_metrics_x</key> <param> <key>id</key> - <value>qtgui_number_sink_0</value> + <value>trellis_metrics_x_0</value> </param> <param> <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>name</key> - <value>""</value> + <value>False</value> </param> <param> <key>type</key> - <value>float</value> - </param> - <param> - <key>autoscale</key> - <value>False</value> + <value>f</value> </param> <param> - <key>avg</key> - <value>0.001</value> + <key>card</key> + <value>fsm.O()</value> </param> <param> - <key>graph_type</key> - <value>qtgui.NUM_GRAPH_HORIZ</value> + <key>dim</key> + <value>tot_mod[0]</value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>table</key> + <value>tot_mod[1]</value> </param> <param> - <key>min</key> - <value>0</value> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> </param> <param> - <key>max</key> - <value>1</value> + <key>alias</key> + <value></value> </param> <param> - <key>update_time</key> - <value>0.10</value> + <key>affinity</key> + <value></value> </param> <param> - <key>gui_hint</key> - <value>1,0,1,1</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>label1</key> - <value></value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>unit1</key> - <value></value> + <key>_coordinate</key> + <value>(272, 1271)</value> </param> <param> - <key>color1</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable_slider</key> <param> - <key>factor1</key> - <value>1</value> + <key>id</key> + <value>EsN0_dB</value> </param> <param> - <key>label2</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit2</key> - <value></value> + <key>label</key> + <value>Es/N0 (dB)</value> </param> <param> - <key>color2</key> - <value>("black", "black")</value> + <key>value</key> + <value>20.0</value> </param> <param> - <key>factor2</key> - <value>1</value> + <key>min</key> + <value>-10</value> </param> <param> - <key>label3</key> - <value></value> + <key>max</key> + <value>30</value> </param> <param> - <key>unit3</key> - <value></value> + <key>num_steps</key> + <value>1000</value> </param> <param> - <key>color3</key> - <value>("black", "black")</value> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> </param> <param> - <key>factor3</key> - <value>1</value> + <key>converver</key> + <value>float_converter</value> </param> <param> - <key>label4</key> + <key>grid_pos</key> <value></value> </param> <param> - <key>unit4</key> + <key>notebook</key> <value></value> </param> <param> - <key>color4</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor4</key> - <value>1</value> - </param> - <param> - <key>label5</key> + <key>alias</key> <value></value> </param> <param> - <key>unit5</key> - <value></value> + <key>_coordinate</key> + <value>(728, 105)</value> </param> <param> - <key>color5</key> - <value>("black", "black")</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_throttle</key> <param> - <key>factor5</key> - <value>1</value> + <key>id</key> + <value>blocks_throttle_0</value> </param> <param> - <key>label6</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>unit6</key> - <value></value> + <key>type</key> + <value>byte</value> </param> <param> - <key>color6</key> - <value>("black", "black")</value> + <key>samples_per_second</key> + <value>R</value> </param> <param> - <key>factor6</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>label7</key> - <value></value> + <key>ignoretag</key> + <value>True</value> </param> <param> - <key>unit7</key> + <key>alias</key> <value></value> </param> <param> - <key>color7</key> - <value>("black", "black")</value> - </param> - <param> - <key>factor7</key> - <value>1</value> - </param> - <param> - <key>label8</key> + <key>affinity</key> <value></value> </param> <param> - <key>unit8</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>color8</key> - <value>("black", "black")</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>factor8</key> - <value>1</value> + <key>_coordinate</key> + <value>(240, 580)</value> </param> <param> - <key>label9</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> <param> - <key>unit9</key> - <value></value> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0_0</value> </param> <param> - <key>color9</key> - <value>("black", "black")</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>factor9</key> - <value>1</value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>label10</key> - <value></value> + <key>out_type</key> + <value>float</value> </param> <param> - <key>unit10</key> - <value></value> + <key>symbol_table</key> + <value>modulation[1]</value> </param> <param> - <key>color10</key> - <value>("black", "black")</value> + <key>dimension</key> + <value>modulation[0]</value> </param> <param> - <key>factor10</key> + <key>num_ports</key> <value>1</value> </param> <param> @@ -842,8 +1179,16 @@ <value></value> </param> <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(609, 482)</value> + <value>(672, 613)</value> </param> <param> <key>_rotation</key> @@ -851,69 +1196,88 @@ </param> </block> <block> - <key>variable_qtgui_range</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>snr_db</value> + <value>virtual_sink_0_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>SNR (dB)</value> + <key>stream_id</key> + <value>estimate</value> </param> <param> - <key>value</key> - <value>5</value> + <key>_coordinate</key> + <value>(944, 1436)</value> </param> <param> - <key>start</key> - <value>-10</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>trellis_viterbi_x</key> <param> - <key>stop</key> - <value>10</value> + <key>id</key> + <value>trellis_viterbi_x_0</value> </param> <param> - <key>step</key> - <value>0.01</value> + <key>_enabled</key> + <value>False</value> </param> <param> - <key>widget</key> - <value>counter_slider</value> + <key>type</key> + <value>b</value> </param> <param> - <key>orient</key> - <value>Qt.Horizontal</value> + <key>fsm_args</key> + <value>fsm</value> </param> <param> - <key>min_len</key> - <value>200</value> + <key>block_size</key> + <value>block/bpsym</value> </param> <param> - <key>gui_hint</key> - <value></value> + <key>init_state</key> + <value>-1</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> </param> <param> <key>alias</key> <value></value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(177, 10)</value> + <value>(480, 1271)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> - <key>trellis_sccc_encoder_xx</key> + <key>trellis_viterbi_combined_xx</key> <param> <key>id</key> - <value>trellis_sccc_encoder_xx_0</value> + <value>trellis_viterbi_combined_xx_0</value> </param> <param> <key>_enabled</key> @@ -921,31 +1285,78 @@ </param> <param> <key>type</key> - <value>ss</value> + <value>f</value> </param> <param> - <key>o_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> + <key>out_type</key> + <value>b</value> </param> <param> - <key>o_init_state</key> + <key>fsm_args</key> + <value>fsm</value> + </param> + <param> + <key>block_size</key> + <value>block/bpsym</value> + </param> + <param> + <key>init_state</key> + <value>-1</value> + </param> + <param> + <key>final_state</key> + <value>-1</value> + </param> + <param> + <key>dim</key> + <value>tot_mod[0]</value> + </param> + <param> + <key>table</key> + <value>tot_mod[1]</value> + </param> + <param> + <key>metric_type</key> + <value>digital.TRELLIS_EUCLIDEAN</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>i_fsm_args</key> - <value>prefix+"/awgn2o3_4.fsm"</value> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(352, 1410)</value> </param> <param> - <key>i_init_state</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_unpack_k_bits_bb</key> <param> - <key>interleaver_args</key> - <value>trellis.interleaver(block,666)</value> + <key>id</key> + <value>blocks_unpack_k_bits_bb_0</value> </param> <param> - <key>bl</key> - <value>block</value> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>k</key> + <value>bpsym</value> </param> <param> <key>alias</key> @@ -965,7 +1376,7 @@ </param> <param> <key>_coordinate</key> - <value>(294, 154)</value> + <value>(728, 1364)</value> </param> <param> <key>_rotation</key> @@ -973,58 +1384,65 @@ </param> </block> <block> - <key>trellis_sccc_decoder_x</key> + <key>blocks_pack_k_bits_bb</key> <param> <key>id</key> - <value>trellis_sccc_decoder_x_0</value> + <value>blocks_pack_k_bits_bb_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>out_type</key> - <value>s</value> + <key>k</key> + <value>bpsym</value> </param> <param> - <key>o_fsm_args</key> - <value>prefix+"/awgn1o2_4.fsm"</value> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> </param> <param> - <key>o_init_state</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>o_final_state</key> - <value>-1</value> + <key>maxoutbuf</key> + <value>0</value> </param> <param> - <key>i_fsm_args</key> - <value>prefix+"/awgn2o3_4.fsm"</value> + <key>_coordinate</key> + <value>(456, 572)</value> </param> <param> - <key>i_init_state</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>trellis_encoder_xx</key> <param> - <key>i_final_state</key> - <value>-1</value> + <key>id</key> + <value>trellis_encoder_xx_0</value> </param> <param> - <key>interleaver</key> - <value>trellis.interleaver(block,666)</value> + <key>_enabled</key> + <value>False</value> </param> <param> - <key>block_size</key> - <value>block</value> + <key>type</key> + <value>bs</value> </param> <param> - <key>iterations</key> - <value>10</value> + <key>fsm_args</key> + <value>fsm</value> </param> <param> - <key>siso_type</key> - <value>trellis.TRELLIS_MIN_SUM</value> + <key>init_state</key> + <value>0</value> </param> <param> <key>alias</key> @@ -1044,7 +1462,7 @@ </param> <param> <key>_coordinate</key> - <value>(292, 280)</value> + <value>(672, 461)</value> </param> <param> <key>_rotation</key> @@ -1052,44 +1470,80 @@ </param> </block> <connection> - <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>blks2_error_rate_0</source_block_id> + <sink_block_id>wxgui_numbersink2_3_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_0</source_block_id> + <sink_block_id>blks2_error_rate_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_metrics_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>trellis_metrics_x_0</source_block_id> + <sink_block_id>trellis_viterbi_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>trellis_viterbi_combined_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> <source_block_id>analog_random_source_x_0</source_block_id> - <sink_block_id>trellis_sccc_encoder_xx_0</sink_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_sccc_encoder_xx_0</source_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> <source_block_id>blocks_add_xx_1</source_block_id> - <sink_block_id>trellis_metrics_x_0</sink_block_id> + <sink_block_id>blocks_null_sink_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_metrics_x_0</source_block_id> - <sink_block_id>trellis_sccc_decoder_x_0</sink_block_id> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>trellis_sccc_decoder_x_0</source_block_id> - <sink_block_id>blocks_sub_xx_0</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> + <sink_block_id>fir_filter_xxx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> + <source_block_id>fir_filter_xxx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> @@ -1100,32 +1554,44 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_noise_source_x_0</source_block_id> - <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_block_id>trellis_encoder_xx_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_pack_k_bits_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>blocks_pack_k_bits_bb_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_unpack_k_bits_bb_0</source_block_id> + <sink_block_id>virtual_sink_0_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_sub_xx_0</source_block_id> - <sink_block_id>blocks_multiply_xx_2_0</sink_block_id> + <source_block_id>trellis_viterbi_x_0</source_block_id> + <sink_block_id>blocks_unpack_k_bits_bb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_2_0</source_block_id> - <sink_block_id>blocks_short_to_float_1_0</sink_block_id> + <source_block_id>trellis_viterbi_combined_xx_0</source_block_id> + <sink_block_id>blocks_unpack_k_bits_bb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_short_to_float_1_0</source_block_id> - <sink_block_id>qtgui_number_sink_0</sink_block_id> + <source_block_id>blocks_pack_k_bits_bb_0</source_block_id> + <sink_block_id>trellis_encoder_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-trellis/examples/python/CMakeLists.txt b/gr-trellis/examples/python/CMakeLists.txt index e2c7e70ff7..8a05525bc4 100644 --- a/gr-trellis/examples/python/CMakeLists.txt +++ b/gr-trellis/examples/python/CMakeLists.txt @@ -21,18 +21,8 @@ include(GrPython) GR_PYTHON_INSTALL( PROGRAMS - fsm_utils.py test_tcm.py - test_tcm_parallel.py - test_tcm_combined.py - test_sccc_hard.py - test_sccc_soft.py - test_sccc_turbo.py - test_viterbi_equalization1.py - test_viterbi_equalization.py - test_turbo_equalization.py - test_turbo_equalization1.py - test_turbo_equalization2.py + test_cpm.py DESTINATION ${GR_PKG_TRELLIS_EXAMPLES_DIR} COMPONENT "trellis_examples" ) @@ -45,20 +35,38 @@ install( install( FILES + fsm_files/awgn1o1_16rsc.fsm + fsm_files/awgn1o1_4rsc.fsm fsm_files/awgn1o2_128.fsm fsm_files/awgn1o2_16.fsm + fsm_files/awgn1o2_16rsc.fsm fsm_files/awgn1o2_4.fsm + fsm_files/awgn1o2_4rsc.fsm fsm_files/awgn1o2_8.fsm fsm_files/awgn2o3_16.fsm + fsm_files/awgn2o3_16ungerboecka.fsm + fsm_files/awgn2o3_16ungerboeck.fsm + fsm_files/awgn2o3_32ungerboecka.fsm + fsm_files/awgn2o3_32ungerboeck.fsm fsm_files/awgn2o3_4.fsm fsm_files/awgn2o3_4_msb.fsm fsm_files/awgn2o3_4_msbG.fsm + fsm_files/awgn2o3_4ungerboecka.fsm + fsm_files/awgn2o3_4ungerboeck.fsm + fsm_files/awgn2o3_64ungerboecka.fsm + fsm_files/awgn2o3_64ungerboeck.fsm fsm_files/awgn2o3_8.fsm + fsm_files/awgn2o3_8ungerboecka.fsm + fsm_files/awgn2o3_8ungerboeck.fsm fsm_files/awgn2o4_4.fsm fsm_files/disconnected.fsm + fsm_files/irregular.fsm + fsm_files/joint_16_16.fsm + fsm_files/joint_4_16.fsm fsm_files/rep3.fsm fsm_files/rep5.fsm fsm_files/simple.fsm + fsm_files/uncoded4.fsm DESTINATION ${GR_PKG_TRELLIS_EXAMPLES_DIR}/fsm_files COMPONENT "trellis_examples" ) diff --git a/gr-trellis/examples/python/README b/gr-trellis/examples/python/README index 155b0a9416..8b4e0f0abb 100644 --- a/gr-trellis/examples/python/README +++ b/gr-trellis/examples/python/README @@ -2,8 +2,6 @@ Here we have several test programs for use with the gr-trellis implementation. Documentation can be found in http://gnuradio.org/doc/doxygen/group__trellis__coding__blk.html -fsm_utils.py contains several useful functions. - fsm_files is a directory with some FSM definitions If you just want to see what these programs do run them; @@ -26,10 +24,12 @@ which gives you information about the: number of transmitted packets number of packets in error estimated packet error rate -number of transmitted shorts (or symbols, or bits, depending on the specific program) -number of shorts (or symbols, or bits) in error -estimated short (or symbol, or bit) error rate +number of transmitted symbols, or bits, depending on the specific program +number of symbols, or bits in error +estimated symbol, or bit error rate for instance, the final number 1.10e-03 is the error rate estimate by sending 1000 packets of 1024 shorts each, using an 1/2 4-state convolutional code and QPSK modulation through an AWGN with Es/N0 = 6.0 dB + +There is a similar example in the ../grc/ directory diff --git a/gr-trellis/examples/python/fsm_files/awgn1o1_16rsc.fsm b/gr-trellis/examples/python/fsm_files/awgn1o1_16rsc.fsm new file mode 100644 index 0000000000..f82d6052c2 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn1o1_16rsc.fsm @@ -0,0 +1,40 @@ +2 16 2 + +0 8 +8 0 +1 9 +9 1 +2 10 +10 2 +3 11 +11 3 +12 4 +4 12 +13 5 +5 13 +14 6 +6 14 +15 7 +7 15 + + +0 1 +0 1 +1 0 +1 0 +1 0 +1 0 +0 1 +0 1 +1 0 +1 0 +0 1 +0 1 +0 1 +0 1 +1 0 +1 0 + +Recursive Systematic Codes(RSC) +GM1o2_16rsc=[1, 1+D+D^4/1+D^2+D^3+D^4] = [1, 27/31] (in decimal); + diff --git a/gr-trellis/examples/python/fsm_files/awgn1o1_4rsc.fsm b/gr-trellis/examples/python/fsm_files/awgn1o1_4rsc.fsm new file mode 100644 index 0000000000..d5e7fe31ba --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn1o1_4rsc.fsm @@ -0,0 +1,16 @@ +2 4 2 + +0 2 +2 0 +1 3 +3 1 + +0 1 +0 1 +1 0 +1 0 + + +Recursive Systematic Codes(RSC) +GM1o2_4rsc=[1, 1+D+D^2/1+D^2] = [1, 7/5] (in decimal); +without the systematic bit diff --git a/gr-trellis/examples/python/fsm_files/awgn1o2_16rsc.fsm b/gr-trellis/examples/python/fsm_files/awgn1o2_16rsc.fsm new file mode 100644 index 0000000000..ccf1f1d4b1 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn1o2_16rsc.fsm @@ -0,0 +1,40 @@ +2 16 4 + +0 8 +8 0 +1 9 +9 1 +2 10 +10 2 +3 11 +11 3 +12 4 +4 12 +13 5 +5 13 +14 6 +6 14 +15 7 +7 15 + + +0 3 +0 3 +1 2 +1 2 +1 2 +1 2 +0 3 +0 3 +1 2 +1 2 +0 3 +0 3 +0 3 +0 3 +1 2 +1 2 + +Recursive Systematic Codes(RSC) +GM1o2_16rsc=[1, 1+D+D^4/1+D^2+D^3+D^4] = [1, 27/31] (in decimal); + diff --git a/gr-trellis/examples/python/fsm_files/awgn1o2_4rsc.fsm b/gr-trellis/examples/python/fsm_files/awgn1o2_4rsc.fsm new file mode 100644 index 0000000000..adb500a217 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn1o2_4rsc.fsm @@ -0,0 +1,14 @@ +2 4 4 + +0 2 +2 0 +1 3 +3 1 + +0 3 +0 3 +1 2 +1 2 + +Recursive Systematic Codes(RSC) +GM1o2_4rsc=[1, 1+D+D^2/1+D^2] = [1, 7/5] (in decimal); diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_16ungerboeck.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_16ungerboeck.fsm new file mode 100644 index 0000000000..70ead4f17a --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_16ungerboeck.fsm @@ -0,0 +1,50 @@ +4 16 8
+
+0 1 2 3
+4 5 6 7
+8 9 10 11
+12 13 14 15
+0 1 2 3
+4 5 6 7
+8 9 10 11
+12 13 14 15
+0 1 2 3
+4 5 6 7
+8 9 10 11
+12 13 14 15
+0 1 2 3
+4 5 6 7
+8 9 10 11
+12 13 14 15
+
+
+0 4 2 6
+1 5 3 7
+4 0 6 2
+5 1 7 3
+2 6 0 4
+3 7 1 5
+6 2 4 0
+7 3 5 1
+4 0 6 2
+5 1 7 3
+0 4 2 6
+1 5 3 7
+6 2 4 0
+7 3 5 1
+2 6 0 4
+3 7 1 5
+
+This is the rate 2/3 Ungerboeck code with 16 states for 8-PSK (natural mapping).
+The states are defined in Ungerboeck's way.
+
+d_free^2 = 2.274^2 Es --> 7.13 dB (so gain of 4.13 dB over uncoded QPSK)
+
+Parity check matrix in octal: [16 04 23]
+
+Generator Matrix:
+
+[ D 1+D+D^2 0
+ 1+D^2 D^2 D]
+
+
diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_16ungerboecka.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_16ungerboecka.fsm new file mode 100644 index 0000000000..523384362f --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_16ungerboecka.fsm @@ -0,0 +1,48 @@ +4 16 8
+
+0 8 2 10
+0 8 2 10
+1 9 3 11
+1 9 3 11
+0 8 2 10
+0 8 2 10
+1 9 3 11
+1 9 3 11
+4 12 6 14
+4 12 6 14
+5 13 7 15
+5 13 7 15
+4 12 6 14
+4 12 6 14
+5 13 7 15
+5 13 7 15
+
+
+0 6 2 4
+2 4 0 6
+6 0 4 2
+4 2 6 0
+4 2 6 0
+6 0 4 2
+2 4 0 6
+0 6 2 4
+1 7 3 5
+3 5 1 7
+7 1 5 3
+5 3 7 1
+5 3 7 1
+7 1 5 3
+3 5 1 7
+1 7 3 5
+
+This is the rate 2/3 Ungerboeck code with 16 states for 8-PSK (natural mapping).
+The states are defined in typical way.
+
+d_free^2 = 2.274^2Es --> 7.13 dB (so gain of 4.13 dB over uncoded QPSK)
+
+Parity check matrix in octal: [16 04 23]
+
+Generator Matrix:
+
+[ D 1+D+D^2 0
+ 1+D^2 D^2 D]
diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_32ungerboeck.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_32ungerboeck.fsm new file mode 100644 index 0000000000..a00f9c2e8d --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_32ungerboeck.fsm @@ -0,0 +1,83 @@ +4 32 8
+
+0 16 1 17
+0 16 1 17
+0 16 1 17
+0 16 1 17
+2 18 3 19
+2 18 3 19
+2 18 3 19
+2 18 3 19
+4 20 5 21
+4 20 5 21
+4 20 5 21
+4 20 5 21
+6 22 7 23
+6 22 7 23
+6 22 7 23
+6 22 7 23
+8 24 9 25
+8 24 9 25
+8 24 9 25
+8 24 9 25
+10 26 11 27
+10 26 11 27
+10 26 11 27
+10 26 11 27
+12 28 13 29
+12 28 13 29
+12 28 13 29
+12 28 13 29
+14 30 15 31
+14 30 15 31
+14 30 15 31
+14 30 15 31
+
+
+
+
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+5 1 7 3
+1 5 3 7
+7 3 5 1
+3 7 1 5
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+4 0 6 2
+0 4 2 6
+6 2 4 0
+2 6 0 4
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+4 0 6 2
+0 4 2 6
+6 2 4 0
+2 6 0 4
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+5 1 7 3
+1 5 3 7
+7 3 5 1
+3 7 1 5
+
+This is the rate 2/3 Ungerboeck code with 32 states for 8-PSK (natural mapping).
+The states are defined in typical way.
+
+d_free^2 = 2.405^2 Es --> 7.59 dB (so gain of 4.59 dB over uncoded QPSK)
+
+Parity check matrix in octal: [34 16 45]
+
+Generator Matrix:
+
+[ 1 D 0
+ D^4 D^2+1 D^3+D^2+D]
+
diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_32ungerboecka.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_32ungerboecka.fsm new file mode 100644 index 0000000000..b2e6ebdf44 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_32ungerboecka.fsm @@ -0,0 +1,84 @@ +4 32 8
+0 16 1 17
+0 16 1 17
+0 16 1 17
+0 16 1 17
+2 18 3 19
+2 18 3 19
+2 18 3 19
+2 18 3 19
+4 20 5 21
+4 20 5 21
+4 20 5 21
+4 20 5 21
+6 22 7 23
+6 22 7 23
+6 22 7 23
+6 22 7 23
+8 24 9 25
+8 24 9 25
+8 24 9 25
+8 24 9 25
+10 26 11 27
+10 26 11 27
+10 26 11 27
+10 26 11 27
+12 28 13 29
+12 28 13 29
+12 28 13 29
+12 28 13 29
+14 30 15 31
+14 30 15 31
+14 30 15 31
+14 30 15 31
+
+
+
+
+
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+3 7 1 5
+7 3 5 1
+1 5 3 7
+5 1 7 3
+2 6 0 4
+6 2 4 0
+0 4 2 6
+4 0 6 2
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+2 6 0 4
+6 2 4 0
+0 4 2 6
+4 0 6 2
+3 7 1 5
+7 3 5 1
+1 5 3 7
+5 1 7 3
+
+This is the rate 2/3 Ungerboeck code with 32 states for 8-PSK (natural mapping).
+The states are defined in typical way.
+
+d_free^2 = 2.405^2 Es --> 7.59 dB (so gain of 4.59 dB over uncoded QPSK)
+
+Parity check matrix in octal: [34 16 45]
+
+Generator Matrix:
+
+[ 1 D 0
+ D^4+D 1 D^3+D^2+D]
+
+
diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_4_msb.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_4_msb.fsm index d834c52718..ff6e2a763b 100644 --- a/gr-trellis/examples/python/fsm_files/awgn2o3_4_msb.fsm +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_4_msb.fsm @@ -12,7 +12,7 @@ This is generated by the 1/2 AWGN code (5 7) operated twice, ie, -(xk+1 xki) [xk-1 xk-2] -> [xk+1 xki]. +(xk+1 xk) [xk-1 xk-2] -> [xk+1 xk]. We also puncture the first (MSB) bit. This code is worse than awgn2o3_4_msbG and slightly worse than awgn2o3_4, BUT seems to be a good innner code for sctcm (with 8PSK natural). diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_4_msbG.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_4_msbG.fsm index 8956c53da2..54f9cbc3cc 100644 --- a/gr-trellis/examples/python/fsm_files/awgn2o3_4_msbG.fsm +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_4_msbG.fsm @@ -11,7 +11,7 @@ This is generated by the 1/2 AWGN code (5 7) operated twice, ie, -(xk+1 xki) [xk-1 xk-2] -> [xk+1 xki]. +(xk+1 xk) [xk-1 xk-2] -> [xk+1 xk]. We also puncture the first (MSB) bit and Gray map the symbols. intermediate states: @@ -45,7 +45,7 @@ and in decimal: After Gray mapping: label -> phase 0 -> 0 -1 -> 0 +1 -> 1 2 -> 7 3 -> 2 4 -> 5 diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_4ungerboeck.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_4ungerboeck.fsm new file mode 100644 index 0000000000..160f4ea30f --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_4ungerboeck.fsm @@ -0,0 +1,26 @@ +4 4 8 + +0 0 1 1 +2 2 3 3 +0 0 1 1 +2 2 3 3 + + +0 4 2 6 +1 5 3 7 +2 6 0 4 +3 7 1 5 + + + +This is the Ungerboeck code for 8-PSK (natural mapping). +The states are defined in Ungerboeck's way. + +d_free^2=4 Es -> 3.0 dB over uncoded QPSK + +Parity check matrix in octal: [0 2 5] + +Generator matrix: + +[1 0 0 + 0 1+D^2 D] diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_4ungerboecka.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_4ungerboecka.fsm new file mode 100644 index 0000000000..d9c210a0e9 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_4ungerboecka.fsm @@ -0,0 +1,23 @@ +4 4 8 + +0 2 0 2 +0 2 0 2 +1 3 1 3 +1 3 1 3 + +0 2 4 6 +2 0 6 4 +1 3 5 7 +3 1 7 5 + +This is the rate 2/3 Ungerboeck's code with 4 states. +The states are defined in typical way. + +d_free^2=4 Es -> 3.0 dB over uncoded QPSK + +Parity check matrix in octal: [0 2 5] + +Generator matrix: + +[1 0 0 + 0 1+D^2 D] diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_64ungerboeck.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_64ungerboeck.fsm new file mode 100644 index 0000000000..62c75c31c1 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_64ungerboeck.fsm @@ -0,0 +1,150 @@ +4 64 8
+
+
+0 32 1 33
+0 32 1 33
+0 32 1 33
+0 32 1 33
+2 34 3 35
+2 34 3 35
+2 34 3 35
+2 34 3 35
+4 36 5 37
+4 36 5 37
+4 36 5 37
+4 36 5 37
+6 38 7 39
+6 38 7 39
+6 38 7 39
+6 38 7 39
+8 40 9 41
+8 40 9 41
+8 40 9 41
+8 40 9 41
+10 42 11 43
+10 42 11 43
+10 42 11 43
+10 42 11 43
+12 44 13 45
+12 44 13 45
+12 44 13 45
+12 44 13 45
+14 46 15 47
+14 46 15 47
+14 46 15 47
+14 46 15 47
+16 48 17 49
+16 48 17 49
+16 48 17 49
+16 48 17 49
+18 50 19 51
+18 50 19 51
+18 50 19 51
+18 50 19 51
+20 52 21 53
+20 52 21 53
+20 52 21 53
+20 52 21 53
+22 54 23 55
+22 54 23 55
+22 54 23 55
+22 54 23 55
+24 56 25 57
+24 56 25 57
+24 56 25 57
+24 56 25 57
+26 58 27 59
+26 58 27 59
+26 58 27 59
+26 58 27 59
+28 60 29 61
+28 60 29 61
+28 60 29 61
+28 60 29 61
+30 62 31 63
+30 62 31 63
+30 62 31 63
+30 62 31 63
+
+
+
+
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+3 7 1 5
+7 3 5 1
+1 5 3 7
+5 1 7 3
+2 6 0 4
+6 2 4 0
+0 4 2 6
+4 0 6 2
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+2 6 0 4
+6 2 4 0
+0 4 2 6
+4 0 6 2
+3 7 1 5
+7 3 5 1
+1 5 3 7
+5 1 7 3
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+2 6 0 4
+6 2 4 0
+0 4 2 6
+4 0 6 2
+3 7 1 5
+7 3 5 1
+1 5 3 7
+5 1 7 3
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+3 7 1 5
+7 3 5 1
+1 5 3 7
+5 1 7 3
+2 6 0 4
+6 2 4 0
+0 4 2 6
+4 0 6 2
+
+
+This is the rate 2/3 Ungerboeck code with 64 states for 8-PSK (natural mapping).
+The states are defined in typical way.
+
+d_free^2 = 2.52^2 Es --> 8.01 dB (so gain of 5.01 dB over uncoded QPSK)
+
+parity check matrix in octal: [074 036 105]
+
+generator matrix:
+
+[1 D 0
+ D^5 D^2+1 D^4+D^3+D^2+D]
+
+
diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_64ungerboecka.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_64ungerboecka.fsm new file mode 100644 index 0000000000..137091f1f6 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_64ungerboecka.fsm @@ -0,0 +1,154 @@ +4 64 8
+
+
+0 32 1 33
+0 32 1 33
+0 32 1 33
+0 32 1 33
+2 34 3 35
+2 34 3 35
+2 34 3 35
+2 34 3 35
+4 36 5 37
+4 36 5 37
+4 36 5 37
+4 36 5 37
+6 38 7 39
+6 38 7 39
+6 38 7 39
+6 38 7 39
+8 40 9 41
+8 40 9 41
+8 40 9 41
+8 40 9 41
+10 42 11 43
+10 42 11 43
+10 42 11 43
+10 42 11 43
+12 44 13 45
+12 44 13 45
+12 44 13 45
+12 44 13 45
+14 46 15 47
+14 46 15 47
+14 46 15 47
+14 46 15 47
+16 48 17 49
+16 48 17 49
+16 48 17 49
+16 48 17 49
+18 50 19 51
+18 50 19 51
+18 50 19 51
+18 50 19 51
+20 52 21 53
+20 52 21 53
+20 52 21 53
+20 52 21 53
+22 54 23 55
+22 54 23 55
+22 54 23 55
+22 54 23 55
+24 56 25 57
+24 56 25 57
+24 56 25 57
+24 56 25 57
+26 58 27 59
+26 58 27 59
+26 58 27 59
+26 58 27 59
+28 60 29 61
+28 60 29 61
+28 60 29 61
+28 60 29 61
+30 62 31 63
+30 62 31 63
+30 62 31 63
+30 62 31 63
+
+
+
+
+
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+5 1 7 3
+1 5 3 7
+7 3 5 1
+3 7 1 5
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+4 0 6 2
+0 4 2 6
+6 2 4 0
+2 6 0 4
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+4 0 6 2
+0 4 2 6
+6 2 4 0
+2 6 0 4
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+5 1 7 3
+1 5 3 7
+7 3 5 1
+3 7 1 5
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+4 0 6 2
+0 4 2 6
+6 2 4 0
+2 6 0 4
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+5 1 7 3
+1 5 3 7
+7 3 5 1
+3 7 1 5
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+5 1 7 3
+1 5 3 7
+7 3 5 1
+3 7 1 5
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+4 0 6 2
+0 4 2 6
+6 2 4 0
+2 6 0 4
+
+
+
+
+
+This is the rate 2/3 Ungerboeck code with 64 states for 8-PSK (natural mapping).
+The states are defined in typical way.
+
+d_free^2 = 2.52^2 Es --> 8.01 dB (so gain of 5.01 dB over uncoded QPSK)
+
+parity check matrix in octal: [074 036 105]
+
+generator matrix:
+
+[1 D 0
+ D^5+D 1 D^4+D^3+D^2+D]
+
+
diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_8.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_8.fsm index 34deeb68cb..6ace4f5e14 100644 --- a/gr-trellis/examples/python/fsm_files/awgn2o3_8.fsm +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_8.fsm @@ -21,5 +21,6 @@ -This is generated by the 1/2 8-state AWGN code (15 17) by puncturing the fourth bit. +This is generated by the 1/2 8-state AWGN code (15 17) by operating it twice and +puncturing the fourth bit. --> d_free=??? diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_8ungerboeck.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_8ungerboeck.fsm new file mode 100644 index 0000000000..e2f08eba25 --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_8ungerboeck.fsm @@ -0,0 +1,35 @@ +4 8 8 + +0 1 2 3 +4 5 6 7 +0 1 2 3 +4 5 6 7 +0 1 2 3 +4 5 6 7 +0 1 2 3 +4 5 6 7 + + +0 4 2 6 +1 5 3 7 +4 0 6 2 +5 1 7 3 +2 6 0 4 +3 7 1 5 +6 2 4 0 +7 3 5 1 + + + +This is the rate 2/3 Ungerboeck code with 8-states for 8-PSK (natural mapping). +The states are defined in Ungerboeck's way. + +d_free^2 = 4.585 Es --> 6.6 dB (so gain of 3.6 dB over uncoded QPSK) + +Parity check matrix in octal: [04 02 11] + +Generator Matrix: + +[ 1 D 0 + D^2 1 D] + diff --git a/gr-trellis/examples/python/fsm_files/awgn2o3_8ungerboecka.fsm b/gr-trellis/examples/python/fsm_files/awgn2o3_8ungerboecka.fsm new file mode 100644 index 0000000000..2425e6a01a --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/awgn2o3_8ungerboecka.fsm @@ -0,0 +1,32 @@ +4 8 8
+
+0 4 1 5
+0 4 1 5
+0 4 1 5
+0 4 1 5
+2 6 3 7
+2 6 3 7
+2 6 3 7
+2 6 3 7
+
+0 4 2 6
+4 0 6 2
+2 6 0 4
+6 2 4 0
+1 5 3 7
+5 1 7 3
+3 7 1 5
+7 3 5 1
+
+This is the rate 2/3 Ungerboeck code with 8-states for 8-PSK (natural mapping).
+The states are defined in typical way.
+
+d_free^2 = 4.585 Es --> 6.6 dB (so gain of 3.6 dB over uncoded QPSK)
+
+Parity check matrix in octal: [04 02 11]
+
+Generator Matrix:
+
+[ 1 D 0
+ D^2 1 D]
+
diff --git a/gr-trellis/examples/python/fsm_files/uncoded4.fsm b/gr-trellis/examples/python/fsm_files/uncoded4.fsm new file mode 100644 index 0000000000..67cb12ce8f --- /dev/null +++ b/gr-trellis/examples/python/fsm_files/uncoded4.fsm @@ -0,0 +1,7 @@ +4 1 4 + +0 0 0 0 + +0 1 2 3 + +uncoded 4-ary transmission diff --git a/gr-trellis/examples/python/test_cpm.py b/gr-trellis/examples/python/test_cpm.py index 3f5cfc4587..6fe25ec68c 100755 --- a/gr-trellis/examples/python/test_cpm.py +++ b/gr-trellis/examples/python/test_cpm.py @@ -12,8 +12,8 @@ from gnuradio import trellis, digital, filter, blocks from grc_gnuradio import blks2 as grc_blks2 import math import numpy -import fsm_utils from gnuradio import trellis +from gnuradio.trellis import fsm_utils try: from gnuradio import analog @@ -43,8 +43,9 @@ def run_test(seed,blocksize): f = trellis.fsm(P,M,L) # CPFSK signals - #p = numpy.ones(Q)/(2.0) - #q = numpy.cumsum(p)/(1.0*Q) + #p = numpy.ones(L*Q) + #q = numpy.cumsum(p) + #q = q/q[-1]/2.0; # GMSK signals BT=0.3; diff --git a/gr-trellis/examples/python/test_pccc_turbo1.py b/gr-trellis/examples/python/test_pccc_turbo1.py deleted file mode 100755 index 7104aa5039..0000000000 --- a/gr-trellis/examples/python/test_pccc_turbo1.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,seed): - tb = gr.top_block () - - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head (gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality - #src = blocks.vector_source_s([0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],False) - enc = trellis.pccc_encoder_ss(fo,0,fi,0,interleaver,K) - code = blocks.vector_sink_s() - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - metrics_in = trellis.metrics_f(fi.O()*fo.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner SISO - scale = blocks.multiply_const_ff(1.0/N0) - dec = trellis.pccc_decoder_s(fo,0,-1,fi,0,-1,interleaver,K,IT,trellis.TRELLIS_MIN_SUM) - - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - tb.connect (src,src_head,s2fsmi,enc,mod) - #tb.connect (src,enc,mod) - #tb.connect(enc,code) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,metrics_in,scale,dec,fsmi2s,dst) - - tb.run() - - #print code.data() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 5: - fname_out=args[0] - fname_in=args[1] - esn0_db=float(args[2]) # Es/No in dB - IT=int(args[3]) - rep=int(args[4]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_pccc_turbo.py fsm_name_1 fsm_fname_2 Es/No_db iterations repetitions\n') - sys.exit (1) - - # system parameters - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(fname_in) # get the innner FSM specification from a file - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - if fo.I() != fi.I(): - sys.stderr.write ('Incompatible input cardinality between two FSMs.\n') - sys.exit (1) - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - #modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations - dimensionality = 4 - constellation = [ 1, 0, 1, 0,\ - 1, 0,-1, 0,\ - 1, 0, 0, 1,\ - 1, 0, 0,-1,\ - -1, 0, 1, 0,\ - -1, 0,-1, 0,\ - -1, 0, 0, 1,\ - -1, 0, 0,-1,\ - 0, 1, 1, 0,\ - 0, 1,-1, 0,\ - 0, 1, 0, 1,\ - 0, 1, 0,-1,\ - 0,-1, 1, 0,\ - 0,-1,-1, 0,\ - 0,-1, 0, 1,\ - 0,-1, 0,-1,] # equivalent to 2 QPSK symbols - if len(constellation)/dimensionality != fi.O()*fo.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0): # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/examples/python/test_sccc_hard.py b/gr-trellis/examples/python/test_sccc_hard.py deleted file mode 100755 index 83393df4dc..0000000000 --- a/gr-trellis/examples/python/test_sccc_hard.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): - tb = gr.top_block () - - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality - enc_out = trellis.encoder_ss(fo,0) # initial state = 0 - inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - metrics_in = trellis.metrics_f(fi.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner Viterbi - va_in = trellis.viterbi_s(fi,K,0,-1) # Put -1 if the Initial/Final states are not set. - deinter = trellis.permutation(interleaver.K(),interleaver.DEINTER(),1,gr.sizeof_short) - metrics_out = trellis.metrics_s(fo.O(),1,[0,1,2,3],digital.TRELLIS_HARD_SYMBOL) # data preprocessing to generate metrics for outer Viterbi (hard decisions) - va_out = trellis.viterbi_s(fo,K,0,-1) # Put -1 if the Initial/Final states are not set. - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,metrics_in) - tb.connect (metrics_in,va_in,deinter,metrics_out,va_out,fsmi2s,dst) - - tb.run() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 4: - fname_out=args[0] - fname_in=args[1] - esn0_db=float(args[2]) # Es/No in dB - rep=int(args[3]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_name_out fsm_fname_in Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(fname_in) # get the innner FSM specification from a file - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/examples/python/test_sccc_soft.py b/gr-trellis/examples/python/test_sccc_soft.py deleted file mode 100755 index 25d26e0025..0000000000 --- a/gr-trellis/examples/python/test_sccc_soft.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): - tb = gr.top_block () - - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head (gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality - enc_out = trellis.encoder_ss(fo,0) # initial state = 0 - inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - metrics_in = trellis.metrics_f(fi.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner Viterbi - gnd = blocks.vector_source_f([0],True); - siso_in = trellis.siso_f(fi,K,0,-1,True,False,trellis.TRELLIS_MIN_SUM) # Put -1 if the Initial/Final states are not set. - deinter = trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) - va_out = trellis.viterbi_s(fo,K,0,-1) # Put -1 if the Initial/Final states are not set. - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,metrics_in) - tb.connect (gnd,(siso_in,0)) - tb.connect (metrics_in,(siso_in,1)) - tb.connect (siso_in,deinter,va_out,fsmi2s,dst) - - tb.run() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 4: - fname_out=args[0] - fname_in=args[1] - esn0_db=float(args[2]) # Es/No in dB - rep=int(args[3]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_name_out fsm_fname_in Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(fname_in) # get the innner FSM specification from a file - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/examples/python/test_sccc_turbo.py b/gr-trellis/examples/python/test_sccc_turbo.py deleted file mode 100755 index 08004e8a0d..0000000000 --- a/gr-trellis/examples/python/test_sccc_turbo.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def make_rx(tb,fo,fi,dimensionality,constellation,K,interleaver,IT,Es,N0,type): - metrics_in = trellis.metrics_f(fi.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner Viterbi - scale = blocks.multiply_const_ff(1.0/N0) - gnd = blocks.vector_source_f([0],True); - - inter=[] - deinter=[] - siso_in=[] - siso_out=[] - - # generate all blocks - for it in range(IT): - inter.append( trellis.permutation(interleaver.K(),interleaver.INTER(),fi.I(),gr.sizeof_float) ) - siso_in.append( trellis.siso_f(fi,K,0,-1,True,False,type) ) - deinter.append( trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) ) - if it < IT-1: - siso_out.append( trellis.siso_f(fo,K,0,-1,False,True,type) ) - else: - siso_out.append( trellis.viterbi_s(fo,K,0,-1) ) # no soft outputs needed - - # connect first stage - tb.connect (gnd,inter[0]) - tb.connect (metrics_in,scale) - tb.connect (scale,(siso_in[0],1)) - - # connect the rest - for it in range(IT): - if it < IT-1: - tb.connect (metrics_in,(siso_in[it+1],1)) - tb.connect (siso_in[it],deinter[it],(siso_out[it],1)) - tb.connect (gnd,(siso_out[it],0)) - tb.connect (siso_out[it],inter[it+1]) - tb.connect (inter[it],(siso_in[it],0)) - else: - tb.connect (siso_in[it],deinter[it],siso_out[it]) - tb.connect (inter[it],(siso_in[it],0)) - - return (metrics_in,siso_out[IT-1]) - - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,seed): - tb = gr.top_block () - - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality - enc_out = trellis.encoder_ss(fo,0) # initial state = 0 - inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - (head,tail) = make_rx(tb,fo,fi,dimensionality,constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_MIN_SUM) - #(head,tail) = make_rx(tb,fo,fi,dimensionality,constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_SUM_PRODUCT) - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,head) - tb.connect (tail,fsmi2s,dst) - - tb.run() - - #print enc_out.ST(), enc_in.ST() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 5: - fname_out=args[0] - fname_in=args[1] - esn0_db=float(args[2]) # Es/No in dB - IT=int(args[3]) - rep=int(args[4]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_sccc_turbo.py fsm_name_out fsm_fname_in Es/No_db iterations repetitions\n') - sys.exit (1) - - # system parameters - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(fname_in) # get the innner FSM specification from a file - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0): # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/examples/python/test_sccc_turbo1.py b/gr-trellis/examples/python/test_sccc_turbo1.py deleted file mode 100755 index 528a79d011..0000000000 --- a/gr-trellis/examples/python/test_sccc_turbo1.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,seed): - tb = gr.top_block () - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality - enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - dec = trellis.sccc_decoder_combined_fs(fo,0,-1,fi,0,-1,interleaver,K,IT,trellis.TRELLIS_MIN_SUM,dimensionality,constellation,digital.TRELLIS_EUCLIDEAN,1.0) - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - #tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) - tb.connect (src,src_head,s2fsmi,enc,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - #tb.connect (add,head) - #tb.connect (tail,fsmi2s,dst) - tb.connect (add,dec,fsmi2s,dst) - - tb.run() - - #print enc_out.ST(), enc_in.ST() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 5: - fname_out=args[0] - fname_in=args[1] - esn0_db=float(args[2]) # Es/No in dB - IT=int(args[3]) - rep=int(args[4]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_name_out fsm_fname_in Es/No_db iterations repetitions\n') - sys.exit (1) - - # system parameters - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(fname_in) # get the innner FSM specification from a file - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0): # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/examples/python/test_sccc_turbo2.py b/gr-trellis/examples/python/test_sccc_turbo2.py deleted file mode 100755 index d7f26c4e13..0000000000 --- a/gr-trellis/examples/python/test_sccc_turbo2.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,seed): - tb = gr.top_block () - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality - enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - metrics_in = trellis.metrics_f(fi.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner SISO - scale = blocks.multiply_const_ff(1.0/N0) - dec = trellis.sccc_decoder_s(fo,0,-1,fi,0,-1,interleaver,K,IT,trellis.TRELLIS_MIN_SUM) - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - #tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) - tb.connect (src,src_head,s2fsmi,enc,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - #tb.connect (add,head) - #tb.connect (tail,fsmi2s,dst) - tb.connect (add,metrics_in,scale,dec,fsmi2s,dst) - - tb.run() - - #print enc_out.ST(), enc_in.ST() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 5: - fname_out=args[0] - fname_in=args[1] - esn0_db=float(args[2]) # Es/No in dB - IT=int(args[3]) - rep=int(args[4]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_name_out fsm_fname_in Es/No_db iterations repetitions\n') - sys.exit (1) - - # system parameters - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(fname_in) # get the innner FSM specification from a file - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0): # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/examples/python/test_tcm.py b/gr-trellis/examples/python/test_tcm.py index bf9710aa1c..dfc565616e 100755 --- a/gr-trellis/examples/python/test_tcm.py +++ b/gr-trellis/examples/python/test_tcm.py @@ -6,9 +6,10 @@ from gnuradio import eng_notation import math import sys import random -import fsm_utils +from gnuradio.trellis import fsm_utils from gnuradio.eng_option import eng_option from optparse import OptionParser +import numpy try: from gnuradio import analog @@ -19,39 +20,32 @@ except ImportError: def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): tb = gr.top_block () - # TX - #packet = [0]*Kb - #for i in range(Kb-1*16): # last 16 bits = 0 to drive the final state to 0 - #packet[i] = random.randint(0, 1) # random 0s and 1s - #src = blocks.vector_source_s(packet,False) - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - #b2s = blocks.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts + numpy.random.seed(-seed) + packet = numpy.random.randint(0,2,Kb) # create Kb random bits + packet[Kb-10:Kb]=0 + packet[0:Kb]=0 + src = blocks.vector_source_s(packet.tolist(),False) + b2s = blocks.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) + noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),long(seed)) # RX - metrics = trellis.metrics_f(f.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi - va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. + va = trellis.viterbi_combined_fs(f,K,0,0,dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # Put -1 if the Initial/Final states are not set. fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - #s2b = blocks.packed_to_unpacked_ss(1,gr.GR_MSB_FIRST) # unpack shorts to bits - #dst = blocks.vector_sink_s(); - dst = blocks.check_lfsr_32k_s() + s2b = blocks.packed_to_unpacked_ss(1,gr.GR_MSB_FIRST) # unpack shorts to bits + dst = blocks.vector_sink_s(); - tb.connect (src,src_head,s2fsmi,enc,mod) - #tb.connect (src,b2s,s2fsmi,enc,mod) + tb.connect (src,b2s,s2fsmi,enc,mod) tb.connect (mod,(add,0)) tb.connect (noise,(add,1)) - tb.connect (add,metrics) - tb.connect (metrics,va,fsmi2s,dst) - #tb.connect (metrics,va,fsmi2s,s2b,dst) + tb.connect (add,va,fsmi2s,s2b,dst) tb.run() @@ -61,19 +55,11 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): # Then put it as the last argument in the viterbi block #print "final state = " , enc.ST() - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - #ntotal = len(packet) - #if len(dst.data()) != ntotal: - #print "Error: not enough data\n" - #nright = 0; - #for i in range(ntotal): - #if packet[i]==dst.data()[i]: - #nright=nright+1 - #else: - #print "Error in ", i - return (ntotal,ntotal-nright) + if len(dst.data()) != len(packet): + print "Error: not enough data:", len(dst.data()), len(packet) + ntotal=len(packet) + nwrong = sum(abs(packet-numpy.array(dst.data()))); + return (ntotal,nwrong,abs(packet-numpy.array(dst.data()))) @@ -113,20 +99,26 @@ def main(): Es = Es / (len(constellation)/dimensionality) N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error + tot_b=0 # total number of transmitted bits + terr_b=0 # total number of bits in error terr_p=0 # total number of packets in error for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) + (b,e,pattern)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-(666+i)) # run experiment with different seed to get different noise realizations + tot_b=tot_b+b + terr_b=terr_b+e + terr_p=terr_p+(e!=0) if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) + print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_b,terr_b, '%.2e' % ((1.0*terr_b)/tot_b) + if e!=0: + print "rep=",i, e + for k in range(Kb): + if pattern[k]!=0: + print k + # estimate of the bit error rate + print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_b,terr_b, '%.2e' % ((1.0*terr_b)/tot_b) if __name__ == '__main__': main() + diff --git a/gr-trellis/examples/python/test_tcm_bit.py b/gr-trellis/examples/python/test_tcm_bit.py deleted file mode 100755 index 7880f0ea53..0000000000 --- a/gr-trellis/examples/python/test_tcm_bit.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils -from gnuradio.eng_option import eng_option -from optparse import OptionParser - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): - tb = gr.top_block () - - # TX - packet = [0]*Kb - # this for loop is TOO slow!!! - for i in range(Kb-1*16): # last 16 bits = 0 to drive the final state to 0 - packet[i] = random.randint(0, 1) # random 0s and 1s - src = blocks.vector_source_s(packet,False) - #src = blocks.lfsr_32k_source_s() - #src_head = blocks.head (gr.sizeof_short,Kb/16) # packet size in shorts - b2s = blocks.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality - enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - - # RX - metrics = trellis.metrics_f(f.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi - va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - s2b = blocks.packed_to_unpacked_ss(1,gr.GR_MSB_FIRST) # unpack shorts to bits - dst = blocks.vector_sink_s(); - #dst = blocks.check_lfsr_32k_s(); - - - #tb.connect (src,src_head,s2fsmi,enc,mod) - tb.connect (src,b2s,s2fsmi,enc,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,metrics) - #tb.connect (metrics,va,fsmi2s,dst) - tb.connect (metrics,va,fsmi2s,s2b,dst) - - - tb.run() - - # A bit of cheating: run the program once and print the - # final encoder state.. - # Then put it as the last argument in the viterbi block - #print "final state = " , enc.ST() - - #ntotal = dst.ntotal () - #nright = dst.nright () - #runlength = dst.runlength () - ntotal = len(packet) - if len(dst.data()) != ntotal: - print "Error: not enough data\n" - nright = 0; - # this for loop is TOO slow!!! - for i in range(ntotal): - if packet[i]==dst.data()[i]: - nright=nright+1 - #else: - #print "Error in ", i - return (ntotal,ntotal-nright) - - - - -def main(): - parser = OptionParser(option_class=eng_option) - parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") - parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") - parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") - - (options, args) = parser.parse_args () - if len(args) != 0: - parser.print_help() - raise SystemExit, 1 - - fname=options.fsm_file - esn0_db=float(options.esn0) - rep=int(options.repetitions) - - - # system parameters - f=trellis.fsm(fname) # get the FSM specification from a file - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != f.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%1==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main() diff --git a/gr-trellis/examples/python/test_tcm_combined.py b/gr-trellis/examples/python/test_tcm_combined.py deleted file mode 100755 index 697e3cc64a..0000000000 --- a/gr-trellis/examples/python/test_tcm_combined.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import fsm_utils -from gnuradio.eng_option import eng_option -from optparse import OptionParser - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): - tb = gr.top_block () - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality - enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - - # RX - va = trellis.viterbi_combined_fs(f,K,0,-1,dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # Put -1 if the Initial/Final states are not set. - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s(); - - - tb.connect (src,src_head,s2fsmi,enc,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,va,fsmi2s,dst) - - - tb.run() - - # A bit of cheating: run the program once and print the - # final encoder state.. - # Then put it as the last argument in the viterbi block - #print "final state = " , enc.ST() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - - return (ntotal,ntotal-nright) - - - - -def main(): - parser = OptionParser(option_class=eng_option) - parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") - parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") - parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") - - (options, args) = parser.parse_args () - if len(args) != 0: - parser.print_help() - raise SystemExit, 1 - - fname=options.fsm_file - esn0_db=float(options.esn0) - rep=int(options.repetitions) - - # system parameters - f=trellis.fsm(fname) # get the FSM specification from a file (will hopefully be automated in the future...) - Kb=1024*16 # packet size in bits (make it multiple of 16) - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - modulation = fsm_utils.psk4 # see fsm_utils.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != f.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main() - diff --git a/gr-trellis/examples/python/test_tcm_parallel.py b/gr-trellis/examples/python/test_tcm_parallel.py deleted file mode 100755 index b30c80811f..0000000000 --- a/gr-trellis/examples/python/test_tcm_parallel.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import fsm_utils -from gnuradio.eng_option import eng_option -from optparse import OptionParser - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed,P): - tb = gr.top_block () - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16*P) # packet size in shorts - s2fsmi=blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality - s2p = blocks.stream_to_streams(gr.sizeof_short,P) # serial to parallel - enc = trellis.encoder_ss(f,0) # initiali state = 0 - mod = digital.chunks_to_symbols_sf(constellation,dimensionality) - - # CHANNEL - add=[] - noise=[] - for i in range(P): - add.append(blocks.add_ff()) - noise.append(analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed)) - - # RX - metrics = trellis.metrics_f(f.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi - va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. - p2s = blocks.streams_to_stream(gr.sizeof_short,P) # parallel to serial - fsmi2s=blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s() - - tb.connect (src,src_head,s2fsmi,s2p) - for i in range(P): - tb.connect ((s2p,i),(enc,i),(mod,i)) - tb.connect ((mod,i),(add[i],0)) - tb.connect (noise[i],(add[i],1)) - tb.connect (add[i],(metrics,i)) - tb.connect ((metrics,i),(va,i),(p2s,i)) - tb.connect (p2s,fsmi2s,dst) - - - tb.run() - - # A bit of cheating: run the program once and print the - # final encoder state. - # Then put it as the last argument in the viterbi block - #print "final state = " , enc.ST() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - - return (ntotal,ntotal-nright) - - - -def main(): - parser = OptionParser(option_class=eng_option) - parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") - parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") - parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") - - (options, args) = parser.parse_args () - if len(args) != 0: - parser.print_help() - raise SystemExit, 1 - - fname=options.fsm_file - esn0_db=float(options.esn0) - rep=int(options.repetitions) - - # system parameters - f=trellis.fsm(fname) # get the FSM specification from a file - P=4 # how many parallel streams? - Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations - dimensionality = modulation[0] - constellation = modulation[1] - if len(constellation)/dimensionality != f.O(): - sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') - sys.exit (1) - # calculate average symbol energy - Es = 0 - for i in range(len(constellation)): - Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i),P) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - -if __name__ == '__main__': - main() - diff --git a/gr-trellis/examples/python/test_turbo_equalization.py b/gr-trellis/examples/python/test_turbo_equalization.py deleted file mode 100755 index b2d58a6014..0000000000 --- a/gr-trellis/examples/python/test_turbo_equalization.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def make_rx(tb,fo,fi,dimensionality,tot_constellation,K,interleaver,IT,Es,N0,type): - metrics_in = trellis.metrics_f(fi.O(),dimensionality,tot_constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner SISO - scale = blocks.multiply_const_ff(1.0/N0) - gnd = blocks.vector_source_f([0],True); - - inter=[] - deinter=[] - siso_in=[] - siso_out=[] - - # generate all blocks - for it in range(IT): - inter.append( trellis.permutation(interleaver.K(),interleaver.INTER(),fi.I(),gr.sizeof_float) ) - siso_in.append( trellis.siso_f(fi,K,0,-1,True,False,type) ) - deinter.append( trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) ) - if it < IT-1: - siso_out.append( trellis.siso_f(fo,K,0,-1,False,True,type) ) - else: - siso_out.append( trellis.viterbi_s(fo,K,0,-1) ) # no soft outputs needed - - # connect first stage - tb.connect (gnd,inter[0]) - tb.connect (metrics_in,scale) - tb.connect (scale,(siso_in[0],1)) - - # connect the rest - for it in range(IT): - if it < IT-1: - tb.connect (metrics_in,(siso_in[it+1],1)) - tb.connect (siso_in[it],deinter[it],(siso_out[it],1)) - tb.connect (gnd,(siso_out[it],0)) - tb.connect (siso_out[it],inter[it+1]) - tb.connect (inter[it],(siso_in[it],0)) - else: - tb.connect (siso_in[it],deinter[it],siso_out[it]) - tb.connect (inter[it],(siso_in[it],0)) - - return (metrics_in,siso_out[IT-1]) - - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,tot_constellation,Es,N0,IT,seed): - tb = gr.top_block () - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head(gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the iouter FSM input cardinality - enc_out = trellis.encoder_ss(fo,0) # initial state = 0 - inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - # essentially here we implement the combination of modulation and channel as a memoryless modulation (the memory induced by the channel is hidden in the innner FSM) - mod = digital.chunks_to_symbols_sf(tot_constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - (head,tail) = make_rx(tb,fo,fi,dimensionality,tot_constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_MIN_SUM) - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s(); - - tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,head) - tb.connect (tail,fsmi2s,dst) - - tb.run() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - #print ntotal,nright,runlength - - return (ntotal,ntotal-nright) - - - - -def main(args): - nargs = len (args) - if nargs == 3: - fname_out=args[0] - esn0_db=float(args[1]) - rep=int(args[2]) - else: - sys.stderr.write ('usage: test_turbo_equalization.py fsm_name_out Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=64*16 # packet size in bits (multiple of 16) - modulation = fsm_utils.pam4 # see fsm_utlis.py for available predefined modulations - channel = fsm_utils.c_channel # see fsm_utlis.py for available predefined test channels - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(len(modulation[1]),len(channel)) # generate the FSM automatically - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - print 'size = ',K - interleaver=trellis.interleaver(K,666) # construct a random interleaver - tot_channel = fsm_utils.make_isi_lookup(modulation,channel,True) # generate the lookup table (normalize energy to 1) - dimensionality = tot_channel[0] - tot_constellation = tot_channel[1] - if len(tot_constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and lookup table size.\n') - sys.exit (1) - N0=pow(10.0,-esn0_db/10.0); # noise variance - IT = 3 # number of turbo iterations - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,tot_constellation,1,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - print s - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main (sys.argv[1:]) - diff --git a/gr-trellis/examples/python/test_turbo_equalization1.py b/gr-trellis/examples/python/test_turbo_equalization1.py deleted file mode 100755 index 5ff21ec757..0000000000 --- a/gr-trellis/examples/python/test_turbo_equalization1.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, filter, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def make_rx(tb,fo,fi,dimensionality,tot_constellation,K,interleaver,IT,Es,N0,type): - metrics_in = trellis.metrics_f(fi.O(),dimensionality,tot_constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner SISO - scale = blocks.multiply_const_ff(1.0/N0) - gnd = blocks.vector_source_f([0],True); - - inter=[] - deinter=[] - siso_in=[] - siso_out=[] - - # generate all blocks - for it in range(IT): - inter.append( trellis.permutation(interleaver.K(),interleaver.INTER(),fi.I(),gr.sizeof_float) ) - siso_in.append( trellis.siso_f(fi,K,0,-1,True,False,type) ) - deinter.append( trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) ) - if it < IT-1: - siso_out.append( trellis.siso_f(fo,K,0,-1,False,True,type) ) - else: - siso_out.append( trellis.viterbi_s(fo,K,0,-1) ) # no soft outputs needed - - # connect first stage - tb.connect (gnd,inter[0]) - tb.connect (metrics_in,scale) - tb.connect (scale,(siso_in[0],1)) - - # connect the rest - for it in range(IT): - if it < IT-1: - tb.connect (scale,(siso_in[it+1],1)) - tb.connect (siso_in[it],deinter[it],(siso_out[it],1)) - tb.connect (gnd,(siso_out[it],0)) - tb.connect (siso_out[it],inter[it+1]) - tb.connect (inter[it],(siso_in[it],0)) - else: - tb.connect (siso_in[it],deinter[it],siso_out[it]) - tb.connect (inter[it],(siso_in[it],0)) - - return (metrics_in,siso_out[IT-1]) - - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,Es,N0,IT,seed): - tb = gr.top_block () - L = len(channel) - - # TX - # this for loop is TOO slow in python!!! - packet = [0]*(K) - random.seed(seed) - for i in range(len(packet)): - packet[i] = random.randint(0, 2**bitspersymbol - 1) # random symbols - src = blocks.vector_source_s(packet,False) - enc_out = trellis.encoder_ss(fo,0) # initial state = 0 - inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) - - # CHANNEL - isi = filter.fir_filter_fff(1,channel) - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - (head,tail) = make_rx(tb,fo,fi,dimensionality,tot_constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_MIN_SUM) - dst = blocks.vector_sink_s(); - - tb.connect (src,enc_out,inter,mod) - tb.connect (mod,isi,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,head) - tb.connect (tail,dst) - - tb.run() - - data = dst.data() - ntotal = len(data) - nright=0 - for i in range(ntotal): - if packet[i]==data[i]: - nright=nright+1 - #else: - #print "Error in ", i - - return (ntotal,ntotal-nright) - - - - -def main(args): - nargs = len (args) - if nargs == 3: - fname_out=args[0] - esn0_db=float(args[1]) - rep=int(args[2]) - else: - sys.stderr.write ('usage: test_turbo_equalization.py fsm_name_out Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=64*16 # packet size in bits (multiple of 16) - modulation = fsm_utils.pam4 # see fsm_utlis.py for available predefined modulations - channel = fsm_utils.c_channel # see fsm_utlis.py for available predefined test channels - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(len(modulation[1]),len(channel)) # generate the FSM automatically - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - tot_channel = fsm_utils.make_isi_lookup(modulation,channel,True) # generate the lookup table (normalize energy to 1) - dimensionality = tot_channel[0] - tot_constellation = tot_channel[1] - if len(tot_constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and lookup table size.\n') - sys.exit (1) - N0=pow(10.0,-esn0_db/10.0); # noise variance - IT = 3 # number of turbo iterations - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,1,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main (sys.argv[1:]) - diff --git a/gr-trellis/examples/python/test_turbo_equalization2.py b/gr-trellis/examples/python/test_turbo_equalization2.py deleted file mode 100755 index c2af9fbfca..0000000000 --- a/gr-trellis/examples/python/test_turbo_equalization2.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, filter, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def make_rx(tb,fo,fi,dimensionality,tot_constellation,K,interleaver,IT,Es,N0,type): - scale = blocks.multiply_const_ff(math.sqrt(1.0/N0)) - gnd = blocks.vector_source_f([0],True); - - inter=[] - deinter=[] - siso_in=[] - siso_out=[] - - # generate all blocks - for it in range(IT): - inter.append( trellis.permutation(interleaver.K(),interleaver.INTER(),fi.I(),gr.sizeof_float) ) - siso_in.append( trellis.siso_combined_f(fi,K,0,-1,True,False,type,dimensionality,tot_constellation,digital.TRELLIS_EUCLIDEAN) ) - deinter.append( trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) ) - if it < IT-1: - siso_out.append( trellis.siso_f(fo,K,0,-1,False,True,type) ) - else: - siso_out.append( trellis.viterbi_s(fo,K,0,-1) ) # no soft outputs needed - - # connect first stage - tb.connect (gnd,inter[0]) - tb.connect (scale,(siso_in[0],1)) - - # connect the rest - for it in range(IT): - if it < IT-1: - tb.connect (scale,(siso_in[it+1],1)) - tb.connect (siso_in[it],deinter[it],(siso_out[it],1)) - tb.connect (gnd,(siso_out[it],0)) - tb.connect (siso_out[it],inter[it+1]) - tb.connect (inter[it],(siso_in[it],0)) - else: - tb.connect (siso_in[it],deinter[it],siso_out[it]) - tb.connect (inter[it],(siso_in[it],0)) - - return (scale,siso_out[IT-1]) - - -def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,Es,N0,IT,seed): - tb = gr.top_block () - L = len(channel) - - # TX - # this for loop is TOO slow in python!!! - packet = [0]*(K) - random.seed(seed) - for i in range(len(packet)): - packet[i] = random.randint(0, 2**bitspersymbol - 1) # random symbols - src = blocks.vector_source_s(packet,False) - enc_out = trellis.encoder_ss(fo,0) # initial state = 0 - inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) - - # CHANNEL - isi = filter.fir_filter_fff(1,channel) - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - (head,tail) = make_rx(tb,fo,fi,dimensionality,tot_constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_MIN_SUM) - dst = blocks.vector_sink_s(); - - tb.connect (src,enc_out,inter,mod) - tb.connect (mod,isi,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,head) - tb.connect (tail,dst) - - tb.run() - - data = dst.data() - ntotal = len(data) - nright=0 - for i in range(ntotal): - if packet[i]==data[i]: - nright=nright+1 - #else: - #print "Error in ", i - - return (ntotal,ntotal-nright) - - - - -def main(args): - nargs = len (args) - if nargs == 3: - fname_out=args[0] - esn0_db=float(args[1]) - rep=int(args[2]) - else: - sys.stderr.write ('usage: test_turbo_equalization.py fsm_name_out Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=64*16 # packet size in bits (multiple of 16) - modulation = fsm_utils.pam4 # see fsm_utlis.py for available predefined modulations - channel = fsm_utils.c_channel # see fsm_utlis.py for available predefined test channels - fo=trellis.fsm(fname_out) # get the outer FSM specification from a file - fi=trellis.fsm(len(modulation[1]),len(channel)) # generate the FSM automatically - if fo.O() != fi.I(): - sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') - sys.exit (1) - bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - interleaver=trellis.interleaver(K,666) # construct a random interleaver - tot_channel = fsm_utils.make_isi_lookup(modulation,channel,True) # generate the lookup table (normalize energy to 1) - dimensionality = tot_channel[0] - N0=pow(10.0,-esn0_db/10.0); # noise variance - tot_constellation =[0]*len(tot_channel[1]) - for i in range(len(tot_channel[1])): - tot_constellation[i] = tot_channel[1][i] * math.sqrt(1.0/N0) - if len(tot_constellation)/dimensionality != fi.O(): - sys.stderr.write ('Incompatible FSM output cardinality and lookup table size.\n') - sys.exit (1) - IT = 3 # number of turbo iterations - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - - for i in range(rep): - (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,1,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%10==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main (sys.argv[1:]) - diff --git a/gr-trellis/examples/python/test_viterbi_equalization.py b/gr-trellis/examples/python/test_viterbi_equalization.py deleted file mode 100755 index 987f171b2a..0000000000 --- a/gr-trellis/examples/python/test_viterbi_equalization.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, blocks -from gnuradio import eng_notation -import math -import sys -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (f,Kb,bitspersymbol,K,dimensionality,tot_constellation,N0,seed): - tb = gr.top_block () - - # TX - src = blocks.lfsr_32k_source_s() - src_head = blocks.head (gr.sizeof_short,Kb/16) # packet size in shorts - s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality - enc = trellis.encoder_ss(f,0) # initial state = 0 - # essentially here we implement the combination of modulation and channel as a memoryless modulation (the memory induced by the channel is hidden in the FSM) - mod = digital.chunks_to_symbols_sf(tot_constellation,dimensionality) - - # CHANNEL - add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - metrics = trellis.metrics_f(f.O(),dimensionality,tot_constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi - va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. - fsmi2s = blocks.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts - dst = blocks.check_lfsr_32k_s(); - - tb.connect (src,src_head,s2fsmi,enc,mod) - tb.connect (mod,(add,0)) - tb.connect (noise,(add,1)) - tb.connect (add,metrics) - tb.connect (metrics,va,fsmi2s,dst) - - tb.run() - - ntotal = dst.ntotal () - nright = dst.nright () - runlength = dst.runlength () - #print ntotal,nright,runlength - - return (ntotal,ntotal-nright) - - - - -def main(args): - nargs = len (args) - if nargs == 2: - esn0_db=float(args[0]) - rep=int(args[1]) - else: - sys.stderr.write ('usage: test_viterbi_equalization.py Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=128*16 # packet size in bits (multiple of 16) - modulation = fsm_utils.pam4 # see fsm_utlis.py for available predefined modulations - channel = fsm_utils.c_channel # see fsm_utlis.py for available predefined test channels - f=trellis.fsm(len(modulation[1]),len(channel)) # generate the FSM automatically - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - - tot_channel = fsm_utils.make_isi_lookup(modulation,channel,True) # generate the lookup table (normalize energy to 1) - dimensionality = tot_channel[0] - tot_constellation = tot_channel[1] - N0=pow(10.0,-esn0_db/10.0); # noise variance - if len(tot_constellation)/dimensionality != f.O(): - sys.stderr.write ('Incompatible FSM output cardinality and lookup table size.\n') - sys.exit (1) - - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - - for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,tot_constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or bit) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main (sys.argv[1:]) - diff --git a/gr-trellis/examples/python/test_viterbi_equalization1.py b/gr-trellis/examples/python/test_viterbi_equalization1.py deleted file mode 100755 index baa6a27f1b..0000000000 --- a/gr-trellis/examples/python/test_viterbi_equalization1.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import trellis, digital, filter, blocks -from gnuradio import eng_notation -import math -import sys -import random -import fsm_utils - -try: - from gnuradio import analog -except ImportError: - sys.stderr.write("Error: Program requires gr-analog.\n") - sys.exit(1) - -def run_test (f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,N0,seed): - tb = gr.top_block () - L = len(channel) - - # TX - # this for loop is TOO slow in python!!! - packet = [0]*(K+2*L) - random.seed(seed) - for i in range(len(packet)): - packet[i] = random.randint(0, 2**bitspersymbol - 1) # random symbols - for i in range(L): # first/last L symbols set to 0 - packet[i] = 0 - packet[len(packet)-i-1] = 0 - src = blocks.vector_source_s(packet,False) - mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) - - # CHANNEL - isi = filter.fir_filter_fff(1,channel) - add = blockss.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) - - # RX - skip = blocks.skiphead(gr.sizeof_float, L) # skip the first L samples since you know they are coming from the L zero symbols - #metrics = trellis.metrics_f(f.O(),dimensionality,tot_constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi - #va = trellis.viterbi_s(f,K+L,-1,0) # Put -1 if the Initial/Final states are not set. - va = trellis.viterbi_combined_fs(f,K+L,0,0,dimensionality,tot_constellation,digital.TRELLIS_EUCLIDEAN) # using viterbi_combined_fs instead of metrics_f/viterbi_s allows larger packet lengths because metrics_f is complaining for not being able to allocate large buffers. This is due to the large f.O() in this application... - dst = blocks.vector_sink_s() - - tb.connect (src,mod) - tb.connect (mod,isi,(add,0)) - tb.connect (noise,(add,1)) - #tb.connect (add,metrics) - #tb.connect (metrics,va,dst) - tb.connect (add,skip,va,dst) - - tb.run() - - data = dst.data() - ntotal = len(data) - L - nright=0 - for i in range(ntotal): - if packet[i+L]==data[i]: - nright=nright+1 - #else: - #print "Error in ", i - - return (ntotal,ntotal-nright) - - -def main(args): - nargs = len (args) - if nargs == 2: - esn0_db=float(args[0]) - rep=int(args[1]) - else: - sys.stderr.write ('usage: test_viterbi_equalization1.py Es/No_db repetitions\n') - sys.exit (1) - - # system parameters - Kb=128*16 # packet size in bits (multiple of 16) - modulation = fsm_utils.pam4 # see fsm_utlis.py for available predefined modulations - channel = fsm_utils.c_channel # see fsm_utlis.py for available predefined test channels - f=trellis.fsm(len(modulation[1]),len(channel)) # generate the FSM automatically - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps - - tot_channel = fsm_utils.make_isi_lookup(modulation,channel,True) # generate the lookup table (normalize energy to 1) - dimensionality = tot_channel[0] - tot_constellation = tot_channel[1] - N0=pow(10.0,-esn0_db/10.0); # noise variance - if len(tot_constellation)/dimensionality != f.O(): - sys.stderr.write ('Incompatible FSM output cardinality and lookup table size.\n') - sys.exit (1) - - tot_s=0 # total number of transmitted shorts - terr_s=0 # total number of shorts in error - terr_p=0 # total number of packets in error - - for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations - tot_s=tot_s+s - terr_s=terr_s+e - terr_p=terr_p+(terr_s!=0) - if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - # estimate of the (short or symbol) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) - - - -if __name__ == '__main__': - main (sys.argv[1:]) diff --git a/gr-trellis/gnuradio-trellis.pc.in b/gr-trellis/gnuradio-trellis.pc.in index df7e2e2575..8ccf65b83f 100644 --- a/gr-trellis/gnuradio-trellis.pc.in +++ b/gr-trellis/gnuradio-trellis.pc.in @@ -4,7 +4,7 @@ libdir=@libdir@ includedir=@includedir@ Name: gnuradio-trellis -Description: GNU Radio blocks for trellis coded modulation +Description: GNU Radio blocks for trellis-based processing Requires: gnuradio-runtime Version: @LIBVER@ Libs: -L${libdir} -lgnuradio-trellis diff --git a/gr-trellis/grc/trellis_encoder_xx.xml b/gr-trellis/grc/trellis_encoder_xx.xml index d877d53c53..a2ad69278d 100644 --- a/gr-trellis/grc/trellis_encoder_xx.xml +++ b/gr-trellis/grc/trellis_encoder_xx.xml @@ -10,7 +10,9 @@ <key>trellis_encoder_xx</key> <category>Trellis Coding</category> <import>from gnuradio import trellis</import> - <make>trellis.encoder_$(type)(trellis.fsm($fsm_args), $init_state)</make> + <make> trellis.encoder_$(type)(trellis.fsm($fsm_args), $init_state, $blocklength) if $blockwise else trellis.encoder_$(type)(trellis.fsm($fsm_args), $init_state) </make> + <callback>set_FSM(trellis.fsm($fsm_args))</callback> + <callback>set_ST($init_state)</callback> <param> <name>Type</name> <key>type</key> @@ -63,6 +65,28 @@ <value>0</value> <type>int</type> </param> + <param> + <name>Blockwise</name> + <key>blockwise</key> + <value>False</value> + <type>enum</type> + <hide>part</hide> + <option> + <name>On</name> + <key>True</key> + </option> + <option> + <name>Off</name> + <key>False</key> + </option> + </param> + <param> + <name>Block length</name> + <key>blocklength</key> + <value>0</value> + <type>int</type> + <hide>#if $blockwise() == 'True' then 'none' else 'all'#</hide> + </param> <check>(isinstance(eval(""" $fsm_args """[1:-1], locals(),globals()), str) and open($fsm_args).close()) or True</check> <sink> <name>in</name> diff --git a/gr-trellis/grc/trellis_metrics_x.xml b/gr-trellis/grc/trellis_metrics_x.xml index f551bc1521..8bb978f275 100644 --- a/gr-trellis/grc/trellis_metrics_x.xml +++ b/gr-trellis/grc/trellis_metrics_x.xml @@ -12,6 +12,9 @@ <category>Trellis Coding</category> <import>from gnuradio import trellis, digital</import> <make>trellis.metrics_$(type)($card, $dim, $table, $metric_type)</make> + <callback>set_O($card)</callback> + <callback>set_D($dim)</callback> + <callback>set_TYPE($metric_type)</callback> <callback>set_TABLE($table)</callback> <param> <name>Type</name> diff --git a/gr-trellis/grc/trellis_pccc_decoder_combined_xx.xml b/gr-trellis/grc/trellis_pccc_decoder_combined_xx.xml index 9bb4b034ac..ff727fbf8b 100644 --- a/gr-trellis/grc/trellis_pccc_decoder_combined_xx.xml +++ b/gr-trellis/grc/trellis_pccc_decoder_combined_xx.xml @@ -21,7 +21,7 @@ $dim, $table, $metric_type, $scaling) </make> - <callback>set_TABLE($table)</callback> + <callback>set_scaling($scaling)</callback> <param> <name>Input Type</name> <key>type</key> diff --git a/gr-trellis/grc/trellis_permutation.xml b/gr-trellis/grc/trellis_permutation.xml index bf6fc3ff15..0f118e889f 100644 --- a/gr-trellis/grc/trellis_permutation.xml +++ b/gr-trellis/grc/trellis_permutation.xml @@ -12,6 +12,10 @@ <category>Trellis Coding</category> <import>from gnuradio import trellis</import> <make>trellis.permutation($interleaver_size, $table, $syms_per_block, $type.size*$vlen)</make> + <callback>set_K($interleaver_size)</callback> + <callback>set_TABLE($table)</callback> + <callback>set_SYMS_PER_BLOCK($syms_per_block)</callback> + <param> <name>Type</name> <key>type</key> diff --git a/gr-trellis/grc/trellis_sccc_decoder_combined_xx.xml b/gr-trellis/grc/trellis_sccc_decoder_combined_xx.xml index bacc16cf5e..4947376d94 100644 --- a/gr-trellis/grc/trellis_sccc_decoder_combined_xx.xml +++ b/gr-trellis/grc/trellis_sccc_decoder_combined_xx.xml @@ -21,7 +21,7 @@ $dim, $table, $metric_type, $scaling) </make> - <callback>set_TABLE($table)</callback> + <callback>set_scaling($scaling)</callback> <param> <name>Input Type</name> <key>type</key> diff --git a/gr-trellis/grc/trellis_siso_combined_f.xml b/gr-trellis/grc/trellis_siso_combined_f.xml index 95eceeea31..542bba6d8b 100644 --- a/gr-trellis/grc/trellis_siso_combined_f.xml +++ b/gr-trellis/grc/trellis_siso_combined_f.xml @@ -12,6 +12,16 @@ <category>Trellis Coding</category> <import>from gnuradio import trellis</import> <make>trellis.siso_combined_f(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $a_post_in, $a_post_out, $siso_type, $dim, $table, $metric_type)</make> + <callback>set_FSM(trellis.fsm($fsm_args))</callback> + <callback>set_K($block_size)</callback> + <callback>set_S0($init_state)</callback> + <callback>set_SK($final_state)</callback> + <callback>set_POSTI($a_post_in)</callback> + <callback>set_POSTO($a_post_out)</callback> + <callback>set_SISO_TYPE($siso_type)</callback> + <callback>set_D($dim)</callback> + <callback>set_TABLE($table)</callback> + <callback>set_TYPE($metric_type)</callback> <param> <name>FSM Args</name> <key>fsm_args</key> @@ -101,7 +111,11 @@ </option> </param> <sink> - <name>in</name> + <name>in_i</name> + <type>float</type> + </sink> + <sink> + <name>in_o</name> <type>float</type> </sink> <source> diff --git a/gr-trellis/grc/trellis_siso_f.xml b/gr-trellis/grc/trellis_siso_f.xml index 67eeb27189..30849d2723 100644 --- a/gr-trellis/grc/trellis_siso_f.xml +++ b/gr-trellis/grc/trellis_siso_f.xml @@ -12,6 +12,13 @@ <category>Trellis Coding</category> <import>from gnuradio import trellis</import> <make>trellis.siso_f(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $a_post_in, $a_post_out, $siso_type)</make> + <callback>set_FSM(trellis.fsm($fsm_args))</callback> + <callback>set_K($block_size)</callback> + <callback>set_S0($init_state)</callback> + <callback>set_SK($final_state)</callback> + <callback>set_POSTI($a_post_in)</callback> + <callback>set_POSTO($a_post_out)</callback> + <callback>set_SISO_TYPE($siso_type)</callback> <param> <name>FSM Args</name> <key>fsm_args</key> @@ -75,7 +82,11 @@ </param> <check>(isinstance(eval(""" $fsm_args """[1:-1], locals(),globals()), str) and open($fsm_args).close()) or True</check> <sink> - <name>in</name> + <name>priori</name> + <type>float</type> + </sink> + <sink> + <name>prioro</name> <type>float</type> </sink> <source> diff --git a/gr-trellis/grc/trellis_viterbi_combined_xx.xml b/gr-trellis/grc/trellis_viterbi_combined_xx.xml index 81b49860a5..9c755dc524 100644 --- a/gr-trellis/grc/trellis_viterbi_combined_xx.xml +++ b/gr-trellis/grc/trellis_viterbi_combined_xx.xml @@ -12,7 +12,13 @@ <category>Trellis Coding</category> <import>from gnuradio import trellis, digital</import> <make>trellis.viterbi_combined_$(type)$(out_type)(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $dim, $table, $metric_type)</make> - <callback>set_TABLE($table)</callback> + <callback>set_FSM(trellis.fsm($fsm_args))</callback> + <callback>set_K($block_size)</callback> + <callback>set_S0($init_state)</callback> + <callback>set_SK($final_state)</callback> + <callback>set_D($dim)</callback> + <callback>set_TABLE($table)</callback> + <callback>set_TYPE($metric_type)</callback> <param> <name>Input Type</name> <key>type</key> diff --git a/gr-trellis/grc/trellis_viterbi_x.xml b/gr-trellis/grc/trellis_viterbi_x.xml index 734bb5386a..9083061e6b 100644 --- a/gr-trellis/grc/trellis_viterbi_x.xml +++ b/gr-trellis/grc/trellis_viterbi_x.xml @@ -12,6 +12,10 @@ <category>Trellis Coding</category> <import>from gnuradio import trellis</import> <make>trellis.viterbi_$(type)(trellis.fsm($fsm_args), $block_size, $init_state, $final_state)</make> + <callback>set_FSM(trellis.fsm($fsm_args))</callback> + <callback>set_K($block_size)</callback> + <callback>set_S0($init_state)</callback> + <callback>set_SK($final_state)</callback> <param> <name>Type</name> <key>type</key> diff --git a/gr-trellis/include/gnuradio/trellis/encoder_XX.h.t b/gr-trellis/include/gnuradio/trellis/encoder_XX.h.t index 7ece5d3f21..affd62f68b 100644 --- a/gr-trellis/include/gnuradio/trellis/encoder_XX.h.t +++ b/gr-trellis/include/gnuradio/trellis/encoder_XX.h.t @@ -44,8 +44,14 @@ namespace gr { static sptr make(const fsm &FSM, int ST); + static sptr make(const fsm &FSM, int ST, int K); + virtual fsm FSM() const = 0; virtual int ST() const = 0; + virtual int K() const = 0; + virtual void set_FSM(const fsm &FSM) =0; + virtual void set_ST(int ST) =0; + virtual void set_K(int K) =0; }; } /* namespace trellis */ diff --git a/gr-trellis/include/gnuradio/trellis/fsm.h b/gr-trellis/include/gnuradio/trellis/fsm.h index cc8893f1e3..5ba4483b97 100644 --- a/gr-trellis/include/gnuradio/trellis/fsm.h +++ b/gr-trellis/include/gnuradio/trellis/fsm.h @@ -153,6 +153,16 @@ namespace gr { * \param FSM2 second FSMS */ fsm(const fsm &FSM1, const fsm &FSM2); + + + /*! + * \brief Creates an FSMS describing the trellis of two serially concatenated FSMs. + * + * \param FSMo outer FSMS + * \param FSMi inner FSMS + * \param serial set it to true to distinguish from the previous constructor + */ + fsm(const fsm &FSMo, const fsm &FSMi, bool serial); /*! * \brief Creates an FSMS representing n stages through the originial FSM (AKA radix-n FSM). diff --git a/gr-trellis/include/gnuradio/trellis/metrics_X.h.t b/gr-trellis/include/gnuradio/trellis/metrics_X.h.t index 3f650faf0e..f463c865a9 100644 --- a/gr-trellis/include/gnuradio/trellis/metrics_X.h.t +++ b/gr-trellis/include/gnuradio/trellis/metrics_X.h.t @@ -49,9 +49,14 @@ namespace gr { virtual int D() const = 0; virtual digital::trellis_metric_type_t TYPE() const = 0; virtual std::vector<@I_TYPE@> TABLE() const = 0; + + virtual void set_O(int O) = 0; + virtual void set_D(int D) = 0; + virtual void set_TYPE(digital::trellis_metric_type_t type) = 0; virtual void set_TABLE(const std::vector<@I_TYPE@> &table) = 0; }; + } /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/include/gnuradio/trellis/permutation.h b/gr-trellis/include/gnuradio/trellis/permutation.h index 80b9fef641..5c86f3c9a7 100644 --- a/gr-trellis/include/gnuradio/trellis/permutation.h +++ b/gr-trellis/include/gnuradio/trellis/permutation.h @@ -44,9 +44,14 @@ namespace gr { int SYMS_PER_BLOCK, size_t NBYTES); virtual int K() const = 0; - virtual const std::vector<int> & TABLE() const = 0; + virtual std::vector<int> TABLE() const = 0; virtual int SYMS_PER_BLOCK() const = 0; virtual size_t BYTES_PER_SYMBOL() const = 0; + + virtual void set_K(int K) =0; + virtual void set_TABLE (const std::vector<int> &table) = 0; + virtual void set_SYMS_PER_BLOCK(int spb) =0; + }; } /* namespace trellis */ diff --git a/gr-trellis/include/gnuradio/trellis/sccc_decoder_combined_XX.h.t b/gr-trellis/include/gnuradio/trellis/sccc_decoder_combined_XX.h.t index 699de12fd8..e1f95dff1f 100644 --- a/gr-trellis/include/gnuradio/trellis/sccc_decoder_combined_XX.h.t +++ b/gr-trellis/include/gnuradio/trellis/sccc_decoder_combined_XX.h.t @@ -70,6 +70,7 @@ namespace gr { virtual digital::trellis_metric_type_t METRIC_TYPE() const = 0; virtual siso_type_t SISO_TYPE() const = 0; virtual float scaling() const = 0; + virtual void set_scaling(float scaling) = 0; }; diff --git a/gr-trellis/include/gnuradio/trellis/siso_combined_f.h b/gr-trellis/include/gnuradio/trellis/siso_combined_f.h index 47c34ea81e..4c37b2c68d 100644 --- a/gr-trellis/include/gnuradio/trellis/siso_combined_f.h +++ b/gr-trellis/include/gnuradio/trellis/siso_combined_f.h @@ -60,6 +60,17 @@ namespace gr { virtual int D() const = 0; virtual std::vector<float> TABLE() const = 0; virtual digital::trellis_metric_type_t TYPE() const = 0; + + virtual void set_FSM(const fsm &FSM) =0; + virtual void set_K(int K) =0; + virtual void set_S0(int S0) =0; + virtual void set_SK(int SK) =0; + virtual void set_POSTI(bool POSTI) =0; + virtual void set_POSTO(bool POSTO) =0; + virtual void set_SISO_TYPE(trellis::siso_type_t type) =0; + virtual void set_D(int D) =0; + virtual void set_TABLE(const std::vector<float> &table) =0; + virtual void set_TYPE(digital::trellis_metric_type_t type) =0; }; } /* namespace trellis */ diff --git a/gr-trellis/include/gnuradio/trellis/siso_f.h b/gr-trellis/include/gnuradio/trellis/siso_f.h index ae212cb4cf..89bcba0e82 100644 --- a/gr-trellis/include/gnuradio/trellis/siso_f.h +++ b/gr-trellis/include/gnuradio/trellis/siso_f.h @@ -53,6 +53,14 @@ namespace gr { virtual bool POSTI() const = 0; virtual bool POSTO() const = 0; virtual siso_type_t SISO_TYPE() const = 0; + + virtual void set_FSM(const fsm &FSM) =0; + virtual void set_K(int K) =0; + virtual void set_S0(int S0) =0; + virtual void set_SK(int SK) =0; + virtual void set_POSTI(bool posti) =0; + virtual void set_POSTO(bool posto) =0; + virtual void set_SISO_TYPE(trellis::siso_type_t type) = 0; }; } /* namespace trellis */ diff --git a/gr-trellis/include/gnuradio/trellis/viterbi_X.h.t b/gr-trellis/include/gnuradio/trellis/viterbi_X.h.t index 2d72cb5e09..252ffb715d 100644 --- a/gr-trellis/include/gnuradio/trellis/viterbi_X.h.t +++ b/gr-trellis/include/gnuradio/trellis/viterbi_X.h.t @@ -45,10 +45,15 @@ namespace gr { static sptr make(const fsm &FSM, int K, int S0, int SK); - virtual fsm FSM() const = 0; - virtual int K() const = 0; - virtual int S0() const = 0; - virtual int SK() const = 0; + virtual fsm FSM() const = 0; + virtual int K() const = 0; + virtual int S0() const = 0; + virtual int SK() const = 0; + + virtual void set_FSM(const fsm &FSM) =0; + virtual void set_K(int K) =0; + virtual void set_S0(int S0) =0; + virtual void set_SK(int SK) =0; }; } /* namespace trellis */ diff --git a/gr-trellis/include/gnuradio/trellis/viterbi_combined_XX.h.t b/gr-trellis/include/gnuradio/trellis/viterbi_combined_XX.h.t index 2becf8bf18..4546e95739 100644 --- a/gr-trellis/include/gnuradio/trellis/viterbi_combined_XX.h.t +++ b/gr-trellis/include/gnuradio/trellis/viterbi_combined_XX.h.t @@ -50,12 +50,19 @@ namespace gr { virtual fsm FSM() const = 0; virtual int K() const = 0; - virtual int S0() const = 0; + virtual int S0() const = 0; virtual int SK() const = 0; virtual int D() const = 0; virtual std::vector<@I_TYPE@> TABLE() const = 0; virtual digital::trellis_metric_type_t TYPE() const = 0; + + virtual void set_FSM(const fsm &FSM) =0; + virtual void set_K(int K) =0; + virtual void set_S0(int S0) =0; + virtual void set_SK(int SK) =0; + virtual void set_D(int D) =0; virtual void set_TABLE (const std::vector<@I_TYPE@> &table) = 0; + virtual void set_TYPE(digital::trellis_metric_type_t type) = 0; }; } /* namespace trellis */ diff --git a/gr-trellis/lib/calc_metric.cc b/gr-trellis/lib/calc_metric.cc index b95899940a..bdbb13ea08 100644 --- a/gr-trellis/lib/calc_metric.cc +++ b/gr-trellis/lib/calc_metric.cc @@ -73,19 +73,17 @@ namespace gr { } template - void calc_metric<short>(int O, int D, const std::vector<short> &TABLE, const short *input, - float *metric, digital::trellis_metric_type_t type); + void calc_metric<char>(int O, int D, const std::vector<char> &TABLE, const char *input, float *metric, digital::trellis_metric_type_t type); template - void calc_metric<int>(int O, int D, const std::vector<int> &TABLE, const int *input, - float *metric, digital::trellis_metric_type_t type); + void calc_metric<short>(int O, int D, const std::vector<short> &TABLE, const short *input, float *metric, digital::trellis_metric_type_t type); - template - void calc_metric<float>(int O, int D, const std::vector<float> &TABLE, const float *input, - float *metric, digital::trellis_metric_type_t type); + template void calc_metric<int>(int O, int D, const std::vector<int> &TABLE, const int *input, float *metric, digital::trellis_metric_type_t type); - void calc_metric(int O, int D, const std::vector<short> &TABLE, const short *input, - float *metric, digital::trellis_metric_type_t type) + template void calc_metric<float>(int O, int D, const std::vector<float> &TABLE, const float *input, float *metric, digital::trellis_metric_type_t type); + + /* + void calc_metric(int O, int D, const std::vector<short> &TABLE, const short *input, float *metric, digital::trellis_metric_type_t type) { float minm = FLT_MAX; int minmi = 0; @@ -124,7 +122,6 @@ namespace gr { } } - /* void calc_metric(int O, int D, const std::vector<int> &TABLE, const int *input, float *metric, digital::trellis_metric_type_t type) { diff --git a/gr-trellis/lib/core_algorithms.cc b/gr-trellis/lib/core_algorithms.cc index a8a0174551..b26ee331f2 100644 --- a/gr-trellis/lib/core_algorithms.cc +++ b/gr-trellis/lib/core_algorithms.cc @@ -215,6 +215,19 @@ namespace gr { //--------------- template void + viterbi_algorithm_combined<char,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<char> &TABLE, + digital::trellis_metric_type_t TYPE, + const char *in, unsigned char *out); + + template void viterbi_algorithm_combined<short,unsigned char>(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS, @@ -269,6 +282,19 @@ namespace gr { //--------------- template void + viterbi_algorithm_combined<char,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<char> &TABLE, + digital::trellis_metric_type_t TYPE, + const char *in, short *out); + + template void viterbi_algorithm_combined<short,short>(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS, @@ -323,6 +349,19 @@ namespace gr { //-------------- template void + viterbi_algorithm_combined<char,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<char> &TABLE, + digital::trellis_metric_type_t TYPE, + const char *in, int *out); + + template void viterbi_algorithm_combined<short,int>(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS, @@ -1177,17 +1216,17 @@ namespace gr { for(int k=0;k<blocklength;k++) { //std::cout << k << std::endl; for(int i=0;i<FSM1.O();i++) { - float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0]; + float x=cprioro[k*O+i*FSM2.O()+0]; for(int j=1;j<FSM2.O();j++) - x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]); + x = (*p2mymin)(x,cprioro[k*O+i*FSM2.O()+j]); prioro1[k*FSM1.O()+i]=x; //std::cout << prioro1[k*FSM1.O()+i] << ", "; } //std::cout << std::endl; for(int i=0;i<FSM2.O();i++) { - float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i]; + float x=cprioro[k*O+0*FSM2.O()+i]; for(int j=1;j<FSM1.O();j++) - x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]); + x = (*p2mymin)(x,cprioro[k*O+j*FSM2.O()+i]); prioro2[k*FSM2.O()+i]=x; } } diff --git a/gr-trellis/lib/encoder_XX_impl.cc.t b/gr-trellis/lib/encoder_XX_impl.cc.t index 4b11e3c06d..3a004a2f94 100644 --- a/gr-trellis/lib/encoder_XX_impl.cc.t +++ b/gr-trellis/lib/encoder_XX_impl.cc.t @@ -37,18 +37,45 @@ namespace gr { @BASE_NAME@::make(const fsm &FSM, int ST) { return gnuradio::get_initial_sptr - (new @IMPL_NAME@(FSM,ST)); + (new @IMPL_NAME@(FSM,ST,0,false)); } - @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM, int ST) + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSM, int ST, int K) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSM,ST,K,true)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM, int ST, int K, bool B) : sync_block("@BASE_NAME@", - io_signature::make(1, -1, sizeof(@I_TYPE@)), - io_signature::make(1, -1, sizeof(@O_TYPE@))), + io_signature::make(1, 1, sizeof(@I_TYPE@)), + io_signature::make(1, 1, sizeof(@O_TYPE@))), d_FSM(FSM), - d_ST(ST) + d_ST(ST), + d_K(K), + d_B(B) { } + void @IMPL_NAME@::set_FSM(const fsm &FSM) + { + gr::thread::scoped_lock guard(d_setlock); + d_FSM = FSM; + } + + void @IMPL_NAME@::set_ST(int ST) + { + gr::thread::scoped_lock guard(d_setlock); + d_ST = ST; + } + + void @IMPL_NAME@::set_K(int K) + { + gr::thread::scoped_lock guard(d_setlock); + d_K = K; + } + @IMPL_NAME@::~@IMPL_NAME@() { } @@ -58,25 +85,34 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int ST_tmp = 0; - int nstreams = input_items.size(); - for(int m=0;m<nstreams;m++) { - const @I_TYPE@ *in = (const @I_TYPE@*)input_items[m]; - @O_TYPE@ *out = (@O_TYPE@ *) output_items[m]; - ST_tmp = d_ST; - - // per stream processing - for(int i = 0; i < noutput_items; i++) { - out[i] = (@O_TYPE@)d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time? - ST_tmp = (int)d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]]; - } - // end per stream processing - } - d_ST = ST_tmp; - - return noutput_items; - } + if (d_B){ // blockwise operation + int nblocks = noutput_items /d_K; + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + for(int n = 0; n < nblocks; n++) { + ST_tmp = d_ST; + for(int i = 0; i < d_K; i++) { + out[n*d_K+i] = (@O_TYPE@)d_FSM.OS()[ST_tmp*d_FSM.I()+in[n*d_K+i]]; + ST_tmp = (int)d_FSM.NS()[ST_tmp*d_FSM.I()+in[n*d_K+i]]; + } + } + return nblocks*d_K; + } // end blockwise operation + else{ // streaming operation + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + ST_tmp = d_ST; + for(int i = 0; i < noutput_items; i++) { + out[i] = (@O_TYPE@)d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; + ST_tmp = (int)d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]]; + } + d_ST = ST_tmp; + return noutput_items; + } // end streaming operation + } } /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/encoder_XX_impl.h.t b/gr-trellis/lib/encoder_XX_impl.h.t index ec2f82611e..2b0ff31f4d 100644 --- a/gr-trellis/lib/encoder_XX_impl.h.t +++ b/gr-trellis/lib/encoder_XX_impl.h.t @@ -35,14 +35,20 @@ namespace gr { private: fsm d_FSM; int d_ST; + int d_K; + bool d_B; + public: - @IMPL_NAME@(const fsm &FSM, int ST); + @IMPL_NAME@(const fsm &FSM, int ST, int K, bool B); ~@IMPL_NAME@(); - fsm FSM() const { return d_FSM; } - int ST() const { return d_ST; } - + fsm FSM() const { return d_FSM;; } + int ST() const { return d_ST; } + int K() const { return d_K; } + void set_FSM(const fsm &FSM); + void set_ST(int ST); + void set_K(int K); int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gr-trellis/lib/fsm.cc b/gr-trellis/lib/fsm.cc index 20eeed5c25..4e57949f5e 100644 --- a/gr-trellis/lib/fsm.cc +++ b/gr-trellis/lib/fsm.cc @@ -313,6 +313,54 @@ namespace gr { generate_TM(); } + + //###################################################################### + //# Automatically generate an FSM specification describing the + //# the joint trellis of two serially concatenated fsms. + //###################################################################### + fsm::fsm(const fsm &FSMo, const fsm &FSMi, bool serial) + { + if(serial==false || FSMo.O()!=FSMi.I()) { + d_I=0; + d_S=0; + d_O=0; + d_NS.resize(0); + d_OS.resize(0); + d_PS.resize(0); + d_PI.resize(0); + d_TMi.resize(0); + d_TMl.resize(0); + return; + } + + d_I=FSMo.I(); + d_S=FSMo.S()*FSMi.S(); + d_O=FSMi.O(); + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + + for(int s=0;s<d_S;s++) { + for(int i=0;i<d_I;i++) { + int so=s/FSMi.S(); + int si=s%FSMi.S(); + int oo=FSMo.OS()[so * FSMo.I() + i]; + int oi=FSMi.OS()[si * FSMi.I() + oo]; + d_NS[s*d_I+i] = FSMo.NS()[so * FSMo.I() + i] * FSMo.S() + FSMi.NS()[si * FSMi.I() + oo]; + d_OS[s*d_I+i] = oi; + } + } + + generate_PS_PI(); + generate_TM(); + } + + + + + + + //###################################################################### //# Generate a new FSM representing n stages through the original FSM //# AKA radix-n FSM diff --git a/gr-trellis/lib/metrics_X_impl.cc.t b/gr-trellis/lib/metrics_X_impl.cc.t index 499bd8b9cd..5e74e4b2fc 100644 --- a/gr-trellis/lib/metrics_X_impl.cc.t +++ b/gr-trellis/lib/metrics_X_impl.cc.t @@ -54,16 +54,40 @@ namespace gr { set_output_multiple ((int)d_O); } - @IMPL_NAME@::~@IMPL_NAME@() + void @IMPL_NAME@::set_O(int O) + { + gr::thread::scoped_lock guard(d_setlock); + d_O = O; + set_relative_rate (1.0 * d_O / ((double) d_D)); + set_output_multiple ((int)d_O); + } + + void @IMPL_NAME@::set_D(int D) + { + gr::thread::scoped_lock guard(d_setlock); + d_D = D; + set_relative_rate (1.0 * d_O / ((double) d_D)); + } + + void + @IMPL_NAME@::set_TYPE(digital::trellis_metric_type_t type) { + gr::thread::scoped_lock guard(d_setlock); + d_TYPE = type; } void @IMPL_NAME@::set_TABLE(const std::vector<@I_TYPE@> &table) { + gr::thread::scoped_lock guard(d_setlock); d_TABLE = table; } + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void @IMPL_NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) { @@ -79,6 +103,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nstreams = input_items.size(); for(int m = 0; m < nstreams; m++) { diff --git a/gr-trellis/lib/metrics_X_impl.h.t b/gr-trellis/lib/metrics_X_impl.h.t index 2b4481fdb1..9323ae4645 100644 --- a/gr-trellis/lib/metrics_X_impl.h.t +++ b/gr-trellis/lib/metrics_X_impl.h.t @@ -47,6 +47,10 @@ namespace gr { int D() const { return d_D; } digital::trellis_metric_type_t TYPE() const { return d_TYPE; } std::vector<@I_TYPE@> TABLE() const { return d_TABLE; } + + void set_O(int O); + void set_D(int D); + void set_TYPE(digital::trellis_metric_type_t type); void set_TABLE(const std::vector<@I_TYPE@> &table); void forecast(int noutput_items, diff --git a/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t b/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t index 15ea3ceecb..5b3cdeeb62 100644 --- a/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t +++ b/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t @@ -90,6 +90,7 @@ namespace gr { void @IMPL_NAME@::set_scaling(float scaling) { + gr::thread::scoped_lock guard(d_setlock); d_scaling = scaling; } @@ -109,6 +110,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nblocks = noutput_items / d_blocklength; float (*p2min)(float, float) = NULL; diff --git a/gr-trellis/lib/pccc_encoder_XX_impl.cc.t b/gr-trellis/lib/pccc_encoder_XX_impl.cc.t index 119bff6ddb..8fd143ca9d 100644 --- a/gr-trellis/lib/pccc_encoder_XX_impl.cc.t +++ b/gr-trellis/lib/pccc_encoder_XX_impl.cc.t @@ -81,7 +81,7 @@ namespace gr { ST1_tmp = (int) d_FSM1.NS()[ST1_tmp*d_FSM1.I()+in[i]]; int o2 = d_FSM2.OS()[ST2_tmp*d_FSM2.I()+in[k]]; ST2_tmp = (int) d_FSM2.NS()[ST2_tmp*d_FSM2.I()+in[k]]; - out[i] = (@O_TYPE@) (o1*d_FSM1.O() + o2); + out[i] = (@O_TYPE@) (o1*d_FSM2.O() + o2); } } return noutput_items; diff --git a/gr-trellis/lib/permutation_impl.cc b/gr-trellis/lib/permutation_impl.cc index 06bba1e11f..2fe0ea8cb8 100644 --- a/gr-trellis/lib/permutation_impl.cc +++ b/gr-trellis/lib/permutation_impl.cc @@ -49,10 +49,30 @@ namespace gr { d_SYMS_PER_BLOCK(SYMS_PER_BLOCK), d_BYTES_PER_SYMBOL(BYTES_PER_SYMBOL) { - set_output_multiple(d_K*SYMS_PER_BLOCK); + set_output_multiple(d_K*d_SYMS_PER_BLOCK); //std::cout << d_K << "\n"; } + void permutation_impl::set_K(int K) + { + gr::thread::scoped_lock guard(d_setlock); + d_K=K; + set_output_multiple(d_K*d_SYMS_PER_BLOCK); + } + + void permutation_impl::set_TABLE (const std::vector<int> &table) + { + gr::thread::scoped_lock guard(d_setlock); + d_TABLE = table; + } + + void permutation_impl::set_SYMS_PER_BLOCK(int spb) + { + gr::thread::scoped_lock guard(d_setlock); + d_SYMS_PER_BLOCK=spb; + set_output_multiple(d_K*d_SYMS_PER_BLOCK); + } + permutation_impl::~permutation_impl() { } @@ -62,6 +82,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nstreams = input_items.size(); for(int m=0;m<nstreams;m++) { diff --git a/gr-trellis/lib/permutation_impl.h b/gr-trellis/lib/permutation_impl.h index 2c7b28d62f..e013e52a20 100644 --- a/gr-trellis/lib/permutation_impl.h +++ b/gr-trellis/lib/permutation_impl.h @@ -43,10 +43,14 @@ namespace gr { ~permutation_impl(); int K() const { return d_K; } - const std::vector<int> & TABLE() const { return d_TABLE; } + std::vector<int> TABLE() const { return d_TABLE; } int SYMS_PER_BLOCK() const { return d_SYMS_PER_BLOCK; } size_t BYTES_PER_SYMBOL() const { return d_BYTES_PER_SYMBOL; } + void set_K(int K) ; + void set_TABLE (const std::vector<int> &table); + void set_SYMS_PER_BLOCK(int spb) ; + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t b/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t index 4acc560175..f66b1f37e7 100644 --- a/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t +++ b/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t @@ -89,6 +89,7 @@ namespace gr { void @IMPL_NAME@::set_scaling(float scaling) { + gr::thread::scoped_lock guard(d_setlock); d_scaling = scaling; } @@ -108,6 +109,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nblocks = noutput_items / d_blocklength; float (*p2min)(float, float) = NULL; diff --git a/gr-trellis/lib/siso_combined_f_impl.cc b/gr-trellis/lib/siso_combined_f_impl.cc index d30f5cc4bb..3b89684bf0 100644 --- a/gr-trellis/lib/siso_combined_f_impl.cc +++ b/gr-trellis/lib/siso_combined_f_impl.cc @@ -48,23 +48,9 @@ namespace gr { SISO_TYPE, D, TABLE, TYPE)); } - siso_combined_f_impl::siso_combined_f_impl(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t SISO_TYPE, - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE) - : block("siso_combined_f", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(1, -1, sizeof(float))), - d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK), - d_POSTI(POSTI), d_POSTO(POSTO), - d_SISO_TYPE(SISO_TYPE), - d_D(D), d_TABLE(TABLE), d_TYPE(TYPE)//, - //d_alpha(FSM.S()*(K+1)), - //d_beta(FSM.S()*(K+1)) + void siso_combined_f_impl::recalculate() { - int multiple; + int multiple; if(d_POSTI && d_POSTO) multiple = d_FSM.I()+d_FSM.O(); else if(d_POSTI) @@ -74,7 +60,6 @@ namespace gr { else throw std::runtime_error ("Not both POSTI and POSTO can be false."); - //printf("constructor: Multiple = %d\n",multiple); set_output_multiple(d_K*multiple); //what is the meaning of relative rate for a block with 2 inputs? @@ -84,9 +69,94 @@ namespace gr { //set_relative_rate ( multiple / ((double) d_FSM.O()) ); // I am tempted to automate like this if(d_FSM.I() <= d_D) - set_relative_rate(multiple / ((double)d_D)); + set_relative_rate(multiple / ((double)d_D)); else - set_relative_rate(multiple / ((double)d_FSM.I())); + set_relative_rate(multiple / ((double)d_FSM.I())); + } + + + siso_combined_f_impl::siso_combined_f_impl(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t SISO_TYPE, + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE) + : block("siso_combined_f", + io_signature::make(1, -1, sizeof(float)), + io_signature::make(1, -1, sizeof(float))), + d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK), + d_POSTI(POSTI), d_POSTO(POSTO), + d_SISO_TYPE(SISO_TYPE), + d_D(D), d_TABLE(TABLE), d_TYPE(TYPE)//, + //d_alpha(FSM.S()*(K+1)), + //d_beta(FSM.S()*(K+1)) + { + recalculate(); + } + + void siso_combined_f_impl::set_FSM(const fsm &FSM) + { + gr::thread::scoped_lock guard(d_setlock); + d_FSM=FSM; + recalculate(); + } + + void siso_combined_f_impl::set_K(int K) + { + gr::thread::scoped_lock guard(d_setlock); + d_K=K; + recalculate(); + } + + void siso_combined_f_impl::set_POSTI(bool POSTI) + { + gr::thread::scoped_lock guard(d_setlock); + d_POSTI = POSTI; + recalculate(); + } + + void siso_combined_f_impl::set_POSTO(bool POSTO) + { + gr::thread::scoped_lock guard(d_setlock); + d_POSTO = POSTO; + recalculate(); + } + + void siso_combined_f_impl::set_D(int D) + { + gr::thread::scoped_lock guard(d_setlock); + d_D=D; + recalculate(); + } + + void siso_combined_f_impl::set_S0(int S0) + { + gr::thread::scoped_lock guard(d_setlock); + d_S0 = S0; + } + + void siso_combined_f_impl::set_SK(int SK) + { + gr::thread::scoped_lock guard(d_setlock); + d_SK = SK; + } + + void siso_combined_f_impl::set_SISO_TYPE(trellis::siso_type_t type) + { + gr::thread::scoped_lock guard(d_setlock); + d_SISO_TYPE = type; + } + + void siso_combined_f_impl::set_TABLE(const std::vector<float> &table) + { + gr::thread::scoped_lock guard(d_setlock); + d_TABLE = table; + } + + void siso_combined_f_impl::set_TYPE(digital::trellis_metric_type_t type) + { + gr::thread::scoped_lock guard(d_setlock); + d_TYPE = type; } siso_combined_f_impl::~siso_combined_f_impl() @@ -126,6 +196,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nstreams = output_items.size(); //printf("general_work:Streams: %d\n",nstreams); diff --git a/gr-trellis/lib/siso_combined_f_impl.h b/gr-trellis/lib/siso_combined_f_impl.h index 5035a0a83d..93e9aa87d2 100644 --- a/gr-trellis/lib/siso_combined_f_impl.h +++ b/gr-trellis/lib/siso_combined_f_impl.h @@ -41,6 +41,7 @@ namespace gr { int d_D; std::vector<float> d_TABLE; digital::trellis_metric_type_t d_TYPE; + void recalculate(); //std::vector<float> d_alpha; //std::vector<float> d_beta; @@ -64,6 +65,17 @@ namespace gr { std::vector<float> TABLE() const { return d_TABLE; } digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + void set_FSM(const fsm &FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + void set_POSTI(bool POSTI); + void set_POSTO(bool POSTO); + void set_SISO_TYPE(trellis::siso_type_t type); + void set_D(int D); + void set_TABLE(const std::vector<float> &table); + void set_TYPE(digital::trellis_metric_type_t type); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/gr-trellis/lib/siso_f_impl.cc b/gr-trellis/lib/siso_f_impl.cc index d699cecaec..2af5a21710 100644 --- a/gr-trellis/lib/siso_f_impl.cc +++ b/gr-trellis/lib/siso_f_impl.cc @@ -45,19 +45,8 @@ namespace gr { (new siso_f_impl(FSM, K, S0, SK, POSTI, POSTO, SISO_TYPE)); } - siso_f_impl::siso_f_impl(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t SISO_TYPE) - : block("siso_f", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(1, -1, sizeof(float))), - d_FSM(FSM), d_K(K), - d_S0(S0),d_SK(SK), - d_POSTI(POSTI), d_POSTO(POSTO), - d_SISO_TYPE(SISO_TYPE)//, - //d_alpha(FSM.S()*(K+1)), - //d_beta(FSM.S()*(K+1)) + + void siso_f_impl::recalculate() { int multiple; if(d_POSTI && d_POSTO) @@ -69,7 +58,6 @@ namespace gr { else throw std::runtime_error ("Not both POSTI and POSTO can be false."); - //printf("constructor: Multiple = %d\n",multiple); set_output_multiple (d_K*multiple); //what is the meaning of relative rate for a block with 2 inputs? @@ -84,6 +72,69 @@ namespace gr { set_relative_rate(multiple / ((double) d_FSM.I())); } + siso_f_impl::siso_f_impl(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t SISO_TYPE) + : block("siso_f", + io_signature::make(1, -1, sizeof(float)), + io_signature::make(1, -1, sizeof(float))), + d_FSM(FSM), d_K(K), + d_S0(S0),d_SK(SK), + d_POSTI(POSTI), d_POSTO(POSTO), + d_SISO_TYPE(SISO_TYPE)//, + //d_alpha(FSM.S()*(K+1)), + //d_beta(FSM.S()*(K+1)) + { + recalculate(); + } + + void siso_f_impl::set_FSM(const fsm &FSM) + { + gr::thread::scoped_lock guard(d_setlock); + d_FSM=FSM; + recalculate(); + } + + void siso_f_impl::set_K(int K) + { + gr::thread::scoped_lock guard(d_setlock); + d_K=K; + recalculate(); + } + + void siso_f_impl::set_POSTI(bool POSTI) + { + gr::thread::scoped_lock guard(d_setlock); + d_POSTI = POSTI; + recalculate(); + } + + void siso_f_impl::set_POSTO(bool POSTO) + { + gr::thread::scoped_lock guard(d_setlock); + d_POSTO = POSTO; + recalculate(); + } + + void siso_f_impl::set_S0(int S0) + { + gr::thread::scoped_lock guard(d_setlock); + d_S0 = S0; + } + + void siso_f_impl::set_SK(int SK) + { + gr::thread::scoped_lock guard(d_setlock); + d_SK = SK; + } + + void siso_f_impl::set_SISO_TYPE(trellis::siso_type_t type) + { + gr::thread::scoped_lock guard(d_setlock); + d_SISO_TYPE = type; + } + siso_f_impl::~siso_f_impl() { } @@ -119,6 +170,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nstreams = output_items.size(); //printf("general_work:Streams: %d\n",nstreams); int multiple; diff --git a/gr-trellis/lib/siso_f_impl.h b/gr-trellis/lib/siso_f_impl.h index ca8f623aaf..f92616bf0a 100644 --- a/gr-trellis/lib/siso_f_impl.h +++ b/gr-trellis/lib/siso_f_impl.h @@ -42,6 +42,7 @@ namespace gr { bool d_POSTI; bool d_POSTO; siso_type_t d_SISO_TYPE; + void recalculate(); //std::vector<float> d_alpha; //std::vector<float> d_beta; @@ -60,6 +61,14 @@ namespace gr { bool POSTO() const { return d_POSTO; } siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + void set_FSM(const fsm &FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + void set_POSTI(bool POSTI); + void set_POSTO(bool POSTO); + void set_SISO_TYPE(trellis::siso_type_t type); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/gr-trellis/lib/viterbi_X_impl.cc.t b/gr-trellis/lib/viterbi_X_impl.cc.t index 247424b3f3..1d4864596e 100644 --- a/gr-trellis/lib/viterbi_X_impl.cc.t +++ b/gr-trellis/lib/viterbi_X_impl.cc.t @@ -55,6 +55,32 @@ namespace gr { set_output_multiple(d_K); } + void @IMPL_NAME@::set_FSM(const fsm &FSM) + { + gr::thread::scoped_lock guard(d_setlock); + d_FSM = FSM; + set_relative_rate(1.0 / ((double)d_FSM.O())); + } + + void @IMPL_NAME@::set_K(int K) + { + gr::thread::scoped_lock guard(d_setlock); + d_K = K; + set_output_multiple(d_K); + } + + void @IMPL_NAME@::set_S0(int S0) + { + gr::thread::scoped_lock guard(d_setlock); + d_S0 = S0; + } + + void @IMPL_NAME@::set_SK(int SK) + { + gr::thread::scoped_lock guard(d_setlock); + d_SK = SK; + } + @IMPL_NAME@::~@IMPL_NAME@() { } @@ -76,6 +102,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nstreams = input_items.size(); int nblocks = noutput_items / d_K; diff --git a/gr-trellis/lib/viterbi_X_impl.h.t b/gr-trellis/lib/viterbi_X_impl.h.t index b9554e8c39..1479ad5a3f 100644 --- a/gr-trellis/lib/viterbi_X_impl.h.t +++ b/gr-trellis/lib/viterbi_X_impl.h.t @@ -44,11 +44,15 @@ namespace gr { int S0, int SK); ~@IMPL_NAME@(); - fsm FSM() const { return d_FSM; } - int K() const { return d_K; } - int S0() const { return d_S0; } - int SK() const { return d_SK; } + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + void set_FSM(const fsm &FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); //std::vector<int> trace () const { return d_trace; } void forecast(int noutput_items, diff --git a/gr-trellis/lib/viterbi_combined_XX_impl.cc.t b/gr-trellis/lib/viterbi_combined_XX_impl.cc.t index c7cf10e567..722708bcd2 100644 --- a/gr-trellis/lib/viterbi_combined_XX_impl.cc.t +++ b/gr-trellis/lib/viterbi_combined_XX_impl.cc.t @@ -60,16 +60,58 @@ namespace gr { set_output_multiple(d_K); } - @IMPL_NAME@::~@IMPL_NAME@() + void + @IMPL_NAME@::set_K(int K) + { + gr::thread::scoped_lock guard(d_setlock); + d_K = K; + set_output_multiple(d_K); + } + + void + @IMPL_NAME@::set_D(int D) + { + gr::thread::scoped_lock guard(d_setlock); + d_D = D; + set_relative_rate(1.0 / ((double)d_D)); + } + + void @IMPL_NAME@::set_FSM(const fsm &FSM) + { + gr::thread::scoped_lock guard(d_setlock); + d_FSM = FSM; + } + + void @IMPL_NAME@::set_S0(int S0) + { + gr::thread::scoped_lock guard(d_setlock); + d_S0 = S0; + } + + void @IMPL_NAME@::set_SK(int SK) + { + gr::thread::scoped_lock guard(d_setlock); + d_SK = SK; + } + + void + @IMPL_NAME@::set_TYPE(digital::trellis_metric_type_t type) { + gr::thread::scoped_lock guard(d_setlock); + d_TYPE = type; } void @IMPL_NAME@::set_TABLE(const std::vector<@I_TYPE@> &table) { + gr::thread::scoped_lock guard(d_setlock); d_TABLE = table; } + @IMPL_NAME@::~@IMPL_NAME@() + { + } + void @IMPL_NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) @@ -87,6 +129,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock guard(d_setlock); int nstreams = input_items.size(); int nblocks = noutput_items / d_K; diff --git a/gr-trellis/lib/viterbi_combined_XX_impl.h.t b/gr-trellis/lib/viterbi_combined_XX_impl.h.t index 199e8c8e88..788e609895 100644 --- a/gr-trellis/lib/viterbi_combined_XX_impl.h.t +++ b/gr-trellis/lib/viterbi_combined_XX_impl.h.t @@ -49,15 +49,22 @@ namespace gr { digital::trellis_metric_type_t TYPE); ~@IMPL_NAME@(); - fsm FSM() const { return d_FSM; } - int K() const { return d_K; } - int S0() const { return d_S0; } - int SK() const { return d_SK; } - int D() const { return d_D; } + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + int D() const { return d_D; } std::vector<@I_TYPE@> TABLE() const { return d_TABLE; } digital::trellis_metric_type_t TYPE() const { return d_TYPE; } //std::vector<int> trace() const { return d_trace; } + + void set_FSM(const fsm &FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + void set_D(int D); void set_TABLE(const std::vector<@I_TYPE@> &table); + void set_TYPE(digital::trellis_metric_type_t type); void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/gr-trellis/python/trellis/CMakeLists.txt b/gr-trellis/python/trellis/CMakeLists.txt index b4223af935..5cfe927412 100644 --- a/gr-trellis/python/trellis/CMakeLists.txt +++ b/gr-trellis/python/trellis/CMakeLists.txt @@ -25,6 +25,7 @@ include(GrPython) GR_PYTHON_INSTALL( FILES __init__.py + fsm_utils.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/trellis COMPONENT "trellis_python" ) diff --git a/gr-trellis/python/trellis/__init__.py b/gr-trellis/python/trellis/__init__.py index 6c6d80ecdf..662aa58197 100644 --- a/gr-trellis/python/trellis/__init__.py +++ b/gr-trellis/python/trellis/__init__.py @@ -31,3 +31,6 @@ except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) from trellis_swig import * + +# import any pure python here +import fsm_utils diff --git a/gr-trellis/examples/python/fsm_utils.py b/gr-trellis/python/trellis/fsm_utils.py index 06855ea775..72aa1d3660 100755 --- a/gr-trellis/examples/python/fsm_utils.py +++ b/gr-trellis/python/trellis/fsm_utils.py @@ -27,7 +27,7 @@ import sys import operator import numpy -from gnuradio import trellis +#from gnuradio import trellis try: import scipy.linalg @@ -182,6 +182,7 @@ psk4=(2,[1, 0, \ 0, 1, \ 0, -1,\ -1, 0]) # includes Gray mapping + psk8=(2,[math.cos(2*math.pi*0/8), math.sin(2*math.pi*0/8), \ math.cos(2*math.pi*1/8), math.sin(2*math.pi*1/8), \ math.cos(2*math.pi*2/8), math.sin(2*math.pi*2/8), \ @@ -191,6 +192,32 @@ psk8=(2,[math.cos(2*math.pi*0/8), math.sin(2*math.pi*0/8), \ math.cos(2*math.pi*6/8), math.sin(2*math.pi*6/8), \ math.cos(2*math.pi*7/8), math.sin(2*math.pi*7/8)]) +psk2x3 = (3,[-1,-1,-1, \ + -1,-1,1, \ + -1,1,-1, \ + -1,1,1, \ + 1,-1,-1, \ + 1,-1,1, \ + 1,1,-1, \ + 1,1,1]) + +psk2x4 = (4,[-1,-1,-1,-1, \ + -1,-1,-1,1, \ + -1,-1,1,-1, \ + -1,-1,1,1, \ + -1,1,-1,-1, \ + -1,1,-1,1, \ + -1,1,1,-1, \ + -1,1,1,1, \ + 1,-1,-1,-1, \ + 1,-1,-1,1, \ + 1,-1,1,-1, \ + 1,-1,1,1, \ + 1,1,-1,-1, \ + 1,1,-1,1, \ + 1,1,1,-1, \ + 1,1,1,1]) + orth2 = (2,[1, 0, \ 0, 1]) orth4=(4,[1, 0, 0, 0, \ @@ -205,35 +232,3 @@ orth4=(4,[1, 0, 0, 0, \ # C test channel (J. Proakis, Digital Communications, McGraw-Hill Inc., 2001) c_channel = [0.227, 0.460, 0.688, 0.460, 0.227] - - - - - - - - - -if __name__ == '__main__': - f1=trellis.fsm('fsm_files/awgn1o2_4.fsm') - #f2=trellis.fsm('fsm_files/awgn2o3_4.fsm') - #print f1.I(), f1.S(), f1.O() - #print f1.NS() - #print f1.OS() - #print f2.I(), f2.S(), f2.O() - #print f2.NS() - #print f2.OS() - ##f1.write_trellis_svg('f1.svg',4) - #f2.write_trellis_svg('f2.svg',4) - #f=fsm_concatenate(f1,f2) - #f=fsm_radix(f1,2) - - #print "----------\n" - #print f.I(), f.S(), f.O() - #print f.NS() - #print f.OS() - #f.write_trellis_svg('f.svg',4) - - q=numpy.arange(0,8)/(2.0*8) - (f0,SS,S,F,Sf,Ff,N) = make_cpm_signals(1,2,2,1,q,0.99) - diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc index 1a17e87775..c184f0a406 100644 --- a/gr-uhd/lib/usrp_sink_impl.cc +++ b/gr-uhd/lib/usrp_sink_impl.cc @@ -88,7 +88,7 @@ namespace gr { { bool clocks_locked = true; - // 1) Check ref lock for all mboards + // Check ref lock for all mboards for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) { std::string sensor_name = "ref_locked"; if (_dev->get_clock_source(mboard_index) == "internal") { @@ -107,19 +107,6 @@ namespace gr { } } - // 2) Check LO for all channels - for (size_t i = 0; i < _nchan; i++) { - size_t chan_index = _stream_args.channels[i]; - if (not _wait_for_locked_sensor( - get_sensor_names(chan_index), - "lo_locked", - boost::bind(&usrp_sink_impl::get_sensor, this, _1, chan_index) - )) { - GR_LOG_WARN(d_logger, boost::format("Sensor 'lo_locked' failed to lock within timeout on channel %d.") % chan_index); - clocks_locked = false; - } - } - return clocks_locked; } diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc index 6be0bac9ca..3142627952 100644 --- a/gr-uhd/lib/usrp_source_impl.cc +++ b/gr-uhd/lib/usrp_source_impl.cc @@ -87,7 +87,7 @@ namespace gr { { bool clocks_locked = true; - // 1) Check ref lock for all mboards + // Check ref lock for all mboards for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) { std::string sensor_name = "ref_locked"; if (_dev->get_clock_source(mboard_index) == "internal") { @@ -106,19 +106,6 @@ namespace gr { } } - // 2) Check LO for all channels - for (size_t i = 0; i < _nchan; i++) { - size_t chan_index = _stream_args.channels[i]; - if (not _wait_for_locked_sensor( - get_sensor_names(chan_index), - "lo_locked", - boost::bind(&usrp_source_impl::get_sensor, this, _1, chan_index) - )) { - GR_LOG_WARN(d_logger, boost::format("Sensor 'lo_locked' failed to lock within timeout on channel %d.") % chan_index); - clocks_locked = false; - } - } - return clocks_locked; } diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/FindCppUnit.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/FindCppUnit.cmake index 9af308f84b..f93ade3412 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/FindCppUnit.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/FindCppUnit.cmake @@ -15,6 +15,7 @@ PKG_CHECK_MODULES(PC_CPPUNIT "cppunit") FIND_PATH(CPPUNIT_INCLUDE_DIRS NAMES cppunit/TestCase.h HINTS ${PC_CPPUNIT_INCLUDE_DIR} + ${CMAKE_INSTALL_PREFIX}/include PATHS /usr/local/include /usr/include @@ -23,6 +24,8 @@ FIND_PATH(CPPUNIT_INCLUDE_DIRS FIND_LIBRARY(CPPUNIT_LIBRARIES NAMES cppunit HINTS ${PC_CPPUNIT_LIBDIR} + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 PATHS ${CPPUNIT_INCLUDE_DIRS}/../lib /usr/local/lib diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake index 9331d5debc..188c40480b 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. +# Copyright 2010-2011,2014 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -94,7 +94,13 @@ macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG(${flag} ${have}) if(${have}) - add_definitions(${flag}) + if(${CMAKE_VERSION} VERSION_GREATER "2.8.4") + STRING(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_dup) + if(${flag_dup} EQUAL -1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}") + endif(${flag_dup} EQUAL -1) + endif(${CMAKE_VERSION} VERSION_GREATER "2.8.4") endif(${have}) endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE) @@ -155,7 +161,7 @@ function(GR_LIBRARY_FOO target) GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR}) #give the library a special name with ultra-zero soversion - set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0") + set_target_properties(${target} PROPERTIES OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0") set(target_name lib${target}-${LIBVER}.so.0.0.0) #custom command to generate symlinks @@ -208,3 +214,312 @@ function(GR_GEN_TARGET_DEPS name var) set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) endif() endfunction(GR_GEN_TARGET_DEPS) + +######################################################################## +# Control use of gr_logger +# Usage: +# GR_LOGGING() +# +# Will set ENABLE_GR_LOG to 1 by default. +# Can manually set with -DENABLE_GR_LOG=0|1 +######################################################################## +function(GR_LOGGING) + find_package(Log4cpp) + + OPTION(ENABLE_GR_LOG "Use gr_logger" ON) + if(ENABLE_GR_LOG) + # If gr_logger is enabled, make it usable + add_definitions( -DENABLE_GR_LOG ) + + # also test LOG4CPP; if we have it, use this version of the logger + # otherwise, default to the stdout/stderr model. + if(LOG4CPP_FOUND) + SET(HAVE_LOG4CPP True CACHE INTERNAL "" FORCE) + add_definitions( -DHAVE_LOG4CPP ) + else(not LOG4CPP_FOUND) + SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE) + SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE) + SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE) + SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE) + endif(LOG4CPP_FOUND) + + SET(ENABLE_GR_LOG ${ENABLE_GR_LOG} CACHE INTERNAL "" FORCE) + + else(ENABLE_GR_LOG) + SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE) + SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE) + SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE) + SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE) + endif(ENABLE_GR_LOG) + + message(STATUS "ENABLE_GR_LOG set to ${ENABLE_GR_LOG}.") + message(STATUS "HAVE_LOG4CPP set to ${HAVE_LOG4CPP}.") + message(STATUS "LOG4CPP_LIBRARIES set to ${LOG4CPP_LIBRARIES}.") + +endfunction(GR_LOGGING) + +######################################################################## +# Run GRCC to compile .grc files into .py files. +# +# Usage: GRCC(filename, directory) +# - filenames: List of file name of .grc file +# - directory: directory of built .py file - usually in +# ${CMAKE_CURRENT_BINARY_DIR} +# - Sets PYFILES: output converted GRC file names to Python files. +######################################################################## +function(GRCC) + # Extract directory from list of args, remove it for the list of filenames. + list(GET ARGV -1 directory) + list(REMOVE_AT ARGV -1) + set(filenames ${ARGV}) + file(MAKE_DIRECTORY ${directory}) + + SET(GRCC_COMMAND ${CMAKE_SOURCE_DIR}/gr-utils/python/grcc) + + # GRCC uses some stuff in grc and gnuradio-runtime, so we force + # the known paths here + list(APPEND PYTHONPATHS + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/gnuradio-runtime/python + ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/swig + ${CMAKE_BINARY_DIR}/gnuradio-runtime/lib/swig + ) + + if(WIN32) + #SWIG generates the python library files into a subdirectory. + #Therefore, we must append this subdirectory into PYTHONPATH. + #Only do this for the python directories matching the following: + foreach(pydir ${PYTHONPATHS}) + get_filename_component(name ${pydir} NAME) + if(name MATCHES "^(swig|lib|src)$") + list(APPEND PYTHONPATHS ${pydir}/${CMAKE_BUILD_TYPE}) + endif() + endforeach(pydir) + endif(WIN32) + + file(TO_NATIVE_PATH "${PYTHONPATHS}" pypath) + + if(UNIX) + list(APPEND pypath "$PYTHONPATH") + string(REPLACE ";" ":" pypath "${pypath}") + set(ENV{PYTHONPATH} ${pypath}) + endif(UNIX) + + if(WIN32) + list(APPEND pypath "%PYTHONPATH%") + string(REPLACE ";" "\\;" pypath "${pypath}") + #list(APPEND environs "PYTHONPATH=${pypath}") + set(ENV{PYTHONPATH} ${pypath}) + endif(WIN32) + + foreach(f ${filenames}) + execute_process( + COMMAND ${GRCC_COMMAND} -d ${directory} ${f} + ) + string(REPLACE ".grc" ".py" pyfile "${f}") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" pyfile "${pyfile}") + list(APPEND pyfiles ${pyfile}) + endforeach(f) + + set(PYFILES ${pyfiles} PARENT_SCOPE) +endfunction(GRCC) + +######################################################################## +# Check if HAVE_PTHREAD_SETSCHEDPARAM and HAVE_SCHED_SETSCHEDULER +# should be defined +######################################################################## +macro(GR_CHECK_LINUX_SCHED_AVAIL) +set(CMAKE_REQUIRED_LIBRARIES -lpthread) + CHECK_CXX_SOURCE_COMPILES(" + #include <pthread.h> + int main(){ + pthread_t pthread; + pthread_setschedparam(pthread, 0, 0); + return 0; + } " HAVE_PTHREAD_SETSCHEDPARAM + ) + GR_ADD_COND_DEF(HAVE_PTHREAD_SETSCHEDPARAM) + + CHECK_CXX_SOURCE_COMPILES(" + #include <sched.h> + int main(){ + pid_t pid; + sched_setscheduler(pid, 0, 0); + return 0; + } " HAVE_SCHED_SETSCHEDULER + ) + GR_ADD_COND_DEF(HAVE_SCHED_SETSCHEDULER) +endmacro(GR_CHECK_LINUX_SCHED_AVAIL) + +######################################################################## +# Macros to generate source and header files from template +######################################################################## +macro(GR_EXPAND_X_H component root) + + include(GrPython) + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py +"#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_RUNTIME_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_dict2(name, sig, '${component}') + build_utils.expand_template(d, inp) +") + + #make a list of all the generated headers + unset(expanded_files_h) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h) + endforeach(sig) + unset(name) + + #create a command to generate the headers + 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} + ) + + #install rules for the generated headers + list(APPEND generated_includes ${expanded_files_h}) + +endmacro(GR_EXPAND_X_H) + +macro(GR_EXPAND_X_CC_H component root) + + include(GrPython) + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py +"#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_RUNTIME_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, '${component}') + build_utils.expand_template(d, inp) +") + + #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) + unset(name) + + #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 files + 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 files + list(APPEND generated_sources ${expanded_files_cc}) + list(APPEND generated_headers ${expanded_files_h}) + +endmacro(GR_EXPAND_X_CC_H) + +macro(GR_EXPAND_X_CC_H_IMPL component root) + + include(GrPython) + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py +"#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_RUNTIME_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_dict(name, sig, '${component}') + build_utils.expand_template(d, inp, '_impl') +") + + #make a list of all the generated files + unset(expanded_files_cc_impl) + unset(expanded_files_h_impl) + unset(expanded_files_h) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_cc_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.cc) + list(APPEND expanded_files_h_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.h) + list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/../include/gnuradio/${component}/${name}.h) + endforeach(sig) + unset(name) + + #create a command to generate the _impl.cc files + add_custom_command( + OUTPUT ${expanded_files_cc_impl} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.cc.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}_impl.cc.t ${ARGN} + ) + + #create a command to generate the _impl.h files + add_custom_command( + OUTPUT ${expanded_files_h_impl} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.h.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}_impl.h.t ${ARGN} + ) + + #make _impl.cc source files depend on _impl.h to force generation + set_source_files_properties(${expanded_files_cc_impl} + PROPERTIES OBJECT_DEPENDS "${expanded_files_h_impl}" + ) + + #make _impl.h source files depend on headers to force generation + set_source_files_properties(${expanded_files_h_impl} + PROPERTIES OBJECT_DEPENDS "${expanded_files_h}" + ) + + #install rules for the generated files + list(APPEND generated_sources ${expanded_files_cc_impl}) + list(APPEND generated_headers ${expanded_files_h_impl}) + +endmacro(GR_EXPAND_X_CC_H_IMPL) diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPlatform.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPlatform.cmake index a2e4f3b34e..5b7e886f85 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPlatform.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPlatform.cmake @@ -37,10 +37,18 @@ if(LINUX AND EXISTS "/etc/redhat-release") set(REDHAT TRUE) endif() +if(LINUX AND EXISTS "/etc/slackware-version") + set(SLACKWARE TRUE) +endif() + ######################################################################## # when the library suffix should be 64 (applies to redhat linux family) ######################################################################## -if(NOT DEFINED LIB_SUFFIX AND REDHAT AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$") +if (REDHAT OR SLACKWARE) + set(LIB64_CONVENTION TRUE) +endif() + +if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$") set(LIB_SUFFIX 64) endif() set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix") diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake index 68ca58e996..395faffa5a 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake @@ -48,8 +48,15 @@ else(PYTHON_EXECUTABLE) endif(PYTHON_EXECUTABLE) +if (CMAKE_CROSSCOMPILING) + set(QA_PYTHON_EXECUTABLE "/usr/bin/python") +else (CMAKE_CROSSCOMPILING) + set(QA_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) +endif(CMAKE_CROSSCOMPILING) + #make the path to the executable appear in the cmake gui set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") +set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests") #make sure we can use -B with python (introduced in 2.6) if(PYTHON_EXECUTABLE) @@ -76,10 +83,11 @@ macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) execute_process( COMMAND ${PYTHON_EXECUTABLE} -c " ######################################### -try: import ${mod} -except: exit(-1) -try: assert ${cmd} -except: exit(-1) +try: + import ${mod} + assert ${cmd} +except ImportError, AssertionError: exit(-1) +except: pass #########################################" RESULT_VARIABLE ${have} ) @@ -95,11 +103,13 @@ endmacro(GR_PYTHON_CHECK_MODULE) ######################################################################## # Sets the python installation directory GR_PYTHON_DIR ######################################################################## +if(NOT DEFINED GR_PYTHON_DIR) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " from distutils import sysconfig print sysconfig.get_python_lib(plat_specific=True, prefix='') " OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ) +endif() file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) ######################################################################## @@ -181,6 +191,10 @@ function(GR_PYTHON_INSTALL) #################################################################### file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) + if (CMAKE_CROSSCOMPILING) + set(pyexe_native "/usr/bin/env python") + endif() + foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) get_filename_component(pyfile_name ${pyfile} NAME) get_filename_component(pyfile ${pyfile} ABSOLUTE) @@ -193,8 +207,9 @@ function(GR_PYTHON_INSTALL) add_custom_command( OUTPUT ${pyexefile} DEPENDS ${pyfile} COMMAND ${PYTHON_EXECUTABLE} -c - \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" + "open('${pyexefile}','w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())" COMMENT "Shebangin ${pyfile_name}" + VERBATIM ) #on windows, python files need an extension to execute diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake index 569667b0e9..abf4dc4612 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake @@ -33,14 +33,13 @@ include(GrPython) # - GR_SWIG_DOCS_TARGET_DEPS ######################################################################## function(GR_SWIG_MAKE_DOCS output_file) - find_package(Doxygen) - if(DOXYGEN_FOUND) + if(ENABLE_DOXYGEN) #setup the input files variable list, quote formated set(input_files) unset(INPUT_PATHS) foreach(input_path ${ARGN}) - if (IS_DIRECTORY ${input_path}) #when input path is a directory + if(IS_DIRECTORY ${input_path}) #when input path is a directory file(GLOB input_path_h_files ${input_path}/*.h) else() #otherwise its just a file, no glob set(input_path_h_files ${input_path}) @@ -76,17 +75,18 @@ function(GR_SWIG_MAKE_DOCS output_file) #call the swig_doc script on the xml files add_custom_command( OUTPUT ${output_file} - DEPENDS ${input_files} ${OUTPUT_DIRECTORY}/xml/index.xml + DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py ${OUTPUT_DIRECTORY}/xml ${output_file} + COMMENT "Generating python docstrings for ${name}" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen ) - else(DOXYGEN_FOUND) + else(ENABLE_DOXYGEN) file(WRITE ${output_file} "\n") #no doxygen -> empty file - endif(DOXYGEN_FOUND) + endif(ENABLE_DOXYGEN) endfunction(GR_SWIG_MAKE_DOCS) ######################################################################## @@ -105,20 +105,35 @@ endfunction(GR_SWIG_MAKE_DOCS) macro(GR_SWIG_MAKE name) set(ifiles ${ARGN}) + # Shimming this in here to take care of a SWIG bug with handling + # vector<size_t> and vector<unsigned int> (on 32-bit machines) and + # vector<long unsigned int> (on 64-bit machines). Use this to test + # the size of size_t, then set SIZE_T_32 if it's a 32-bit machine + # or not if it's 64-bit. The logic in gr_type.i handles the rest. + INCLUDE(CheckTypeSize) + CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T) + CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT) + if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT}) + list(APPEND GR_SWIG_FLAGS -DSIZE_T_32) + endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT}) + #do swig doc generation if specified - if (GR_SWIG_DOC_FILE) + if(GR_SWIG_DOC_FILE) set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS}) - set(GR_SWIG_DOCS_TAREGT_DEPS ${GR_SWIG_TARGET_DEPS}) + list(APPEND GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS}) GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) - list(APPEND GR_SWIG_SOURCE_DEPS ${GR_SWIG_DOC_FILE}) + add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE}) + list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc ${GR_RUNTIME_SWIG_DOC_FILE}) endif() #append additional include directories find_package(PythonLibs 2) list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) - list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) - list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) + + #prepend local swig directories + list(INSERT GR_SWIG_INCLUDE_DIRS 0 ${CMAKE_CURRENT_SOURCE_DIR}) + list(INSERT GR_SWIG_INCLUDE_DIRS 0 ${CMAKE_CURRENT_BINARY_DIR}) #determine include dependencies for swig file execute_process( @@ -157,6 +172,9 @@ macro(GR_SWIG_MAKE name) include(UseSWIG) SWIG_ADD_MODULE(${name} python ${ifiles}) SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES}) + if(${name} STREQUAL "runtime_swig") + SET_TARGET_PROPERTIES(${SWIG_MODULE_runtime_swig_REAL_NAME} PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS") + endif(${name} STREQUAL "runtime_swig") endmacro(GR_SWIG_MAKE) @@ -204,21 +222,25 @@ file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py " import os, sys, re -include_matcher = re.compile('[#|%]include\\s*[<|\"](.*)[>|\"]') +i_include_matcher = re.compile('%(include|import)\\s*[<|\"](.*)[>|\"]') +h_include_matcher = re.compile('#(include)\\s*[<|\"](.*)[>|\"]') include_dirs = sys.argv[2].split(';') def get_swig_incs(file_path): + if file_path.endswith('.i'): matcher = i_include_matcher + else: matcher = h_include_matcher file_contents = open(file_path, 'r').read() - return include_matcher.findall(file_contents, re.MULTILINE) + return matcher.findall(file_contents, re.MULTILINE) def get_swig_deps(file_path, level): deps = [file_path] if level == 0: return deps - for inc_file in get_swig_incs(file_path): + for keyword, inc_file in get_swig_incs(file_path): for inc_dir in include_dirs: inc_path = os.path.join(inc_dir, inc_file) if not os.path.exists(inc_path): continue deps.extend(get_swig_deps(inc_path, level-1)) + break #found, we dont search in lower prio inc dirs return deps if __name__ == '__main__': diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrTest.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrTest.cmake index 6174c034e9..62caab4b51 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrTest.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrTest.cmake @@ -30,10 +30,10 @@ set(__INCLUDED_GR_TEST_CMAKE TRUE) # GR_TEST_TARGET_DEPS - built targets for the library path # GR_TEST_LIBRARY_DIRS - directories for the library path # GR_TEST_PYTHON_DIRS - directories for the python path +# GR_TEST_ENVIRONS - other environment key/value pairs ######################################################################## function(GR_ADD_TEST test_name) - if(WIN32) #Ensure that the build exe also appears in the PATH. list(APPEND GR_TEST_TARGET_DEPS ${ARGN}) @@ -50,6 +50,7 @@ function(GR_ADD_TEST test_name) endif(location) endforeach(target) + if(WIN32) #SWIG generates the python library files into a subdirectory. #Therefore, we must append this subdirectory into PYTHONPATH. #Only do this for the python directories matching the following: @@ -65,7 +66,8 @@ function(GR_ADD_TEST test_name) file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list? file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list? - set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}") + set(environs "VOLK_GENERIC=1" "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}") + list(APPEND environs ${GR_TEST_ENVIRONS}) #http://www.cmake.org/pipermail/cmake/2009-May/029464.html #Replaced this add test + set environs code with the shell script generation. @@ -74,18 +76,26 @@ function(GR_ADD_TEST test_name) #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}") if(UNIX) + set(LD_PATH_VAR "LD_LIBRARY_PATH") + if(APPLE) + set(LD_PATH_VAR "DYLD_LIBRARY_PATH") + endif() + set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH") - #set both LD and DYLD paths to cover multiple UNIX OS library paths - list(APPEND libpath "$LD_LIBRARY_PATH" "$DYLD_LIBRARY_PATH") + list(APPEND libpath "$${LD_PATH_VAR}") list(APPEND pypath "$PYTHONPATH") #replace list separator with the path separator string(REPLACE ";" ":" libpath "${libpath}") string(REPLACE ";" ":" pypath "${pypath}") - list(APPEND environs "PATH=${binpath}" "LD_LIBRARY_PATH=${libpath}" "DYLD_LIBRARY_PATH=${libpath}" "PYTHONPATH=${pypath}") + list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}") #generate a bat file that sets the environment and runs the test - find_program(SHELL sh) + if (CMAKE_CROSSCOMPILING) + set(SHELL "/bin/sh") + else(CMAKE_CROSSCOMPILING) + find_program(SHELL sh) + endif(CMAKE_CROSSCOMPILING) set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh) file(WRITE ${sh_file} "#!${SHELL}\n") #each line sets an environment variable diff --git a/gr-utils/python/utils/grcc b/gr-utils/python/utils/grcc index 8fb44c2c79..82db5435db 100755 --- a/gr-utils/python/utils/grcc +++ b/gr-utils/python/utils/grcc @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +import os +import sys +from optparse import OptionParser import warnings warnings.simplefilter('ignore') @@ -28,10 +31,8 @@ try: except ImportError: from gnuradio.grc.python.Platform import Platform -from optparse import OptionParser -import os, sys -class grcc: +class GRCC: def __init__(self, grcfile, out_dir): self.out_dir = out_dir self.platform = Platform() @@ -43,7 +44,9 @@ class grcc: self.fg.validate() if not self.fg.is_valid(): - raise StandardError("Compilation error") + raise StandardError("\n\n".join( + ["Validation failed:"] + self.fg.get_error_messages() + )) self.gen = self.platform.get_generator()(self.fg, out_dir) self.gen.write() @@ -52,7 +55,8 @@ class grcc: progname = self.fg.get_option('id') os.system("{0}/{1}.py".format(self.out_dir, progname)) -if __name__ == "__main__": + +def main(): usage="%prog: [options] filename" description = "Compiles a GRC file (.grc) into a GNU Radio Python program. The program is stored in ~/.grc_gnuradio by default, but this location can be changed with the -d option." @@ -63,15 +67,20 @@ if __name__ == "__main__": help="Run the program after compiling [default=%default]") (options, args) = parser.parse_args () - if(len(args) != 1): + if len(args) != 1: sys.stderr.write("Please specify a GRC file name to compile.\n") sys.exit(1) try: - g = grcc(args[0], options.directory+"/") - except: - sys.stderr.write("Error during file compilation.\n"); + g = GRCC(args[0], options.directory + "/") + except Exception as e: + sys.stderr.write(str(e) + "\n") + sys.stderr.write("Error during file compilation.\n") sys.exit(1) - if(options.execute): + if options.execute: g.exec_program() + + +if __name__ == "__main__": + main() diff --git a/gr-wxgui/python/wxgui/fft_window.py b/gr-wxgui/python/wxgui/fft_window.py index 86023e3f88..024200556e 100644 --- a/gr-wxgui/python/wxgui/fft_window.py +++ b/gr-wxgui/python/wxgui/fft_window.py @@ -336,8 +336,8 @@ class fft_window(wx.Panel, pubsub.pubsub): samples = numpy.fromstring(msg, numpy.float32)[:self.fft_size] #only take first frame num_samps = len(samples) #reorder fft - if self.real: samples = samples[:(num_samps+1)/2] - else: samples = numpy.concatenate((samples[num_samps/2+1:], samples[:(num_samps+1)/2])) + if self.real: samples = samples[:(num_samps+2)/2] + else: samples = numpy.concatenate((samples[(num_samps+1)/2:], samples[:(num_samps+2)/2])) self.samples = samples #peak hold calculation if self[PEAK_HOLD_KEY]: @@ -407,6 +407,6 @@ class fft_window(wx.Panel, pubsub.pubsub): #update y grid self.plotter.set_y_grid(ref_level-y_per_div*y_divs, ref_level, y_per_div) #update y units - self.plotter.set_y_label('Amplitude', 'dB') + self.plotter.set_y_label('Power', 'dB') #update plotter self.plotter.update() diff --git a/gr-wxgui/python/wxgui/fftsink_nongl.py b/gr-wxgui/python/wxgui/fftsink_nongl.py index be69e41578..c63f0fb268 100644 --- a/gr-wxgui/python/wxgui/fftsink_nongl.py +++ b/gr-wxgui/python/wxgui/fftsink_nongl.py @@ -136,17 +136,17 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): for tap in mywindow: power += tap*tap - self.c2mag = blocks.complex_to_mag(self.fft_size) + self.c2magsq = blocks.complex_to_mag_squared(self.fft_size) self.avg = grfilter.single_pole_iir_filter_ff(1.0, self.fft_size) # FIXME We need to add 3dB to all bins but the DC bin - self.log = blocks.nlog10_ff(20, self.fft_size, + self.log = blocks.nlog10_ff(10, self.fft_size, -20*math.log10(self.fft_size) # Adjust for number of bins -10*math.log10(power/self.fft_size) # Adjust for windowing loss -20*math.log10(ref_scale/2)) # Adjust for reference scale self.sink = blocks.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) - self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) + self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2magsq, self.avg, self.log, self.sink) self.win = fft_window(self, parent, size=size) self.set_average(self.average) @@ -183,17 +183,17 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): for tap in mywindow: power += tap*tap - self.c2mag = blocks.complex_to_mag(self.fft_size) + self.c2magsq = blocks.complex_to_mag_squared(self.fft_size) self.avg = grfilter.single_pole_iir_filter_ff(1.0, self.fft_size) # FIXME We need to add 3dB to all bins but the DC bin - self.log = blocks.nlog10_ff(20, self.fft_size, + self.log = blocks.nlog10_ff(10, self.fft_size, -20*math.log10(self.fft_size) # Adjust for number of bins -10*math.log10(power/self.fft_size) # Adjust for windowing loss -20*math.log10(ref_scale/2)) # Adjust for reference scale self.sink = blocks.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) - self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) + self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2magsq, self.avg, self.log, self.sink) self.win = fft_window(self, parent, size=size) self.set_average(self.average) diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index cbf4c9945d..3714401bbb 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -67,6 +67,10 @@ CPACK_COMPONENT("grc" # Create and install the grc conf file ######################################################################## file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${GRC_BLOCKS_DIR} blocksdir) +if(CMAKE_INSTALL_PREFIX STREQUAL "/usr") + # linux binary installs: append blocks dir with prefix /usr/local + set(blocksdir ${blocksdir}:/usr/local/${GRC_BLOCKS_DIR}) +endif(CMAKE_INSTALL_PREFIX STREQUAL "/usr") if (APPLE) set(GRC_XTERM_EXE "xterm") diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py index 02d1b112c4..fb25b46821 100644 --- a/grc/base/FlowGraph.py +++ b/grc/base/FlowGraph.py @@ -17,11 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +import time from . import odict from Element import Element from .. gui import Messages from . Constants import FLOW_GRAPH_FILE_FORMAT_VERSION + class FlowGraph(Element): def __init__(self, platform): @@ -36,6 +38,8 @@ class FlowGraph(Element): """ #initialize Element.__init__(self, platform) + self._elements = [] + self._timestamp = time.ctime() #inital blank import self.import_data() @@ -51,12 +55,14 @@ class FlowGraph(Element): """ index = 0 while True: - id = '%s_%d'%(base_id, index) - index = index + 1 + id = '%s_%d' % (base_id, index) + index += 1 #make sure that the id is not used by another block if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id - def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id')) + def __str__(self): + return 'FlowGraph - %s(%s)' % (self.get_option('title'), self.get_option('id')) + def rewrite(self): def refactor_bus_structure(): @@ -242,9 +248,8 @@ class FlowGraph(Element): Returns: a nested data odict """ - import time n = odict() - n['timestamp'] = time.ctime() + n['timestamp'] = self._timestamp n['block'] = [block.export_data() for block in self.get_blocks()] n['connection'] = [connection.export_data() for connection in self.get_connections()] instructions = odict({ @@ -273,6 +278,7 @@ class FlowGraph(Element): file_format = 0 #use blank data if none provided fg_n = n and n.find('flow_graph') or odict() + self._timestamp = fg_n.find('timestamp') or time.ctime() blocks_n = fg_n.findall('block') connections_n = fg_n.findall('connection') #create option block @@ -384,7 +390,7 @@ def _initialize_dummy_block(block, block_n): """ block._key = block_n.find('key') block.is_dummy_block = lambda: True - block.is_valid = lambda: False + block.is_valid = lambda: False block.get_enabled = lambda: False for param_n in block_n.findall('param'): if param_n['key'] not in block.get_param_keys(): @@ -393,7 +399,7 @@ def _initialize_dummy_block(block, block_n): def _dummy_block_add_port(block, key, dir): - """This is so ugly... Add a port to a dummy-fied block""" + """This is so ugly... Add a port to a dummy-field block""" port_n = odict({'name': '?', 'key': key, 'type': ''}) port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir) if port.is_source(): diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml index 0c3a804fd7..c1c94e4e24 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -58,17 +58,17 @@ else: self.stop(); self.wait()</callback> <param> <name>Generate Options</name> <key>generate_options</key> - <value>wx_gui</value> + <value>qt_gui</value> <type>enum</type> <option> - <name>WX GUI</name> - <key>wx_gui</key> - </option> - <option> <name>QT GUI</name> <key>qt_gui</key> </option> <option> + <name>WX GUI</name> + <key>wx_gui</key> + </option> + <option> <name>No GUI</name> <key>no_gui</key> </option> diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml index 37e132c34c..b022fa3d0d 100644 --- a/grc/blocks/pad_sink.xml +++ b/grc/blocks/pad_sink.xml @@ -7,9 +7,7 @@ <block> <name>Pad Sink</name> <key>pad_sink</key> - <make>#if str($type) == "message" -None;self.message_port_register_hier_in($label) -#end if</make> + <make></make> <param> <name>Label</name> <key>label</key> diff --git a/grc/blocks/pad_source.xml b/grc/blocks/pad_source.xml index 745e48c080..c0fb19eee7 100644 --- a/grc/blocks/pad_source.xml +++ b/grc/blocks/pad_source.xml @@ -7,9 +7,7 @@ <block> <name>Pad Source</name> <key>pad_source</key> - <make>#if str($type) == "message" -None;self.message_port_register_hier_out($label) -#end if</make> + <make></make> <param> <name>Label</name> <key>label</key> diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index f8963fa472..6c56a94e9c 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -495,9 +495,11 @@ class ActionHandler: ExecFlowGraphThread(self) elif action == Actions.FLOW_GRAPH_KILL: if self.get_page().get_proc(): - try: self.get_page().get_proc().kill() - except: print "could not kill process: %d"%self.get_page().get_proc().pid - elif action == Actions.PAGE_CHANGE: #pass and run the global actions + try: + self.get_page().get_proc().kill() + except: + print "could not kill process: %d" % self.get_page().get_proc().pid + elif action == Actions.PAGE_CHANGE: # pass and run the global actions pass elif action == Actions.RELOAD_BLOCKS: self.platform.load_blocks() @@ -583,7 +585,7 @@ class ActionHandler: sensitive = self.get_flow_graph().is_valid() and not self.get_page().get_proc() Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive) Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive) - Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() != None) + Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() is not None) class ExecFlowGraphThread(Thread): """Execute the flow graph as a new process and wait on it to finish.""" @@ -619,13 +621,14 @@ class ExecFlowGraphThread(Thread): """ #handle completion r = "\n" - while(r): + while r: gobject.idle_add(Messages.send_verbose_exec, r) r = os.read(self.p.stdout.fileno(), 1024) + self.p.poll() gobject.idle_add(self.done) def done(self): """Perform end of execution tasks.""" - Messages.send_end_exec() + Messages.send_end_exec(self.p.returncode) self.page.set_proc(None) self.update_exec_stop() diff --git a/grc/gui/Block.py b/grc/gui/Block.py index 1a32f6c2ba..9b8d3b1b56 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -25,7 +25,7 @@ from Constants import BORDER_PROXIMITY_SENSITIVITY from Constants import \ BLOCK_LABEL_PADDING, \ PORT_SEPARATION, LABEL_SEPARATION, \ - PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS + PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS, BLOCK_FONT, PARAM_FONT import Actions import pygtk pygtk.require('2.0') @@ -34,7 +34,7 @@ import pango BLOCK_MARKUP_TMPL="""\ #set $foreground = $block.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>""" +<span foreground="$foreground" font_desc="$font"><b>$encode($block.get_name())</b></span>""" class Block(Element): """The graphical signal block.""" @@ -146,11 +146,13 @@ class Block(Element): #create the main layout layout = gtk.DrawingArea().create_pango_layout('') layouts.append(layout) - layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self)) + layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, font=BLOCK_FONT)) self.label_width, self.label_height = layout.get_pixel_size() #display the params if self.is_dummy_block(): - markups = ['<span foreground="black" font_desc="Sans 7.5"><b>key: </b>{}</span>'.format(self._key)] + markups = [ + '<span foreground="black" font_desc="$font"><b>key: </b>{key}</span>'.format(font=PARAM_FONT, key=self._key) + ] else: markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')] if markups: diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py index 7db291df99..0dc6279fd2 100644 --- a/grc/gui/Constants.py +++ b/grc/gui/Constants.py @@ -41,6 +41,13 @@ MIN_DIALOG_HEIGHT = 500 ##default sizes DEFAULT_BLOCKS_WINDOW_WIDTH = 100 DEFAULT_REPORTS_WINDOW_WIDTH = 100 +## flow-graph canvas fonts +FONT_FAMILY = "Sans" +FONT_SIZE = 8 +BLOCK_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE) +PORT_FONT = BLOCK_FONT +PARAM_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE - 0.5) + ##The size of the state saving cache in the flow graph (for undo/redo functionality) STATE_CACHE_SIZE = 42 diff --git a/grc/gui/Messages.py b/grc/gui/Messages.py index f220b6dd06..90f508d770 100644 --- a/grc/gui/Messages.py +++ b/grc/gui/Messages.py @@ -24,15 +24,17 @@ import os ## A list of functions that can receive a message. MESSENGERS_LIST = list() + def register_messenger(messenger): """ Append the given messenger to the list of messengers. Args: - messenger: a method thats takes a string + messenger: a method that takes a string """ MESSENGERS_LIST.append(messenger) + def send(message): """ Give the message to each of the messengers. @@ -102,8 +104,8 @@ def send_start_exec(file_path): def send_verbose_exec(verbose): send(verbose) -def send_end_exec(): - send('\n>>> Done\n') +def send_end_exec(returncode=0): + send('\n>>> Done%s\n' % (" (return code %s)" % returncode if returncode else "")) ################# functions for saving flow graphs ######################################## def send_fail_save(file_path): diff --git a/grc/gui/Param.py b/grc/gui/Param.py index ef1c154933..2ef8603a83 100644 --- a/grc/gui/Param.py +++ b/grc/gui/Param.py @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import Utils from Element import Element +from . Constants import PARAM_FONT import pygtk pygtk.require('2.0') import gtk @@ -196,7 +197,7 @@ class FileParam(EntryParam): PARAM_MARKUP_TMPL="""\ #set $foreground = $param.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>""" +<span foreground="$foreground" font_desc="$font"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>""" PARAM_LABEL_MARKUP_TMPL="""\ #set $foreground = $modified and 'blue' or $param.is_valid() and 'black' or 'red' @@ -261,4 +262,4 @@ class Param(Element): Returns: a pango markup string """ - return Utils.parse_template(PARAM_MARKUP_TMPL, param=self) + return Utils.parse_template(PARAM_MARKUP_TMPL, param=self, font=PARAM_FONT) diff --git a/grc/gui/Port.py b/grc/gui/Port.py index 364ca6a5b9..2a87573911 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -21,7 +21,7 @@ from Element import Element from Constants import \ PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \ CONNECTOR_EXTENSION_INCREMENT, \ - PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH + PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT import Utils import Actions import Colors @@ -29,10 +29,8 @@ import pygtk pygtk.require('2.0') import gtk -PORT_HIDDEN_MARKUP_TMPL="""\ -<span foreground="black" font_desc="Sans 7.5"> </span>""" PORT_MARKUP_TMPL="""\ -<span foreground="black" font_desc="Sans 7.5">$encode($port.get_name())</span>""" +<span foreground="black" font_desc="$font">$encode($port.get_name())</span>""" class Port(Element): @@ -115,7 +113,7 @@ class Port(Element): self._bg_color = Colors.get_color(self.get_color()) #create the layout layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self)) + layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self, font=PORT_FONT)) self.w, self.h = layout.get_pixel_size() self.W, self.H = 2*PORT_LABEL_PADDING + self.w, 2*PORT_LABEL_PADDING+self.h self.H = self.modify_height(self.H) diff --git a/grc/python/CMakeLists.txt b/grc/python/CMakeLists.txt index 4832dd897e..41d965e89c 100644 --- a/grc/python/CMakeLists.txt +++ b/grc/python/CMakeLists.txt @@ -19,7 +19,6 @@ ######################################################################## GR_PYTHON_INSTALL(FILES - convert_hier.py expr_utils.py extract_docs.py Block.py diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py index daec2d4310..977200da66 100644 --- a/grc/python/FlowGraph.py +++ b/grc/python/FlowGraph.py @@ -58,34 +58,62 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): #return from cache return self._eval_cache[my_hash] - def get_io_signaturev(self, direction): + def get_hier_block_stream_io(self, direction): """ - Get a list of io signatures for this flow graph. + Get a list of stream io signatures for this flow graph. Args: direction: a string of 'in' or 'out' Returns: - a list of dicts with: type, label, vlen, size + a list of dicts with: type, label, vlen, size, optional """ - sorted_pads = { - 'in': self.get_pad_sources(), - 'out': self.get_pad_sinks(), - }[direction] - # we only want stream ports - sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads); - expanded_pads = []; - for i in sorted_pads: - for j in range(i.get_param('num_streams').get_evaluated()): - expanded_pads.append(i); - #load io signature - return [{ - 'label': str(pad.get_param('label').get_evaluated()), - 'type': str(pad.get_param('type').get_evaluated()), - 'vlen': str(pad.get_param('vlen').get_value()), - 'size': pad.get_param('type').get_opt('size'), - 'optional': bool(pad.get_param('optional').get_evaluated()), - } for pad in expanded_pads] + return filter(lambda p: p['type'] != "message", + self.get_hier_block_io(direction)) + + def get_hier_block_message_io(self, direction): + """ + Get a list of message io signatures for this flow graph. + + Args: + direction: a string of 'in' or 'out' + + Returns: + a list of dicts with: type, label, vlen, size, optional + """ + return filter(lambda p: p['type'] == "message", + self.get_hier_block_io(direction)) + + def get_hier_block_io(self, direction): + """ + Get a list of io ports for this flow graph. + + Args: + direction: a string of 'in' or 'out' + + Returns: + a list of dicts with: type, label, vlen, size, optional + """ + pads = self.get_pad_sources() if direction in ('sink', 'in') else \ + self.get_pad_sinks() if direction in ('source', 'out') else [] + ports = [] + for pad in pads: + master = { + 'label': str(pad.get_param('label').get_evaluated()), + 'type': str(pad.get_param('type').get_evaluated()), + 'vlen': str(pad.get_param('vlen').get_value()), + 'size': pad.get_param('type').get_opt('size'), + 'optional': bool(pad.get_param('optional').get_evaluated()), + } + num_ports = pad.get_param('num_streams').get_evaluated() + if num_ports > 1: + for i in xrange(num_ports): + clone = master.copy() + clone['label'] += str(i) + ports.append(clone) + else: + ports.append(master) + return ports def get_pad_sources(self): """ @@ -118,20 +146,14 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): key_offset = 0 pads = self.get_pad_sources() if port.is_source() else self.get_pad_sinks() for pad in pads: + if pad.get_param('type').get_evaluated() == "message": + continue if port.get_parent() == pad: return str(key_offset + int(port.get_key())) # assuming we have either only sources or sinks key_offset += len(pad.get_ports()) return -1 - def get_msg_pad_sources(self): - ps = self.get_pad_sources(); - return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); - - def get_msg_pad_sinks(self): - ps = self.get_pad_sinks(); - return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); - def get_imports(self): """ Get a set of all import statments in this flow graph namespace. diff --git a/grc/python/Generator.py b/grc/python/Generator.py index 4a496b7c0f..24d943d28d 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -23,14 +23,18 @@ import subprocess import tempfile from distutils.spawn import find_executable from Cheetah.Template import Template -import expr_utils -from Constants import \ - TOP_BLOCK_FILE_MODE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, FLOW_GRAPH_TEMPLATE, XTERM_EXECUTABLE -import convert_hier + from .. gui import Messages +from .. base import ParseXML +from .. base import odict + +from . Constants import TOP_BLOCK_FILE_MODE, FLOW_GRAPH_TEMPLATE, \ + XTERM_EXECUTABLE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, BLOCK_DTD +from . import expr_utils class Generator(object): + """Adaptor for various generators (uses generate_options)""" def __init__(self, flow_graph, file_path): """ @@ -39,44 +43,67 @@ class Generator(object): Args: flow_graph: the flow graph object + file_path: the path to the grc file + """ + self._generate_options = flow_graph.get_option('generate_options') + if self._generate_options == 'hb': + self._generator = HierBlockGenerator(flow_graph, file_path) + else: + self._generator = TopBlockGenerator(flow_graph, file_path) + + def get_generate_options(self): + return self._generate_options + + def __getattr__(self, item): + """get all other attrib from actual generator object""" + return getattr(self._generator, item) + + +class TopBlockGenerator(object): + + def __init__(self, flow_graph, file_path): + """ + Initialize the top block generator object. + + Args: + flow_graph: the flow graph object file_path: the path to write the file to """ self._flow_graph = flow_graph self._generate_options = self._flow_graph.get_option('generate_options') - if self._generate_options == 'hb': - self._mode = HIER_BLOCK_FILE_MODE - dirname = HIER_BLOCKS_LIB_DIR - else: - self._mode = TOP_BLOCK_FILE_MODE - dirname = os.path.dirname(file_path) - #handle the case where the directory is read-only - #in this case, use the system's temp directory - if not os.access(dirname, os.W_OK): - dirname = tempfile.gettempdir() + self._mode = TOP_BLOCK_FILE_MODE + dirname = os.path.dirname(file_path) + #handle the case where the directory is read-only + #in this case, use the system's temp directory + if not os.access(dirname, os.W_OK): + dirname = tempfile.gettempdir() filename = self._flow_graph.get_option('id') + '.py' self._file_path = os.path.join(dirname, filename) - def get_file_path(self): return self._file_path + def get_file_path(self): + return self._file_path def write(self): + """generate output and write it to files""" #do throttle warning throttling_blocks = filter(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks()) if not throttling_blocks and self._generate_options != 'hb': - Messages.send_warning('''\ -This flow graph may not have flow control: no audio or RF hardware blocks found. \ -Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') + Messages.send_warning("This flow graph may not have flow control: " + "no audio or RF hardware blocks found. " + "Add a Misc->Throttle block to your flow " + "graph to avoid CPU congestion.") if len(throttling_blocks) > 1: keys = set(map(lambda b: b.get_key(), throttling_blocks)) if len(keys) > 1 and 'blocks_throttle' in keys: - Messages.send_warning('''\ -This flow graph contains a throttle block and another rate limiting block, e.g. a hardware source or sink. \ -This is usually undesired. Consider removing the throttle block.''') + Messages.send_warning("This flow graph contains a throttle " + "block and another rate limiting block, " + "e.g. a hardware source or sink. " + "This is usually undesired. Consider " + "removing the throttle block.") #generate - open(self.get_file_path(), 'w').write(str(self)) - if self._generate_options == 'hb': - #convert hier block to xml wrapper - convert_hier.convert_hier(self._flow_graph, self.get_file_path()) - os.chmod(self.get_file_path(), self._mode) + open(self.get_file_path(), 'w').write( + self._build_python_code_from_template() + ) def get_popen(self): """ @@ -101,10 +128,12 @@ This is usually undesired. Consider removing the throttle block.''') if self._generate_options == 'no_gui' and xterm_executable: cmds = [xterm_executable, '-e'] + cmds - p = subprocess.Popen(args=cmds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, universal_newlines=True) + p = subprocess.Popen( + args=cmds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + shell=False, universal_newlines=True) return p - def __str__(self): + def _build_python_code_from_template(self): """ Convert the flow graph to python code. @@ -119,10 +148,14 @@ This is usually undesired. Consider removing the throttle block.''') #list of blocks not including variables and imports and parameters and disabled def _get_block_sort_text(block): code = block.get_make().replace(block.get_id(), ' ') - try: code += block.get_param('notebook').get_value() #older gui markup w/ wxgui - except: pass - try: code += block.get_param('gui_hint').get_value() #newer gui markup w/ qtgui - except: pass + try: + code += block.get_param('notebook').get_value() #older gui markup w/ wxgui + except: + pass + try: + code += block.get_param('gui_hint').get_value() #newer gui markup w/ qtgui + except: + pass return code blocks = expr_utils.sort_objects( self._flow_graph.get_enabled_blocks(), @@ -137,7 +170,7 @@ This is usually undesired. Consider removing the throttle block.''') #list of variable names var_ids = [var.get_id() for var in parameters + variables] #prepend self. - replace_dict = dict([(var_id, 'self.%s'%var_id) for var_id in var_ids]) + replace_dict = dict([(var_id, 'self.%s' % var_id) for var_id in var_ids]) #list of callbacks callbacks = [ expr_utils.expr_replace(cb, replace_dict) @@ -155,7 +188,7 @@ This is usually undesired. Consider removing the throttle block.''') 'flow_graph': self._flow_graph, 'variables': variables, 'parameters': parameters, - 'monitors': monitors, + 'monitors': monitors, 'blocks': blocks, 'connections': connections, 'messages': messages, @@ -166,3 +199,116 @@ This is usually undesired. Consider removing the throttle block.''') #build the template t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace) return str(t) + + +class HierBlockGenerator(TopBlockGenerator): + """Extends the top block generator to also generate a block XML file""" + + def __init__(self, flow_graph, file_path): + """ + Initialize the hier block generator object. + + Args: + flow_graph: the flow graph object + file_path: where to write the py file (the xml goes into HIER_BLOCK_LIB_DIR) + """ + TopBlockGenerator.__init__(self, flow_graph, file_path) + self._mode = HIER_BLOCK_FILE_MODE + self._file_path = os.path.join(HIER_BLOCKS_LIB_DIR, + self._flow_graph.get_option('id') + '.py') + self._file_path_xml = self._file_path + '.xml' + + def get_file_path_xml(self): + return self._file_path_xml + + def write(self): + """generate output and write it to files""" + TopBlockGenerator.write(self) + ParseXML.to_file(self._build_block_n_from_flow_graph_io(), self.get_file_path_xml()) + ParseXML.validate_dtd(self.get_file_path_xml(), BLOCK_DTD) + + def _build_block_n_from_flow_graph_io(self): + """ + Generate a block XML nested data from the flow graph IO + + Returns: + a xml node tree + """ + #extract info from the flow graph + block_key = self._flow_graph.get_option('id') + parameters = self._flow_graph.get_parameters() + + def var_or_value(name): + if name in map(lambda p: p.get_id(), parameters): + return "$"+name + return name + + #build the nested data + block_n = odict() + block_n['name'] = self._flow_graph.get_option('title') or \ + self._flow_graph.get_option('id').replace('_', ' ').title() + block_n['key'] = block_key + block_n['category'] = self._flow_graph.get_option('category') + block_n['import'] = 'execfile("{0}")'.format(self.get_file_path()) + #make data + if parameters: + block_n['make'] = '{cls}(\n {kwargs},\n)'.format( + cls=block_key, + kwargs=',\n '.join( + '{key}=${key}'.format(key=param.get_id()) for param in parameters + ), + ) + else: + block_n['make'] = '{cls}()'.format(cls=block_key) + #callback data + block_n['callback'] = [ + 'set_{key}(${key})'.format(key=param.get_id()) for param in parameters + ] + + # Parameters + block_n['param'] = list() + for param in parameters: + param_n = odict() + param_n['name'] = param.get_param('label').get_value() or param.get_id() + param_n['key'] = param.get_id() + param_n['value'] = param.get_param('value').get_value() + param_n['type'] = 'raw' + block_n['param'].append(param_n) + + # bus stuff + if self._flow_graph.get_bussink(): + block_n['bus_sink'] = '1' + if self._flow_graph.get_bussrc(): + block_n['bus_source'] = '1' + + # sink/source ports + for direction in ('sink', 'source'): + block_n[direction] = list() + for port in self._flow_graph.get_hier_block_io(direction): + port_n = odict() + port_n['name'] = port['label'] + port_n['type'] = port['type'] + if port['type'] != "message": + port_n['vlen'] = var_or_value(port['vlen']) + if port['optional']: + port_n['optional'] = '1' + block_n[direction].append(port_n) + + # more bus stuff + bus_struct_sink = self._flow_graph.get_bus_structure_sink() + if bus_struct_sink: + block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value() + bus_struct_src = self._flow_graph.get_bus_structure_src() + if bus_struct_src: + block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value() + + # documentation + block_n['doc'] = "\n".join(field for field in ( + self._flow_graph.get_option('author'), + self._flow_graph.get_option('description'), + self.get_file_path() + ) if field) + block_n['grc_source'] = str(self._flow_graph.grc_file_path) + + n = {'block': block_n} + return n diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py deleted file mode 100644 index cf4c04a149..0000000000 --- a/grc/python/convert_hier.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -Copyright 2008-2011 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Constants import BLOCK_DTD -from .. base import ParseXML -from .. base import odict - -def convert_hier(flow_graph, python_file): - #extract info from the flow graph - input_sigs = flow_graph.get_io_signaturev('in') - output_sigs = flow_graph.get_io_signaturev('out') - input_msgp = flow_graph.get_msg_pad_sources(); - output_msgp = flow_graph.get_msg_pad_sinks(); - parameters = flow_graph.get_parameters() - bussink = flow_graph.get_bussink() - bussrc = flow_graph.get_bussrc() - bus_struct_sink = flow_graph.get_bus_structure_sink() - bus_struct_src = flow_graph.get_bus_structure_src() - block_key = flow_graph.get_option('id') - block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title() - block_category = flow_graph.get_option('category') - block_desc = flow_graph.get_option('description') - block_author = flow_graph.get_option('author') - #build the nested data - block_n = odict() - block_n['name'] = block_name - block_n['key'] = block_key - block_n['category'] = block_category - block_n['import'] = 'execfile("%s")'%python_file - #make data - if parameters: block_n['make'] = '%s(\n %s,\n)'%( - block_key, - ',\n '.join(['%s=$%s'%(param.get_id(), param.get_id()) for param in parameters]), - ) - else: block_n['make'] = '%s()'%block_key - #callback data - block_n['callback'] = ['set_%s($%s)'%(param.get_id(), param.get_id()) for param in parameters] - #param data - params_n = list() - for param in parameters: - param_n = odict() - param_n['name'] = param.get_param('label').get_value() or param.get_id() - param_n['key'] = param.get_id() - param_n['value'] = param.get_param('value').get_value() - param_n['type'] = 'raw' - params_n.append(param_n) - block_n['param'] = params_n - #sink data stream ports - if bussink: - block_n['bus_sink'] = '1'; - if bussrc: - block_n['bus_source'] = '1'; - block_n['sink'] = list() - for input_sig in input_sigs: - sink_n = odict() - sink_n['name'] = input_sig['label'] - sink_n['type'] = input_sig['type'] - sink_n['vlen'] = var_or_value(input_sig['vlen'], parameters) - if input_sig['optional']: sink_n['optional'] = '1' - block_n['sink'].append(sink_n) - #sink data msg ports - for input_sig in input_msgp: - sink_n = odict() - sink_n['name'] = input_sig.get_param("label").get_value(); - sink_n['type'] = "message" - sink_n['optional'] = input_sig.get_param("optional").get_value(); - block_n['sink'].append(sink_n) - #source data stream ports - block_n['source'] = list() - if bus_struct_sink: - block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value(); - if bus_struct_src: - block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value(); - for output_sig in output_sigs: - source_n = odict() - source_n['name'] = output_sig['label'] - source_n['type'] = output_sig['type'] - source_n['vlen'] = var_or_value(output_sig['vlen'], parameters) - if output_sig['optional']: source_n['optional'] = '1' - block_n['source'].append(source_n) - #source data msg ports - for output_sig in output_msgp: - source_n = odict() - source_n['name'] = output_sig.get_param("label").get_value(); - source_n['type'] = "message" - source_n['optional'] = output_sig.get_param("optional").get_value(); - block_n['source'].append(source_n) - #doc data - block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) - block_n['grc_source'] = "%s"%(flow_graph.grc_file_path) - #write the block_n to file - xml_file = python_file + '.xml' - ParseXML.to_file({'block': block_n}, xml_file) - ParseXML.validate_dtd(xml_file, BLOCK_DTD) - - -def var_or_value(name, parameters): - if name in map(lambda p: p.get_id(), parameters): - return "$"+name - return name
\ No newline at end of file diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index bee9c68af5..b07c296d09 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -90,8 +90,8 @@ class $(class_name)(gr.top_block): def __init__($param_str): gr.top_block.__init__(self, "$title") #elif $generate_options == 'hb' - #set $in_sigs = $flow_graph.get_io_signaturev('in') - #set $out_sigs = $flow_graph.get_io_signaturev('out') + #set $in_sigs = $flow_graph.get_hier_block_stream_io('in') + #set $out_sigs = $flow_graph.get_hier_block_stream_io('out') class $(class_name)(gr.hier_block2): #def make_io_sig($io_sigs) #set $size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in $io_sigs] @@ -110,6 +110,12 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) $make_io_sig($in_sigs), $make_io_sig($out_sigs), ) + #for $pad in $flow_graph.get_hier_block_message_io('in') + self.message_port_register_hier_out("$pad['label']") + #end for + #for $pad in $flow_graph.get_hier_block_message_io('out') + self.message_port_register_hier_in("$pad['label']") + #end for #end if ######################################################## ##Create Parameters @@ -208,11 +214,11 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) #end for ######################################################## -##Create Asynch Message Connections +##Create Message Connections ######################################################## #if $messages2 $DIVIDER - # Asynch Message Connections + # Message Connections $DIVIDER #end if #for $msg in $messages2 diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc index 074d1e7be4..9bc1842c63 100644 --- a/volk/apps/volk_profile.cc +++ b/volk/apps/volk_profile.cc @@ -37,6 +37,49 @@ namespace fs = boost::filesystem; +void write_json(std::ofstream &json_file, std::vector<volk_test_results_t> results) { + json_file << "{" << std::endl; + json_file << " \"volk_tests\": [" << std::endl; + size_t len = results.size(); + size_t i = 0; + BOOST_FOREACH(volk_test_results_t &result, results) { + json_file << " {" << std::endl; + json_file << " \"name\": \"" << result.name << "\"," << std::endl; + json_file << " \"vlen\": " << result.vlen << "," << std::endl; + json_file << " \"iter\": " << result.iter << "," << std::endl; + json_file << " \"best_arch_a\": \"" << result.best_arch_a + << "\"," << std::endl; + json_file << " \"best_arch_u\": \"" << result.best_arch_u + << "\"," << std::endl; + json_file << " \"results\": {" << std::endl; + size_t results_len = result.results.size(); + size_t ri = 0; + typedef std::pair<std::string, volk_test_time_t> tpair; + BOOST_FOREACH(tpair pair, result.results) { + volk_test_time_t time = pair.second; + json_file << " \"" << time.name << "\": {" << std::endl; + json_file << " \"name\": \"" << time.name << "\"," << std::endl; + json_file << " \"time\": " << time.time << "," << std::endl; + json_file << " \"units\": \"" << time.units << "\"" << std::endl; + json_file << " }" ; + if(ri+1 != results_len) { + json_file << ","; + } + json_file << std::endl; + ri++; + } + json_file << " }" << std::endl; + json_file << " }"; + if(i+1 != len) { + json_file << ","; + } + json_file << std::endl; + i++; + } + json_file << " ]" << std::endl; + json_file << "}" << std::endl; +} + int main(int argc, char *argv[]) { // Adding program options boost::program_options::options_description desc("Options"); @@ -49,6 +92,9 @@ int main(int argc, char *argv[]) { ("tests-regex,R", boost::program_options::value<std::string>(), "Run tests matching regular expression.") + ("json,j", + boost::program_options::value<std::string>(), + "JSON output file") ; // Handle the options that were given @@ -56,6 +102,8 @@ int main(int argc, char *argv[]) { bool benchmark_mode; std::string kernel_regex; bool store_results = true; + std::ofstream json_file; + try { boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); boost::program_options::notify(vm); @@ -83,9 +131,14 @@ int main(int argc, char *argv[]) { return 0; } + if ( vm.count("json") ) + { + json_file.open( vm["json"].as<std::string>().c_str() ); + } + // Run tests - std::vector<std::string> results; + std::vector<volk_test_results_t> results; //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex); //VOLK_PROFILE(volk_16i_branch_4_state_8, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex); @@ -104,16 +157,25 @@ int main(int argc, char *argv[]) { //VOLK_PROFILE(volk_16i_max_star_horizontal_16i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); //VOLK_PROFILE(volk_16i_permute_and_scalar_add, 1e-4, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); //VOLK_PROFILE(volk_16i_x4_quad_max_star_16i, 1e-4, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); - VOLK_PROFILE(volk_16u_byteswap, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); + VOLK_PUPPET_PROFILE(volk_16u_byteswappuppet_16u, volk_16u_byteswap, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_accumulator_s32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_x2_add_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32fc_32f_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_log2_32f, 1.5e-1, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_expfast_32f, 1e-1, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_x2_pow_32f, 1e-2, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_sin_32f, 1e-6, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_cos_32f, 1e-6, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_tan_32f, 1e-6, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_atan_32f, 1e-3, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_asin_32f, 1e-3, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_acos_32f, 1e-3, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32fc_s32f_power_32fc, 1e-4, 0, 204602, 50, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_s32f_calc_spectral_noise_floor_32f, 1e-4, 20.0, 204602, 1000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32fc_s32f_atan2_32f, 1e-4, 10.0, 204602, 100, &results, benchmark_mode, kernel_regex); //VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); - VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 204602, 100, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32fc_deinterleave_32f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32fc_deinterleave_64f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32fc_s32f_deinterleave_real_16i, 0, 32768, 204602, 10000, &results, benchmark_mode, kernel_regex); @@ -157,13 +219,13 @@ int main(int argc, char *argv[]) { VOLK_PROFILE(volk_32i_x2_and_32i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32i_s32f_convert_32f, 1e-4, 100, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32i_x2_or_32i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); - VOLK_PROFILE(volk_32u_byteswap, 0, 0, 204602, 2000, &results, benchmark_mode, kernel_regex); - //VOLK_PROFILE(volk_32u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); + VOLK_PUPPET_PROFILE(volk_32u_byteswappuppet_32u, volk_32u_byteswap, 0, 0, 204602, 2000, &results, benchmark_mode, kernel_regex); + VOLK_PUPPET_PROFILE(volk_32u_popcntpuppet_32u, volk32u_popcnt_32u, 0, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_64f_convert_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_64f_x2_max_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_64f_x2_min_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); - VOLK_PROFILE(volk_64u_byteswap, 0, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); - //VOLK_PROFILE(volk_64u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); + VOLK_PUPPET_PROFILE(volk_64u_byteswappuppet_64u, volk_64u_byteswap, 0, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); + VOLK_PUPPET_PROFILE(volk_64u_popcntpuppet_64u, volk_64u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_8ic_deinterleave_16i_x2, 0, 0, 204602, 3000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_8ic_s32f_deinterleave_32f_x2, 1e-4, 100, 204602, 3000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_8ic_deinterleave_real_16i, 0, 256, 204602, 3000, &results, benchmark_mode, kernel_regex); @@ -178,6 +240,7 @@ int main(int argc, char *argv[]) { VOLK_PROFILE(volk_32f_s32f_multiply_32f, 1e-4, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_binary_slicer_32i, 0, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_binary_slicer_8i, 0, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_tanh_32f, 1e-6, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); // Until we can update the config on a kernel by kernel basis // do not overwrite volk_config when using a regex. @@ -204,8 +267,10 @@ int main(int argc, char *argv[]) { #the function name is followed by the preferred architecture.\n\ "; - BOOST_FOREACH(std::string result, results) { - config << result << std::endl; + BOOST_FOREACH(volk_test_results_t result, results) { + config << result.config_name << " " + << result.best_arch_a << " " + << result.best_arch_u << std::endl; } config.close(); } diff --git a/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h b/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h index 8c66892fd9..2656d766b8 100644 --- a/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h +++ b/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_32fc_dot_prod_32fc_H #define INCLUDED_volk_16i_32fc_dot_prod_32fc_H @@ -7,7 +29,6 @@ #ifdef LV_HAVE_GENERIC - static inline void volk_16i_32fc_dot_prod_32fc_generic(lv_32fc_t* result, const short* input, const lv_32fc_t * taps, unsigned int num_points) { static const int N_UNROLL = 4; @@ -36,7 +57,54 @@ static inline void volk_16i_32fc_dot_prod_32fc_generic(lv_32fc_t* result, const #endif /*LV_HAVE_GENERIC*/ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +static inline void volk_16i_32fc_dot_prod_32fc_neon(lv_32fc_t* result, const short* input, const lv_32fc_t * taps, unsigned int num_points) { + + unsigned ii; + unsigned quarter_points = num_points / 4; + lv_32fc_t* tapsPtr = (lv_32fc_t*) taps; + short* inputPtr = (short*) input; + lv_32fc_t accumulator_vec[4]; + + float32x4x2_t tapsVal, accumulator_val; + int16x4_t input16; + int32x4_t input32; + float32x4_t input_float, prod_re, prod_im; + + accumulator_val.val[0] = vdupq_n_f32(0.0); + accumulator_val.val[1] = vdupq_n_f32(0.0); + + for(ii = 0; ii < quarter_points; ++ii) { + tapsVal = vld2q_f32((float*)tapsPtr); + input16 = vld1_s16(inputPtr); + // widen 16-bit int to 32-bit int + input32 = vmovl_s16(input16); + // convert 32-bit int to float with scale + input_float = vcvtq_f32_s32(input32); + + prod_re = vmulq_f32(input_float, tapsVal.val[0]); + prod_im = vmulq_f32(input_float, tapsVal.val[1]); + + accumulator_val.val[0] = vaddq_f32(prod_re, accumulator_val.val[0]); + accumulator_val.val[1] = vaddq_f32(prod_im, accumulator_val.val[1]); + + tapsPtr += 4; + inputPtr += 4; + } + vst2q_f32((float*)accumulator_vec, accumulator_val); + accumulator_vec[0] += accumulator_vec[1]; + accumulator_vec[2] += accumulator_vec[3]; + accumulator_vec[0] += accumulator_vec[2]; + + for(ii = quarter_points * 4; ii < num_points; ++ii) { + accumulator_vec[0] += *(tapsPtr++) * (float)(*(inputPtr++)); + } + + *result = accumulator_vec[0]; +} +#endif /*LV_HAVE_NEON*/ #if LV_HAVE_SSE && LV_HAVE_MMX diff --git a/volk/kernels/volk/volk_16i_branch_4_state_8.h b/volk/kernels/volk/volk_16i_branch_4_state_8.h index cdfbc7ba13..4477245bbf 100644 --- a/volk/kernels/volk/volk_16i_branch_4_state_8.h +++ b/volk/kernels/volk/volk_16i_branch_4_state_8.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_branch_4_state_8_a_H #define INCLUDED_volk_16i_branch_4_state_8_a_H diff --git a/volk/kernels/volk/volk_16i_convert_8i.h b/volk/kernels/volk/volk_16i_convert_8i.h index 3789b2e4ab..6f16fa45d3 100644 --- a/volk/kernels/volk/volk_16i_convert_8i.h +++ b/volk/kernels/volk/volk_16i_convert_8i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_convert_8i_u_H #define INCLUDED_volk_16i_convert_8i_u_H @@ -116,6 +138,46 @@ static inline void volk_16i_convert_8i_a_sse2(int8_t* outputVector, const int16_ } #endif /* LV_HAVE_SSE2 */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Converts the input 16 bit integer data into 8 bit integer data + \param inputVector The 16 bit input data buffer + \param outputVector The 8 bit output data buffer + \param num_points The number of data values to be converted +*/ +static inline void volk_16i_convert_8i_neon(int8_t* outputVector, const int16_t* inputVector, unsigned int num_points){ + int8_t* outputVectorPtr = outputVector; + const int16_t* inputVectorPtr = inputVector; + unsigned int number = 0; + unsigned int sixteenth_points = num_points / 16; + + int16x8_t inputVal0; + int16x8_t inputVal1; + int8x8_t outputVal0; + int8x8_t outputVal1; + int8x16_t outputVal; + + for(number = 0; number < sixteenth_points; number++){ + // load two input vectors + inputVal0 = vld1q_s16(inputVectorPtr); + inputVal1 = vld1q_s16(inputVectorPtr+8); + // shift right + outputVal0 = vshrn_n_s16(inputVal0, 8); + outputVal1 = vshrn_n_s16(inputVal1, 8); + // squash two vectors and write output + outputVal = vcombine_s8(outputVal0, outputVal1); + vst1q_s8(outputVectorPtr, outputVal); + inputVectorPtr += 16; + outputVectorPtr += 16; + } + + for(number = sixteenth_points * 16; number < num_points; number++){ + *outputVectorPtr++ = ((int8_t)(*inputVectorPtr++ >> 8)); + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Converts the input 16 bit integer data into 8 bit integer data @@ -134,7 +196,4 @@ static inline void volk_16i_convert_8i_a_generic(int8_t* outputVector, const int } #endif /* LV_HAVE_GENERIC */ - - - #endif /* INCLUDED_volk_16i_convert_8i_a_H */ diff --git a/volk/kernels/volk/volk_16i_max_star_16i.h b/volk/kernels/volk/volk_16i_max_star_16i.h index d296c43cb0..e81a91a375 100644 --- a/volk/kernels/volk/volk_16i_max_star_16i.h +++ b/volk/kernels/volk/volk_16i_max_star_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_max_star_16i_a_H #define INCLUDED_volk_16i_max_star_16i_a_H @@ -94,7 +116,7 @@ static inline void volk_16i_max_star_16i_neon(short* target, short* src0, unsign int16x8_t diff, zeros; uint16x8_t comp1, comp2; zeros = veorq_s16(zeros, zeros); - + int16x8x2_t tmpvec; int16x8_t candidate_vec = vld1q_dup_s16(src0 ); diff --git a/volk/kernels/volk/volk_16i_max_star_horizontal_16i.h b/volk/kernels/volk/volk_16i_max_star_horizontal_16i.h index 1915522947..b671929a29 100644 --- a/volk/kernels/volk/volk_16i_max_star_horizontal_16i.h +++ b/volk/kernels/volk/volk_16i_max_star_horizontal_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_max_star_horizontal_16i_a_H #define INCLUDED_volk_16i_max_star_horizontal_16i_a_H @@ -125,17 +147,17 @@ static inline void volk_16i_max_star_horizontal_16i_neon(int16_t* target, int16_ diff = vsubq_s16(input_vec.val[0], input_vec.val[1]); comp1 = vcgeq_s16(diff, zeros); comp2 = vcltq_s16(diff, zeros); - + input_vec.val[0] = vandq_s16(input_vec.val[0], (int16x8_t)comp1); input_vec.val[1] = vandq_s16(input_vec.val[1], (int16x8_t)comp2); - + max_vec = vaddq_s16(input_vec.val[0], input_vec.val[1]); vst1q_s16(target, max_vec); src0 += 16; target += 8; } for(number=0; number < num_points%16; number+=2) { - target[number >> 1] = ((int16_t)(src0[number] - src0[number + 1]) > 0) ? src0[number] : src0[number+1]; + target[number >> 1] = ((int16_t)(src0[number] - src0[number + 1]) > 0) ? src0[number] : src0[number+1]; } } diff --git a/volk/kernels/volk/volk_16i_permute_and_scalar_add.h b/volk/kernels/volk/volk_16i_permute_and_scalar_add.h index 7a01d172a3..e6f20b72bc 100644 --- a/volk/kernels/volk/volk_16i_permute_and_scalar_add.h +++ b/volk/kernels/volk/volk_16i_permute_and_scalar_add.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_permute_and_scalar_add_a_H #define INCLUDED_volk_16i_permute_and_scalar_add_a_H diff --git a/volk/kernels/volk/volk_16i_s32f_convert_32f.h b/volk/kernels/volk/volk_16i_s32f_convert_32f.h index a810a601a0..6ea28f0e90 100644 --- a/volk/kernels/volk/volk_16i_s32f_convert_32f.h +++ b/volk/kernels/volk/volk_16i_s32f_convert_32f.h @@ -1,9 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_s32f_convert_32f_u_H #define INCLUDED_volk_16i_s32f_convert_32f_u_H #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + + /*! + \brief Converts the input 16 bit integer data into floating point data, and divides the each floating point output data point by the scalar value + \param inputVector The 16 bit input data buffer + \param outputVector The floating point output data buffer + \param scalar The value divided against each point in the output buffer + \param num_points The number of data values to be converted + */ +static inline void volk_16i_s32f_convert_32f_u_avx(float* outputVector, const int16_t* inputVector, const float scalar, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + float* outputVectorPtr = outputVector; + __m128 invScalar = _mm_set_ps1(1.0/scalar); + int16_t* inputPtr = (int16_t*)inputVector; + __m128i inputVal, inputVal2; + __m128 ret; + __m256 output; + __m256 dummy = _mm256_setzero_ps(); + + for(;number < eighthPoints; number++){ + + // Load the 8 values + //inputVal = _mm_loadu_si128((__m128i*)inputPtr); + inputVal = _mm_loadu_si128((__m128i*)inputPtr); + + // Shift the input data to the right by 64 bits ( 8 bytes ) + inputVal2 = _mm_srli_si128(inputVal, 8); + + // Convert the lower 4 values into 32 bit words + inputVal = _mm_cvtepi16_epi32(inputVal); + inputVal2 = _mm_cvtepi16_epi32(inputVal2); + + ret = _mm_cvtepi32_ps(inputVal); + ret = _mm_mul_ps(ret, invScalar); + output = _mm256_insertf128_ps(dummy, ret, 0); + + ret = _mm_cvtepi32_ps(inputVal2); + ret = _mm_mul_ps(ret, invScalar); + output = _mm256_insertf128_ps(output, ret, 1); + + _mm256_storeu_ps(outputVectorPtr, output); + + outputVectorPtr += 8; + + inputPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + outputVector[number] =((float)(inputVector[number])) / scalar; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE4_1 #include <smmintrin.h> @@ -116,7 +195,53 @@ static inline void volk_16i_s32f_convert_32f_generic(float* outputVector, const } #endif /* LV_HAVE_GENERIC */ +#ifdef LV_HAVE_NEON + /*! + \brief Converts the input 16 bit integer data into floating point data, and divides the each floating point output data point by the scalar value + \param inputVector The 16 bit input data buffer + \param outputVector The floating point output data buffer + \param scalar The value divided against each point in the output buffer + \param num_points The number of data values to be converted + \note Output buffer does NOT need to be properly aligned + */ +static inline void volk_16i_s32f_convert_32f_neon(float* outputVector, const int16_t* inputVector, const float scalar, unsigned int num_points){ + float* outputPtr = outputVector; + const int16_t* inputPtr = inputVector; + unsigned int number = 0; + unsigned int eighth_points = num_points / 8; + + int16x4x2_t input16; + int32x4_t input32_0, input32_1; + float32x4_t input_float_0, input_float_1; + float32x4x2_t output_float; + float32x4_t inv_scale; + + inv_scale = vdupq_n_f32(1.0/scalar); + + // the generic disassembles to a 128-bit load + // and duplicates every instruction to operate on 64-bits + // at a time. This is only possible with lanes, which is faster + // than just doing a vld1_s16, but still slower. + for(number = 0; number < eighth_points; number++){ + input16 = vld2_s16(inputPtr); + // widen 16-bit int to 32-bit int + input32_0 = vmovl_s16(input16.val[0]); + input32_1 = vmovl_s16(input16.val[1]); + // convert 32-bit int to float with scale + input_float_0 = vcvtq_f32_s32(input32_0); + input_float_1 = vcvtq_f32_s32(input32_1); + output_float.val[0] = vmulq_f32(input_float_0, inv_scale); + output_float.val[1] = vmulq_f32(input_float_1, inv_scale); + vst2q_f32(outputPtr, output_float); + inputPtr += 8; + outputPtr += 8; + } + for(number = eighth_points*8; number < num_points; number++){ + *outputPtr++ = ((float)(*inputPtr++)) / scalar; + } +} +#endif /* LV_HAVE_NEON */ #endif /* INCLUDED_volk_16i_s32f_convert_32f_u_H */ @@ -126,6 +251,63 @@ static inline void volk_16i_s32f_convert_32f_generic(float* outputVector, const #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + + /*! + \brief Converts the input 16 bit integer data into floating point data, and divides the each floating point output data point by the scalar value + \param inputVector The 16 bit input data buffer + \param outputVector The floating point output data buffer + \param scalar The value divided against each point in the output buffer + \param num_points The number of data values to be converted + */ +static inline void volk_16i_s32f_convert_32f_a_avx(float* outputVector, const int16_t* inputVector, const float scalar, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + float* outputVectorPtr = outputVector; + __m128 invScalar = _mm_set_ps1(1.0/scalar); + int16_t* inputPtr = (int16_t*)inputVector; + __m128i inputVal, inputVal2; + __m128 ret; + __m256 output; + __m256 dummy = _mm256_setzero_ps(); + + for(;number < eighthPoints; number++){ + + // Load the 8 values + //inputVal = _mm_loadu_si128((__m128i*)inputPtr); + inputVal = _mm_load_si128((__m128i*)inputPtr); + + // Shift the input data to the right by 64 bits ( 8 bytes ) + inputVal2 = _mm_srli_si128(inputVal, 8); + + // Convert the lower 4 values into 32 bit words + inputVal = _mm_cvtepi16_epi32(inputVal); + inputVal2 = _mm_cvtepi16_epi32(inputVal2); + + ret = _mm_cvtepi32_ps(inputVal); + ret = _mm_mul_ps(ret, invScalar); + output = _mm256_insertf128_ps(dummy, ret, 0); + + ret = _mm_cvtepi32_ps(inputVal2); + ret = _mm_mul_ps(ret, invScalar); + output = _mm256_insertf128_ps(output, ret, 1); + + _mm256_store_ps(outputVectorPtr, output); + + outputVectorPtr += 8; + + inputPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + outputVector[number] =((float)(inputVector[number])) / scalar; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE4_1 #include <smmintrin.h> diff --git a/volk/kernels/volk/volk_16i_x4_quad_max_star_16i.h b/volk/kernels/volk/volk_16i_x4_quad_max_star_16i.h index 8e84b6ea17..4c67ef4e7d 100644 --- a/volk/kernels/volk/volk_16i_x4_quad_max_star_16i.h +++ b/volk/kernels/volk/volk_16i_x4_quad_max_star_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_x4_quad_max_star_16i_a_H #define INCLUDED_volk_16i_x4_quad_max_star_16i_a_H diff --git a/volk/kernels/volk/volk_16i_x5_add_quad_16i_x4.h b/volk/kernels/volk/volk_16i_x5_add_quad_16i_x4.h index cd1952bccb..6a056ff69a 100644 --- a/volk/kernels/volk/volk_16i_x5_add_quad_16i_x4.h +++ b/volk/kernels/volk/volk_16i_x5_add_quad_16i_x4.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16i_x5_add_quad_16i_x4_a_H #define INCLUDED_volk_16i_x5_add_quad_16i_x4_a_H diff --git a/volk/kernels/volk/volk_16ic_deinterleave_16i_x2.h b/volk/kernels/volk/volk_16ic_deinterleave_16i_x2.h index 9ce8012640..26521e215d 100644 --- a/volk/kernels/volk/volk_16ic_deinterleave_16i_x2.h +++ b/volk/kernels/volk/volk_16ic_deinterleave_16i_x2.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_deinterleave_16i_x2_a_H #define INCLUDED_volk_16ic_deinterleave_16i_x2_a_H diff --git a/volk/kernels/volk/volk_16ic_deinterleave_real_16i.h b/volk/kernels/volk/volk_16ic_deinterleave_real_16i.h index f6eccd77ee..5c2988743c 100644 --- a/volk/kernels/volk/volk_16ic_deinterleave_real_16i.h +++ b/volk/kernels/volk/volk_16ic_deinterleave_real_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_deinterleave_real_16i_a_H #define INCLUDED_volk_16ic_deinterleave_real_16i_a_H diff --git a/volk/kernels/volk/volk_16ic_deinterleave_real_8i.h b/volk/kernels/volk/volk_16ic_deinterleave_real_8i.h index f3d0c83524..b2b1e2a41d 100644 --- a/volk/kernels/volk/volk_16ic_deinterleave_real_8i.h +++ b/volk/kernels/volk/volk_16ic_deinterleave_real_8i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_deinterleave_real_8i_a_H #define INCLUDED_volk_16ic_deinterleave_real_8i_a_H diff --git a/volk/kernels/volk/volk_16ic_magnitude_16i.h b/volk/kernels/volk/volk_16ic_magnitude_16i.h index b33306a123..fb29bfdc94 100644 --- a/volk/kernels/volk/volk_16ic_magnitude_16i.h +++ b/volk/kernels/volk/volk_16ic_magnitude_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_magnitude_16i_a_H #define INCLUDED_volk_16ic_magnitude_16i_a_H diff --git a/volk/kernels/volk/volk_16ic_s32f_deinterleave_32f_x2.h b/volk/kernels/volk/volk_16ic_s32f_deinterleave_32f_x2.h index 55243b4aa8..cc702de872 100644 --- a/volk/kernels/volk/volk_16ic_s32f_deinterleave_32f_x2.h +++ b/volk/kernels/volk/volk_16ic_s32f_deinterleave_32f_x2.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_s32f_deinterleave_32f_x2_a_H #define INCLUDED_volk_16ic_s32f_deinterleave_32f_x2_a_H diff --git a/volk/kernels/volk/volk_16ic_s32f_deinterleave_real_32f.h b/volk/kernels/volk/volk_16ic_s32f_deinterleave_real_32f.h index 57d078a595..2dd9188c5f 100644 --- a/volk/kernels/volk/volk_16ic_s32f_deinterleave_real_32f.h +++ b/volk/kernels/volk/volk_16ic_s32f_deinterleave_real_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_s32f_deinterleave_real_32f_a_H #define INCLUDED_volk_16ic_s32f_deinterleave_real_32f_a_H diff --git a/volk/kernels/volk/volk_16ic_s32f_magnitude_32f.h b/volk/kernels/volk/volk_16ic_s32f_magnitude_32f.h index 27901cb9ac..ba06450312 100644 --- a/volk/kernels/volk/volk_16ic_s32f_magnitude_32f.h +++ b/volk/kernels/volk/volk_16ic_s32f_magnitude_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16ic_s32f_magnitude_32f_a_H #define INCLUDED_volk_16ic_s32f_magnitude_32f_a_H diff --git a/volk/kernels/volk/volk_16u_byteswap.h b/volk/kernels/volk/volk_16u_byteswap.h index 436caf0474..3b2f9e2c91 100644 --- a/volk/kernels/volk/volk_16u_byteswap.h +++ b/volk/kernels/volk/volk_16u_byteswap.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_16u_byteswap_u_H #define INCLUDED_volk_16u_byteswap_u_H @@ -136,6 +158,58 @@ static inline void volk_16u_byteswap_neon(uint16_t* intsToSwap, unsigned int num } #endif /* LV_HAVE_NEON */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Byteswaps (in-place) an aligned vector of int32_t's. + \param intsToSwap The vector of data to byte swap + \param numDataPoints The number of data points +*/ +static inline void volk_16u_byteswap_neon_table(uint16_t* intsToSwap, unsigned int num_points){ + uint16_t* inputPtr = intsToSwap; + unsigned int number = 0; + unsigned int n16points = num_points / 16; + + uint8x8x4_t input_table; + uint8x8_t int_lookup01, int_lookup23, int_lookup45, int_lookup67; + uint8x8_t swapped_int01, swapped_int23, swapped_int45, swapped_int67; + + /* these magic numbers are used as byte-indeces in the LUT. + they are pre-computed to save time. A simple C program + can calculate them; for example for lookup01: + uint8_t chars[8] = {24, 16, 8, 0, 25, 17, 9, 1}; + for(ii=0; ii < 8; ++ii) { + index += ((uint64_t)(*(chars+ii))) << (ii*8); + } + */ + int_lookup01 = vcreate_u8(1232017111498883080); + int_lookup23 = vcreate_u8(1376697457175036426); + int_lookup45 = vcreate_u8(1521377802851189772); + int_lookup67 = vcreate_u8(1666058148527343118); + + for(number = 0; number < n16points; ++number){ + input_table = vld4_u8((uint8_t*) inputPtr); + swapped_int01 = vtbl4_u8(input_table, int_lookup01); + swapped_int23 = vtbl4_u8(input_table, int_lookup23); + swapped_int45 = vtbl4_u8(input_table, int_lookup45); + swapped_int67 = vtbl4_u8(input_table, int_lookup67); + vst1_u8((uint8_t*)inputPtr, swapped_int01); + vst1_u8((uint8_t*)(inputPtr+4), swapped_int23); + vst1_u8((uint8_t*)(inputPtr+8), swapped_int45); + vst1_u8((uint8_t*)(inputPtr+12), swapped_int67); + + inputPtr += 16; + } + + for(number = n16points * 16; number < num_points; ++number){ + uint16_t output = *inputPtr; + output = (((output >> 8) & 0xff) | ((output << 8) & 0xff00)); + *inputPtr = output; + inputPtr++; + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Byteswaps (in-place) an aligned vector of int16_t's. diff --git a/volk/kernels/volk/volk_16u_byteswappuppet_16u.h b/volk/kernels/volk/volk_16u_byteswappuppet_16u.h new file mode 100644 index 0000000000..74745d328c --- /dev/null +++ b/volk/kernels/volk/volk_16u_byteswappuppet_16u.h @@ -0,0 +1,55 @@ +#ifndef INCLUDED_volk_16u_byteswappuppet_16u_H +#define INCLUDED_volk_16u_byteswappuppet_16u_H + + +#include <stdint.h> +#include <volk/volk_16u_byteswap.h> +#include <string.h> + +#ifdef LV_HAVE_GENERIC +static inline void volk_16u_byteswappuppet_16u_generic(uint16_t*output, uint16_t* intsToSwap, unsigned int num_points){ + + volk_16u_byteswap_generic((uint16_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint16_t)); + +} +#endif + +#ifdef LV_HAVE_NEON +static inline void volk_16u_byteswappuppet_16u_neon(uint16_t*output, uint16_t* intsToSwap, unsigned int num_points){ + + volk_16u_byteswap_neon((uint16_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint16_t)); + +} +#endif + +#ifdef LV_HAVE_NEON +static inline void volk_16u_byteswappuppet_16u_neon_table(uint16_t*output, uint16_t* intsToSwap, unsigned int num_points){ + + volk_16u_byteswap_neon_table((uint16_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint16_t)); + +} +#endif + +#ifdef LV_HAVE_SSE2 +static inline void volk_16u_byteswappuppet_16u_u_sse2(uint16_t *output, uint16_t* intsToSwap, unsigned int num_points){ + + volk_16u_byteswap_u_sse2((uint16_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint16_t)); + +} +#endif + +#ifdef LV_HAVE_SSE2 +static inline void volk_16u_byteswappuppet_16u_a_sse2(uint16_t *output, uint16_t* intsToSwap, unsigned int num_points){ + + volk_16u_byteswap_a_sse2((uint16_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint16_t)); + +} +#endif + + +#endif diff --git a/volk/kernels/volk/volk_32f_accumulator_s32f.h b/volk/kernels/volk/volk_32f_accumulator_s32f.h index a67d10f9b5..e8995fb6c6 100644 --- a/volk/kernels/volk/volk_32f_accumulator_s32f.h +++ b/volk/kernels/volk/volk_32f_accumulator_s32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_accumulator_s32f_a_H #define INCLUDED_volk_32f_accumulator_s32f_a_H diff --git a/volk/kernels/volk/volk_32f_acos_32f.h b/volk/kernels/volk/volk_32f_acos_32f.h new file mode 100644 index 0000000000..1b2b734835 --- /dev/null +++ b/volk/kernels/volk/volk_32f_acos_32f.h @@ -0,0 +1,194 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +/* This is the number of terms of Taylor series to evaluate, increase this for more accuracy*/ +#define ACOS_TERMS 2 + +#ifndef INCLUDED_volk_32f_acos_32f_a_H +#define INCLUDED_volk_32f_acos_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes arccosine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arccosine is to be computed +*/ +static inline void volk_32f_acos_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + int i, j; + + __m128 aVal, d, pi, pio2, x, y, z, arccosine; + __m128 fzeroes, fones, ftwos, ffours, condition; + + pi = _mm_set1_ps(3.14159265358979323846); + pio2 = _mm_set1_ps(3.14159265358979323846/2); + fzeroes = _mm_setzero_ps(); + fones = _mm_set1_ps(1.0); + ftwos = _mm_set1_ps(2.0); + ffours = _mm_set1_ps(4.0); + + for(;number < quarterPoints; number++){ + aVal = _mm_load_ps(aPtr); + d = aVal; + aVal = _mm_div_ps(_mm_sqrt_ps(_mm_mul_ps(_mm_add_ps(fones, aVal), _mm_sub_ps(fones, aVal))), aVal); + z = aVal; + condition = _mm_cmplt_ps(z, fzeroes); + z = _mm_sub_ps(z, _mm_and_ps(_mm_mul_ps(z, ftwos), condition)); + x = z; + condition = _mm_cmplt_ps(z, fones); + x = _mm_add_ps(x, _mm_and_ps(_mm_sub_ps(_mm_div_ps(fones, z), z), condition)); + + for(i = 0; i < 2; i++) + x = _mm_add_ps(x, _mm_sqrt_ps(_mm_add_ps(fones, _mm_mul_ps(x, x)))); + x = _mm_div_ps(fones, x); + y = fzeroes; + for(j = ACOS_TERMS - 1; j >=0 ; j--) + y = _mm_add_ps(_mm_mul_ps(y, _mm_mul_ps(x, x)), _mm_set1_ps(pow(-1,j)/(2*j+1))); + + y = _mm_mul_ps(y, _mm_mul_ps(x, ffours)); + condition = _mm_cmpgt_ps(z, fones); + + y = _mm_add_ps(y, _mm_and_ps(_mm_sub_ps(pio2, _mm_mul_ps(y, ftwos)), condition)); + arccosine = y; + condition = _mm_cmplt_ps(aVal, fzeroes); + arccosine = _mm_sub_ps(arccosine, _mm_and_ps(_mm_mul_ps(arccosine, ftwos), condition)); + condition = _mm_cmplt_ps(d, fzeroes); + arccosine = _mm_add_ps(arccosine, _mm_and_ps(pi, condition)); + + _mm_store_ps(bPtr, arccosine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = acos(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_acos_32f_a_H */ + + +#ifndef INCLUDED_volk_32f_acos_32f_u_H +#define INCLUDED_volk_32f_acos_32f_u_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes arccosine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arccosine is to be computed +*/ +static inline void volk_32f_acos_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + int i, j; + + __m128 aVal, d, pi, pio2, x, y, z, arccosine; + __m128 fzeroes, fones, ftwos, ffours, condition; + + pi = _mm_set1_ps(3.14159265358979323846); + pio2 = _mm_set1_ps(3.14159265358979323846/2); + fzeroes = _mm_setzero_ps(); + fones = _mm_set1_ps(1.0); + ftwos = _mm_set1_ps(2.0); + ffours = _mm_set1_ps(4.0); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + d = aVal; + aVal = _mm_div_ps(_mm_sqrt_ps(_mm_mul_ps(_mm_add_ps(fones, aVal), _mm_sub_ps(fones, aVal))), aVal); + z = aVal; + condition = _mm_cmplt_ps(z, fzeroes); + z = _mm_sub_ps(z, _mm_and_ps(_mm_mul_ps(z, ftwos), condition)); + x = z; + condition = _mm_cmplt_ps(z, fones); + x = _mm_add_ps(x, _mm_and_ps(_mm_sub_ps(_mm_div_ps(fones, z), z), condition)); + + for(i = 0; i < 2; i++) + x = _mm_add_ps(x, _mm_sqrt_ps(_mm_add_ps(fones, _mm_mul_ps(x, x)))); + x = _mm_div_ps(fones, x); + y = fzeroes; + + for(j = ACOS_TERMS - 1; j >=0 ; j--) + y = _mm_add_ps(_mm_mul_ps(y, _mm_mul_ps(x, x)), _mm_set1_ps(pow(-1,j)/(2*j+1))); + + y = _mm_mul_ps(y, _mm_mul_ps(x, ffours)); + condition = _mm_cmpgt_ps(z, fones); + + y = _mm_add_ps(y, _mm_and_ps(_mm_sub_ps(pio2, _mm_mul_ps(y, ftwos)), condition)); + arccosine = y; + condition = _mm_cmplt_ps(aVal, fzeroes); + arccosine = _mm_sub_ps(arccosine, _mm_and_ps(_mm_mul_ps(arccosine, ftwos), condition)); + condition = _mm_cmplt_ps(d, fzeroes); + arccosine = _mm_add_ps(arccosine, _mm_and_ps(pi, condition)); + + _mm_storeu_ps(bPtr, arccosine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = acos(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes arccosine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arccosine is to be computed +*/ +static inline void volk_32f_acos_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = acos(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_acos_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_asin_32f.h b/volk/kernels/volk/volk_32f_asin_32f.h new file mode 100644 index 0000000000..7b80de7ee8 --- /dev/null +++ b/volk/kernels/volk/volk_32f_asin_32f.h @@ -0,0 +1,189 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +/* This is the number of terms of Taylor series to evaluate, increase this for more accuracy*/ +#define ASIN_TERMS 2 + +#ifndef INCLUDED_volk_32f_asin_32f_a_H +#define INCLUDED_volk_32f_asin_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes arcsine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arcsine is to be computed +*/ +static inline void volk_32f_asin_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + int i, j; + + __m128 aVal, pio2, x, y, z, arcsine; + __m128 fzeroes, fones, ftwos, ffours, condition; + + pio2 = _mm_set1_ps(3.14159265358979323846/2); + fzeroes = _mm_setzero_ps(); + fones = _mm_set1_ps(1.0); + ftwos = _mm_set1_ps(2.0); + ffours = _mm_set1_ps(4.0); + + for(;number < quarterPoints; number++){ + aVal = _mm_load_ps(aPtr); + aVal = _mm_div_ps(aVal, _mm_sqrt_ps(_mm_mul_ps(_mm_add_ps(fones, aVal), _mm_sub_ps(fones, aVal)))); + z = aVal; + condition = _mm_cmplt_ps(z, fzeroes); + z = _mm_sub_ps(z, _mm_and_ps(_mm_mul_ps(z, ftwos), condition)); + x = z; + condition = _mm_cmplt_ps(z, fones); + x = _mm_add_ps(x, _mm_and_ps(_mm_sub_ps(_mm_div_ps(fones, z), z), condition)); + + for(i = 0; i < 2; i++){ + x = _mm_add_ps(x, _mm_sqrt_ps(_mm_add_ps(fones, _mm_mul_ps(x, x)))); + } + x = _mm_div_ps(fones, x); + y = fzeroes; + for(j = ASIN_TERMS - 1; j >=0 ; j--){ + y = _mm_add_ps(_mm_mul_ps(y, _mm_mul_ps(x, x)), _mm_set1_ps(pow(-1,j)/(2*j+1))); + } + + y = _mm_mul_ps(y, _mm_mul_ps(x, ffours)); + condition = _mm_cmpgt_ps(z, fones); + + y = _mm_add_ps(y, _mm_and_ps(_mm_sub_ps(pio2, _mm_mul_ps(y, ftwos)), condition)); + arcsine = y; + condition = _mm_cmplt_ps(aVal, fzeroes); + arcsine = _mm_sub_ps(arcsine, _mm_and_ps(_mm_mul_ps(arcsine, ftwos), condition)); + + _mm_store_ps(bPtr, arcsine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = asin(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_asin_32f_a_H */ + +#ifndef INCLUDED_volk_32f_asin_32f_u_H +#define INCLUDED_volk_32f_asin_32f_u_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes arcsine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arcsine is to be computed +*/ +static inline void volk_32f_asin_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + int i, j; + + __m128 aVal, pio2, x, y, z, arcsine; + __m128 fzeroes, fones, ftwos, ffours, condition; + + pio2 = _mm_set1_ps(3.14159265358979323846/2); + fzeroes = _mm_setzero_ps(); + fones = _mm_set1_ps(1.0); + ftwos = _mm_set1_ps(2.0); + ffours = _mm_set1_ps(4.0); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + aVal = _mm_div_ps(aVal, _mm_sqrt_ps(_mm_mul_ps(_mm_add_ps(fones, aVal), _mm_sub_ps(fones, aVal)))); + z = aVal; + condition = _mm_cmplt_ps(z, fzeroes); + z = _mm_sub_ps(z, _mm_and_ps(_mm_mul_ps(z, ftwos), condition)); + x = z; + condition = _mm_cmplt_ps(z, fones); + x = _mm_add_ps(x, _mm_and_ps(_mm_sub_ps(_mm_div_ps(fones, z), z), condition)); + + for(i = 0; i < 2; i++){ + x = _mm_add_ps(x, _mm_sqrt_ps(_mm_add_ps(fones, _mm_mul_ps(x, x)))); + } + x = _mm_div_ps(fones, x); + y = fzeroes; + for(j = ASIN_TERMS - 1; j >=0 ; j--){ + y = _mm_add_ps(_mm_mul_ps(y, _mm_mul_ps(x, x)), _mm_set1_ps(pow(-1,j)/(2*j+1))); + } + + y = _mm_mul_ps(y, _mm_mul_ps(x, ffours)); + condition = _mm_cmpgt_ps(z, fones); + + y = _mm_add_ps(y, _mm_and_ps(_mm_sub_ps(pio2, _mm_mul_ps(y, ftwos)), condition)); + arcsine = y; + condition = _mm_cmplt_ps(aVal, fzeroes); + arcsine = _mm_sub_ps(arcsine, _mm_and_ps(_mm_mul_ps(arcsine, ftwos), condition)); + + _mm_storeu_ps(bPtr, arcsine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = asin(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes arcsine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arcsine is to be computed +*/ +static inline void volk_32f_asin_32f_u_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = asin(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_asin_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_atan_32f.h b/volk/kernels/volk/volk_32f_atan_32f.h new file mode 100644 index 0000000000..60742bb724 --- /dev/null +++ b/volk/kernels/volk/volk_32f_atan_32f.h @@ -0,0 +1,183 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +/* This is the number of terms of Taylor series to evaluate, increase this for more accuracy*/ +#define TERMS 2 + +#ifndef INCLUDED_volk_32f_atan_32f_a_H +#define INCLUDED_volk_32f_atan_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes arctangent of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arctangent is to be computed +*/ +static inline void volk_32f_atan_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + int i, j; + + __m128 aVal, pio2, x, y, z, arctangent; + __m128 fzeroes, fones, ftwos, ffours, condition; + + pio2 = _mm_set1_ps(3.14159265358979323846/2); + fzeroes = _mm_setzero_ps(); + fones = _mm_set1_ps(1.0); + ftwos = _mm_set1_ps(2.0); + ffours = _mm_set1_ps(4.0); + + for(;number < quarterPoints; number++){ + aVal = _mm_load_ps(aPtr); + z = aVal; + condition = _mm_cmplt_ps(z, fzeroes); + z = _mm_sub_ps(z, _mm_and_ps(_mm_mul_ps(z, ftwos), condition)); + x = z; + condition = _mm_cmplt_ps(z, fones); + x = _mm_add_ps(x, _mm_and_ps(_mm_sub_ps(_mm_div_ps(fones, z), z), condition)); + + for(i = 0; i < 2; i++){ + x = _mm_add_ps(x, _mm_sqrt_ps(_mm_add_ps(fones, _mm_mul_ps(x, x)))); + } + x = _mm_div_ps(fones, x); + y = fzeroes; + for(j = TERMS - 1; j >=0 ; j--){ + y = _mm_add_ps(_mm_mul_ps(y, _mm_mul_ps(x, x)), _mm_set1_ps(pow(-1,j)/(2*j+1))); + } + + y = _mm_mul_ps(y, _mm_mul_ps(x, ffours)); + condition = _mm_cmpgt_ps(z, fones); + + y = _mm_add_ps(y, _mm_and_ps(_mm_sub_ps(pio2, _mm_mul_ps(y, ftwos)), condition)); + arctangent = y; + condition = _mm_cmplt_ps(aVal, fzeroes); + arctangent = _mm_sub_ps(arctangent, _mm_and_ps(_mm_mul_ps(arctangent, ftwos), condition)); + + _mm_store_ps(bPtr, arctangent); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = atan(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_atan_32f_a_H */ + +#ifndef INCLUDED_volk_32f_atan_32f_u_H +#define INCLUDED_volk_32f_atan_32f_u_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes arctangent of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arctangent is to be computed +*/ +static inline void volk_32f_atan_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + int i, j; + + __m128 aVal, pio2, x, y, z, arctangent; + __m128 fzeroes, fones, ftwos, ffours, condition; + + pio2 = _mm_set1_ps(3.14159265358979323846/2); + fzeroes = _mm_setzero_ps(); + fones = _mm_set1_ps(1.0); + ftwos = _mm_set1_ps(2.0); + ffours = _mm_set1_ps(4.0); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + z = aVal; + condition = _mm_cmplt_ps(z, fzeroes); + z = _mm_sub_ps(z, _mm_and_ps(_mm_mul_ps(z, ftwos), condition)); + x = z; + condition = _mm_cmplt_ps(z, fones); + x = _mm_add_ps(x, _mm_and_ps(_mm_sub_ps(_mm_div_ps(fones, z), z), condition)); + + for(i = 0; i < 2; i++) x = _mm_add_ps(x, _mm_sqrt_ps(_mm_add_ps(fones, _mm_mul_ps(x, x)))); + x = _mm_div_ps(fones, x); + y = fzeroes; + for(j = TERMS - 1; j >= 0; j--) y = _mm_add_ps(_mm_mul_ps(y, _mm_mul_ps(x, x)), _mm_set1_ps(pow(-1,j)/(2*j+1))); + + y = _mm_mul_ps(y, _mm_mul_ps(x, ffours)); + condition = _mm_cmpgt_ps(z, fones); + + y = _mm_add_ps(y, _mm_and_ps(_mm_sub_ps(pio2, _mm_mul_ps(y, ftwos)), condition)); + arctangent = y; + condition = _mm_cmplt_ps(aVal, fzeroes); + arctangent = _mm_sub_ps(arctangent, _mm_and_ps(_mm_mul_ps(arctangent, ftwos), condition)); + + _mm_storeu_ps(bPtr, arctangent); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = atan(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes arctangent of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which arctangent is to be computed +*/ +static inline void volk_32f_atan_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = atan(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_atan_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_binary_slicer_32i.h b/volk/kernels/volk/volk_32f_binary_slicer_32i.h index f47d20fd37..41f59148c2 100644 --- a/volk/kernels/volk/volk_32f_binary_slicer_32i.h +++ b/volk/kernels/volk/volk_32f_binary_slicer_32i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_binary_slicer_32i_H #define INCLUDED_volk_32f_binary_slicer_32i_H diff --git a/volk/kernels/volk/volk_32f_binary_slicer_8i.h b/volk/kernels/volk/volk_32f_binary_slicer_8i.h index e24960cab7..ae4420b6e1 100644 --- a/volk/kernels/volk/volk_32f_binary_slicer_8i.h +++ b/volk/kernels/volk/volk_32f_binary_slicer_8i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_binary_slicer_8i_H #define INCLUDED_volk_32f_binary_slicer_8i_H @@ -184,4 +206,84 @@ volk_32f_binary_slicer_8i_u_sse2(int8_t* cVector, const float* aVector, #endif /* LV_HAVE_SSE2 */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Returns integer 1 if float input is greater than or equal to 0, 1 otherwise + \param cVector The char (int8_t) output (either 0 or 1) + \param aVector The float input + \param num_points The number of values in aVector and stored into cVector +*/ +static inline void +volk_32f_binary_slicer_8i_neon(int8_t* cVector, const float* aVector, + unsigned int num_points) +{ + int8_t* cPtr = cVector; + const float* aPtr = aVector; + unsigned int number = 0; + unsigned int n16points = num_points / 16; + + float32x4x2_t input_val0, input_val1; + float32x4_t zero_val; + uint32x4x2_t res0_u32, res1_u32; + uint16x4x2_t res0_u16x4, res1_u16x4; + uint16x8x2_t res_u16x8; + uint8x8x2_t res_u8; + uint8x8_t one; + + zero_val = vdupq_n_f32(0.0); + one = vdup_n_u8(0x01); + + // TODO: this is a good candidate for asm because the vcombines + // can be eliminated simply by picking dst registers that are + // adjacent. + for(number = 0; number < n16points; number++) { + input_val0 = vld2q_f32(aPtr); + input_val1 = vld2q_f32(aPtr+8); + + // test against 0; return uint32 + res0_u32.val[0] = vcgeq_f32(input_val0.val[0], zero_val); + res0_u32.val[1] = vcgeq_f32(input_val0.val[1], zero_val); + res1_u32.val[0] = vcgeq_f32(input_val1.val[0], zero_val); + res1_u32.val[1] = vcgeq_f32(input_val1.val[1], zero_val); + + // narrow uint32 -> uint16 followed by combine to 8-element vectors + res0_u16x4.val[0] = vmovn_u32(res0_u32.val[0]); + res0_u16x4.val[1] = vmovn_u32(res0_u32.val[1]); + res1_u16x4.val[0] = vmovn_u32(res1_u32.val[0]); + res1_u16x4.val[1] = vmovn_u32(res1_u32.val[1]); + + res_u16x8.val[0] = vcombine_u16(res0_u16x4.val[0], res1_u16x4.val[0]); + res_u16x8.val[1] = vcombine_u16(res0_u16x4.val[1], res1_u16x4.val[1]); + + // narrow uint16x8 -> uint8x8 + res_u8.val[0] = vmovn_u16(res_u16x8.val[0]); + res_u8.val[1] = vmovn_u16(res_u16x8.val[1]); + // we *could* load twice as much data and do another vcombine here + // to get a uint8x16x2 vector, still only do 2 vandqs and a single store + // but that turns out to be ~16% slower than this version on zc702 + // it's possible register contention in GCC scheduler slows it down + // and a hand-written asm with quad-word u8 registers is much faster. + + res_u8.val[0] = vand_u8(one, res_u8.val[0]); + res_u8.val[1] = vand_u8(one, res_u8.val[1]); + + vst2_u8((unsigned char*)cPtr, res_u8); + cPtr += 16; + aPtr += 16; + + } + + for(number = n16points * 16; number < num_points; number++) { + if(*aPtr++ >= 0) { + *cPtr++ = 1; + } + else { + *cPtr++ = 0; + } + } +} +#endif /* LV_HAVE_NEON */ + + #endif /* INCLUDED_volk_32f_binary_slicer_8i_H */ diff --git a/volk/kernels/volk/volk_32f_convert_64f.h b/volk/kernels/volk/volk_32f_convert_64f.h index 2f036955dd..96a411c800 100644 --- a/volk/kernels/volk/volk_32f_convert_64f.h +++ b/volk/kernels/volk/volk_32f_convert_64f.h @@ -1,9 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_convert_64f_u_H #define INCLUDED_volk_32f_convert_64f_u_H #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Converts the float values into double values + \param dVector The converted double vector values + \param fVector The float vector values to be converted + \param num_points The number of points in the two vectors to be converted + */ + +static inline void volk_32f_convert_64f_u_avx(double* outputVector, const float* inputVector, unsigned int num_points){ + unsigned int number = 0; + + const unsigned int quarterPoints = num_points / 4; + + const float* inputVectorPtr = (const float*)inputVector; + double* outputVectorPtr = outputVector; + __m256d ret; + __m128 inputVal; + + for(;number < quarterPoints; number++){ + inputVal = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4; + + ret = _mm256_cvtps_pd(inputVal); + _mm256_storeu_pd(outputVectorPtr, ret); + + outputVectorPtr += 4; + } + + number = quarterPoints * 4; + for(; number < num_points; number++){ + outputVector[number] = (double)(inputVector[number]); + } +} + +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE2 #include <emmintrin.h> /*! @@ -68,12 +126,48 @@ static inline void volk_32f_convert_64f_generic(double* outputVector, const floa #endif /* INCLUDED_volk_32f_convert_64f_u_H */ + + #ifndef INCLUDED_volk_32f_convert_64f_a_H #define INCLUDED_volk_32f_convert_64f_a_H #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Converts the float values into double values + \param dVector The converted double vector values + \param fVector The float vector values to be converted + \param num_points The number of points in the two vectors to be converted + */ +static inline void volk_32f_convert_64f_a_avx(double* outputVector, const float* inputVector, unsigned int num_points){ + unsigned int number = 0; + + const unsigned int quarterPoints = num_points / 4; + + const float* inputVectorPtr = (const float*)inputVector; + double* outputVectorPtr = outputVector; + __m256d ret; + __m128 inputVal; + + for(;number < quarterPoints; number++){ + inputVal = _mm_load_ps(inputVectorPtr); inputVectorPtr += 4; + + ret = _mm256_cvtps_pd(inputVal); + _mm256_store_pd(outputVectorPtr, ret); + + outputVectorPtr += 4; + } + + number = quarterPoints * 4; + for(; number < num_points; number++){ + outputVector[number] = (double)(inputVector[number]); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE2 #include <emmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32f_cos_32f.h b/volk/kernels/volk/volk_32f_cos_32f.h new file mode 100644 index 0000000000..49c56580bf --- /dev/null +++ b/volk/kernels/volk/volk_32f_cos_32f.h @@ -0,0 +1,211 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +#ifndef INCLUDED_volk_32f_cos_32f_a_H +#define INCLUDED_volk_32f_cos_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes cosine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which cosine is to be computed +*/ +static inline void volk_32f_cos_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + unsigned int i = 0; + + __m128 aVal, s, m4pi, pio4A, pio4B, cp1, cp2, cp3, cp4, cp5, ffours, ftwos, fones, fzeroes; + __m128 sine, cosine, condition1, condition3; + __m128i q, r, ones, twos, fours; + + m4pi = _mm_set1_ps(1.273239545); + pio4A = _mm_set1_ps(0.78515625); + pio4B = _mm_set1_ps(0.241876e-3); + ffours = _mm_set1_ps(4.0); + ftwos = _mm_set1_ps(2.0); + fones = _mm_set1_ps(1.0); + fzeroes = _mm_setzero_ps(); + ones = _mm_set1_epi32(1); + twos = _mm_set1_epi32(2); + fours = _mm_set1_epi32(4); + + cp1 = _mm_set1_ps(1.0); + cp2 = _mm_set1_ps(0.83333333e-1); + cp3 = _mm_set1_ps(0.2777778e-2); + cp4 = _mm_set1_ps(0.49603e-4); + cp5 = _mm_set1_ps(0.551e-6); + + for(;number < quarterPoints; number++){ + + aVal = _mm_load_ps(aPtr); + s = _mm_sub_ps(aVal, _mm_and_ps(_mm_mul_ps(aVal, ftwos), _mm_cmplt_ps(aVal, fzeroes))); + q = _mm_cvtps_epi32(_mm_mul_ps(s, m4pi)); + r = _mm_add_epi32(q, _mm_and_si128(q, ones)); + + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4A)); + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4B)); + + s = _mm_div_ps(s, _mm_set1_ps(8.0)); // The constant is 2^N, for 3 times argument reduction + s = _mm_mul_ps(s, s); + // Evaluate Taylor series + s = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(s, cp5), cp4), s), cp3), s), cp2), s), cp1), s); + + for(i = 0; i < 3; i++) s = _mm_mul_ps(s, _mm_sub_ps(ffours, s)); + s = _mm_div_ps(s, ftwos); + + sine = _mm_sqrt_ps(_mm_mul_ps(_mm_sub_ps(ftwos, s), s)); + cosine = _mm_sub_ps(fones, s); + + condition1 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, ones), twos)), fzeroes); + + condition3 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, twos), fours)), fzeroes); + + cosine = _mm_add_ps(cosine, _mm_and_ps(_mm_sub_ps(sine, cosine), condition1)); + cosine = _mm_sub_ps(cosine, _mm_and_ps(_mm_mul_ps(cosine, _mm_set1_ps(2.0f)), condition3)); + _mm_store_ps(bPtr, cosine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = cos(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_cos_32f_a_H */ + +#ifndef INCLUDED_volk_32f_cos_32f_u_H +#define INCLUDED_volk_32f_cos_32f_u_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes cosine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which cosine is to be computed +*/ +static inline void volk_32f_cos_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + unsigned int i = 0; + + __m128 aVal, s, m4pi, pio4A, pio4B, cp1, cp2, cp3, cp4, cp5, ffours, ftwos, fones, fzeroes; + __m128 sine, cosine, condition1, condition3; + __m128i q, r, ones, twos, fours; + + m4pi = _mm_set1_ps(1.273239545); + pio4A = _mm_set1_ps(0.78515625); + pio4B = _mm_set1_ps(0.241876e-3); + ffours = _mm_set1_ps(4.0); + ftwos = _mm_set1_ps(2.0); + fones = _mm_set1_ps(1.0); + fzeroes = _mm_setzero_ps(); + ones = _mm_set1_epi32(1); + twos = _mm_set1_epi32(2); + fours = _mm_set1_epi32(4); + + cp1 = _mm_set1_ps(1.0); + cp2 = _mm_set1_ps(0.83333333e-1); + cp3 = _mm_set1_ps(0.2777778e-2); + cp4 = _mm_set1_ps(0.49603e-4); + cp5 = _mm_set1_ps(0.551e-6); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + s = _mm_sub_ps(aVal, _mm_and_ps(_mm_mul_ps(aVal, ftwos), _mm_cmplt_ps(aVal, fzeroes))); + q = _mm_cvtps_epi32(_mm_mul_ps(s, m4pi)); + r = _mm_add_epi32(q, _mm_and_si128(q, ones)); + + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4A)); + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4B)); + + s = _mm_div_ps(s, _mm_set1_ps(8.0)); // The constant is 2^N, for 3 times argument reduction + s = _mm_mul_ps(s, s); + // Evaluate Taylor series + s = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(s, cp5), cp4), s), cp3), s), cp2), s), cp1), s); + + for(i = 0; i < 3; i++){ + s = _mm_mul_ps(s, _mm_sub_ps(ffours, s)); + } + s = _mm_div_ps(s, ftwos); + + sine = _mm_sqrt_ps(_mm_mul_ps(_mm_sub_ps(ftwos, s), s)); + cosine = _mm_sub_ps(fones, s); + + condition1 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, ones), twos)), fzeroes); + + condition3 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, twos), fours)), fzeroes); + + cosine = _mm_add_ps(cosine, _mm_and_ps(_mm_sub_ps(sine, cosine), condition1)); + cosine = _mm_sub_ps(cosine, _mm_and_ps(_mm_mul_ps(cosine, _mm_set1_ps(2.0f)), condition3)); + _mm_storeu_ps(bPtr, cosine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = cos(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes cosine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which cosine is to be computed +*/ +static inline void volk_32f_cos_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(; number < num_points; number++){ + *bPtr++ = cos(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_cos_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_expfast_32f.h b/volk/kernels/volk/volk_32f_expfast_32f.h new file mode 100644 index 0000000000..b64e45c86e --- /dev/null +++ b/volk/kernels/volk/volk_32f_expfast_32f.h @@ -0,0 +1,216 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +#define Mln2 0.6931471805f +#define A 8388608.0f +#define B 1065353216.0f +#define C 60801.0f + + +#ifndef INCLUDED_volk_32f_expfast_32f_a_H +#define INCLUDED_volk_32f_expfast_32f_a_H + +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Computes fast exp (max 7% error) of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which exp is to be computed +*/ +static inline void volk_32f_expfast_32f_a_avx(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + __m256 aVal, bVal, a, b; + __m256i exp; + a = _mm256_set1_ps(A/Mln2); + b = _mm256_set1_ps(B-C); + + for(;number < eighthPoints; number++){ + aVal = _mm256_load_ps(aPtr); + exp = _mm256_cvtps_epi32(_mm256_add_ps(_mm256_mul_ps(a,aVal), b)); + bVal = _mm256_castsi256_ps(exp); + + _mm256_store_ps(bPtr, bVal); + aPtr += 8; + bPtr += 8; + } + + number = eighthPoints * 8; + for(;number < num_points; number++){ + *bPtr++ = expf(*aPtr++); + } +} + +#endif /* LV_HAVE_AVX for aligned */ + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes fast exp (max 7% error) of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which exp is to be computed +*/ +static inline void volk_32f_expfast_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m128 aVal, bVal, a, b; + __m128i exp; + a = _mm_set1_ps(A/Mln2); + b = _mm_set1_ps(B-C); + + for(;number < quarterPoints; number++){ + aVal = _mm_load_ps(aPtr); + exp = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(a,aVal), b)); + bVal = _mm_castsi128_ps(exp); + + _mm_store_ps(bPtr, bVal); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = expf(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_expfast_32f_a_H */ + +#ifndef INCLUDED_volk_32f_expfast_32f_u_H +#define INCLUDED_volk_32f_expfast_32f_u_H + +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Computes fast exp (max 7% error) of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which exp is to be computed +*/ +static inline void volk_32f_expfast_32f_u_avx(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + __m256 aVal, bVal, a, b; + __m256i exp; + a = _mm256_set1_ps(A/Mln2); + b = _mm256_set1_ps(B-C); + + for(;number < eighthPoints; number++){ + aVal = _mm256_loadu_ps(aPtr); + exp = _mm256_cvtps_epi32(_mm256_add_ps(_mm256_mul_ps(a,aVal), b)); + bVal = _mm256_castsi256_ps(exp); + + _mm256_storeu_ps(bPtr, bVal); + aPtr += 8; + bPtr += 8; + } + + number = eighthPoints * 8; + for(;number < num_points; number++){ + *bPtr++ = expf(*aPtr++); + } +} + +#endif /* LV_HAVE_AVX for aligned */ + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes fast exp (max 7% error) of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_expfast_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m128 aVal, bVal, a, b; + __m128i exp; + a = _mm_set1_ps(A/Mln2); + b = _mm_set1_ps(B-C); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + exp = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(a,aVal), b)); + bVal = _mm_castsi128_ps(exp); + + _mm_storeu_ps(bPtr, bVal); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = expf(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes fast exp (max 7% error) of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_expfast_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = expf(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_expfast_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_index_max_16u.h b/volk/kernels/volk/volk_32f_index_max_16u.h index dd1aed2459..a5482a6a61 100644 --- a/volk/kernels/volk/volk_32f_index_max_16u.h +++ b/volk/kernels/volk/volk_32f_index_max_16u.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_index_max_16u_a_H #define INCLUDED_volk_32f_index_max_16u_a_H diff --git a/volk/kernels/volk/volk_32f_invsqrt_32f.h b/volk/kernels/volk/volk_32f_invsqrt_32f.h index 8ea12a73c4..21ed125053 100644 --- a/volk/kernels/volk/volk_32f_invsqrt_32f.h +++ b/volk/kernels/volk/volk_32f_invsqrt_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_invsqrt_32f_a_H #define INCLUDED_volk_32f_invsqrt_32f_a_H @@ -113,7 +135,7 @@ static inline void volk_32f_invsqrt_32f_neon(float* cVector, const float* aVecto aPtr += 4; cPtr += 4; } - + for(number=quarter_points * 4;number < num_points; number++) *cPtr++ = Q_rsqrt(*aPtr++); diff --git a/volk/kernels/volk/volk_32f_log2_32f.h b/volk/kernels/volk/volk_32f_log2_32f.h new file mode 100644 index 0000000000..892eeb1685 --- /dev/null +++ b/volk/kernels/volk/volk_32f_log2_32f.h @@ -0,0 +1,332 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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. + */ + +/* + * This kernel was adapted from Jose Fonseca's Fast SSE2 log implementation + * http://jrfonseca.blogspot.in/2008/09/fast-sse2-pow-tables-or-polynomials.htm + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + * This is the MIT License (MIT) + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <math.h> + +#define POLY0(x, c0) _mm_set1_ps(c0) +#define POLY1(x, c0, c1) _mm_add_ps(_mm_mul_ps(POLY0(x, c1), x), _mm_set1_ps(c0)) +#define POLY2(x, c0, c1, c2) _mm_add_ps(_mm_mul_ps(POLY1(x, c1, c2), x), _mm_set1_ps(c0)) +#define POLY3(x, c0, c1, c2, c3) _mm_add_ps(_mm_mul_ps(POLY2(x, c1, c2, c3), x), _mm_set1_ps(c0)) +#define POLY4(x, c0, c1, c2, c3, c4) _mm_add_ps(_mm_mul_ps(POLY3(x, c1, c2, c3, c4), x), _mm_set1_ps(c0)) +#define POLY5(x, c0, c1, c2, c3, c4, c5) _mm_add_ps(_mm_mul_ps(POLY4(x, c1, c2, c3, c4, c5), x), _mm_set1_ps(c0)) + +#define LOG_POLY_DEGREE 6 + + +#ifndef INCLUDED_volk_32f_log2_32f_a_H +#define INCLUDED_volk_32f_log2_32f_a_H + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes base 2 log of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_log2_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = log2(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes base 2 log of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_log2_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m128 aVal, bVal, mantissa, frac, leadingOne; + __m128i bias, exp; + + for(;number < quarterPoints; number++){ + + aVal = _mm_load_ps(aPtr); + bias = _mm_set1_epi32(127); + leadingOne = _mm_set1_ps(1.0f); + exp = _mm_sub_epi32(_mm_srli_epi32(_mm_and_si128(_mm_castps_si128(aVal), _mm_set1_epi32(0x7f800000)), 23), bias); + bVal = _mm_cvtepi32_ps(exp); + + // Now to extract mantissa + frac = _mm_or_ps(leadingOne, _mm_and_ps(aVal, _mm_castsi128_ps(_mm_set1_epi32(0x7fffff)))); + + #if LOG_POLY_DEGREE == 6 + mantissa = POLY5( frac, 3.1157899f, -3.3241990f, 2.5988452f, -1.2315303f, 3.1821337e-1f, -3.4436006e-2f); + #elif LOG_POLY_DEGREE == 5 + mantissa = POLY4( frac, 2.8882704548164776201f, -2.52074962577807006663f, 1.48116647521213171641f, -0.465725644288844778798f, 0.0596515482674574969533f); + #elif LOG_POLY_DEGREE == 4 + mantissa = POLY3( frac, 2.61761038894603480148f, -1.75647175389045657003f, 0.688243882994381274313f, -0.107254423828329604454f); + #elif LOG_POLY_DEGREE == 3 + mantissa = POLY2( frac, 2.28330284476918490682f, -1.04913055217340124191f, 0.204446009836232697516f); + #else + #error + #endif + + bVal = _mm_add_ps(bVal, _mm_mul_ps(mantissa, _mm_sub_ps(frac, leadingOne))); + _mm_store_ps(bPtr, bVal); + + + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = log2(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + + +#ifdef LV_HAVE_NEON +#include <arm_neon.h> + +/* these macros allow us to embed logs in other kernels */ +#define VLOG2Q_NEON_PREAMBLE() \ + int32x4_t one = vdupq_n_s32(0x000800000); \ + /* minimax polynomial */ \ + float32x4_t p0 = vdupq_n_f32(-3.0400402727048585); \ + float32x4_t p1 = vdupq_n_f32(6.1129631282966113); \ + float32x4_t p2 = vdupq_n_f32(-5.3419892024633207); \ + float32x4_t p3 = vdupq_n_f32(3.2865287703753912); \ + float32x4_t p4 = vdupq_n_f32(-1.2669182593441635); \ + float32x4_t p5 = vdupq_n_f32(0.2751487703421256); \ + float32x4_t p6 = vdupq_n_f32(-0.0256910888150985); \ + int32x4_t exp_mask = vdupq_n_s32(0x7f800000); \ + int32x4_t sig_mask = vdupq_n_s32(0x007fffff); \ + int32x4_t exp_bias = vdupq_n_s32(127); + + +#define VLOG2Q_NEON_F32(log2_approx, aval) \ + int32x4_t exponent_i = vandq_s32(aval, exp_mask); \ + int32x4_t significand_i = vandq_s32(aval, sig_mask); \ + exponent_i = vshrq_n_s32(exponent_i, 23); \ + \ + /* extract the exponent and significand \ + we can treat this as fixed point to save ~9% on the \ + conversion + float add */ \ + significand_i = vorrq_s32(one, significand_i); \ + float32x4_t significand_f = vcvtq_n_f32_s32(significand_i,23); \ + /* debias the exponent and convert to float */ \ + exponent_i = vsubq_s32(exponent_i, exp_bias); \ + float32x4_t exponent_f = vcvtq_f32_s32(exponent_i); \ + \ + /* put the significand through a polynomial fit of log2(x) [1,2]\ + add the result to the exponent */ \ + log2_approx = vaddq_f32(exponent_f, p0); /* p0 */ \ + float32x4_t tmp1 = vmulq_f32(significand_f, p1); /* p1 * x */ \ + log2_approx = vaddq_f32(log2_approx, tmp1); \ + float32x4_t sig_2 = vmulq_f32(significand_f, significand_f); /* x^2 */ \ + tmp1 = vmulq_f32(sig_2, p2); /* p2 * x^2 */ \ + log2_approx = vaddq_f32(log2_approx, tmp1); \ + \ + float32x4_t sig_3 = vmulq_f32(sig_2, significand_f); /* x^3 */ \ + tmp1 = vmulq_f32(sig_3, p3); /* p3 * x^3 */ \ + log2_approx = vaddq_f32(log2_approx, tmp1); \ + float32x4_t sig_4 = vmulq_f32(sig_2, sig_2); /* x^4 */ \ + tmp1 = vmulq_f32(sig_4, p4); /* p4 * x^4 */ \ + log2_approx = vaddq_f32(log2_approx, tmp1); \ + float32x4_t sig_5 = vmulq_f32(sig_3, sig_2); /* x^5 */ \ + tmp1 = vmulq_f32(sig_5, p5); /* p5 * x^5 */ \ + log2_approx = vaddq_f32(log2_approx, tmp1); \ + float32x4_t sig_6 = vmulq_f32(sig_3, sig_3); /* x^6 */ \ + tmp1 = vmulq_f32(sig_6, p6); /* p6 * x^6 */ \ + log2_approx = vaddq_f32(log2_approx, tmp1); + +/*! + \brief Computes base 2 log of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_log2_32f_neon(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number; + const unsigned int quarterPoints = num_points / 4; + + int32x4_t aval; + float32x4_t log2_approx; + + VLOG2Q_NEON_PREAMBLE() + // lms + //p0 = vdupq_n_f32(-1.649132280361871); + //p1 = vdupq_n_f32(1.995047138579499); + //p2 = vdupq_n_f32(-0.336914839219728); + + // keep in mind a single precision float is represented as + // (-1)^sign * 2^exp * 1.significand, so the log2 is + // log2(2^exp * sig) = exponent + log2(1 + significand/(1<<23) + for(number = 0; number < quarterPoints; ++number){ + // load float in to an int register without conversion + aval = vld1q_s32((int*)aPtr); + + VLOG2Q_NEON_F32(log2_approx, aval) + + vst1q_f32(bPtr, log2_approx); + + aPtr += 4; + bPtr += 4; + } + + for(number = quarterPoints * 4; number < num_points; number++){ + *bPtr++ = log2(*aPtr++); + } +} + +#endif /* LV_HAVE_NEON */ + + +#endif /* INCLUDED_volk_32f_log2_32f_a_H */ + +#ifndef INCLUDED_volk_32f_log2_32f_u_H +#define INCLUDED_volk_32f_log2_32f_u_H + + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes base 2 log of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_log2_32f_u_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = log2(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes base 2 log of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which log is to be computed +*/ +static inline void volk_32f_log2_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m128 aVal, bVal, mantissa, frac, leadingOne; + __m128i bias, exp; + + for(;number < quarterPoints; number++){ + + aVal = _mm_loadu_ps(aPtr); + bias = _mm_set1_epi32(127); + leadingOne = _mm_set1_ps(1.0f); + exp = _mm_sub_epi32(_mm_srli_epi32(_mm_and_si128(_mm_castps_si128(aVal), _mm_set1_epi32(0x7f800000)), 23), bias); + bVal = _mm_cvtepi32_ps(exp); + + // Now to extract mantissa + frac = _mm_or_ps(leadingOne, _mm_and_ps(aVal, _mm_castsi128_ps(_mm_set1_epi32(0x7fffff)))); + + #if LOG_POLY_DEGREE == 6 + mantissa = POLY5( frac, 3.1157899f, -3.3241990f, 2.5988452f, -1.2315303f, 3.1821337e-1f, -3.4436006e-2f); + #elif LOG_POLY_DEGREE == 5 + mantissa = POLY4( frac, 2.8882704548164776201f, -2.52074962577807006663f, 1.48116647521213171641f, -0.465725644288844778798f, 0.0596515482674574969533f); + #elif LOG_POLY_DEGREE == 4 + mantissa = POLY3( frac, 2.61761038894603480148f, -1.75647175389045657003f, 0.688243882994381274313f, -0.107254423828329604454f); + #elif LOG_POLY_DEGREE == 3 + mantissa = POLY2( frac, 2.28330284476918490682f, -1.04913055217340124191f, 0.204446009836232697516f); + #else + #error + #endif + + bVal = _mm_add_ps(bVal, _mm_mul_ps(mantissa, _mm_sub_ps(frac, leadingOne))); + _mm_storeu_ps(bPtr, bVal); + + + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = log2(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#endif /* INCLUDED_volk_32f_log2_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_s32f_32f_fm_detect_32f.h b/volk/kernels/volk/volk_32f_s32f_32f_fm_detect_32f.h index 71881c2d5f..f03d80bdd6 100644 --- a/volk/kernels/volk/volk_32f_s32f_32f_fm_detect_32f.h +++ b/volk/kernels/volk/volk_32f_s32f_32f_fm_detect_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_32f_fm_detect_32f_a_H #define INCLUDED_volk_32f_s32f_32f_fm_detect_32f_a_H diff --git a/volk/kernels/volk/volk_32f_s32f_calc_spectral_noise_floor_32f.h b/volk/kernels/volk/volk_32f_s32f_calc_spectral_noise_floor_32f.h index bf05a882d5..9b9f5d3afb 100644 --- a/volk/kernels/volk/volk_32f_s32f_calc_spectral_noise_floor_32f.h +++ b/volk/kernels/volk/volk_32f_s32f_calc_spectral_noise_floor_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_calc_spectral_noise_floor_32f_a_H #define INCLUDED_volk_32f_s32f_calc_spectral_noise_floor_32f_a_H diff --git a/volk/kernels/volk/volk_32f_s32f_convert_16i.h b/volk/kernels/volk/volk_32f_s32f_convert_16i.h index 9fd758655f..c11c13b413 100644 --- a/volk/kernels/volk/volk_32f_s32f_convert_16i.h +++ b/volk/kernels/volk/volk_32f_s32f_convert_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_convert_16i_u_H #define INCLUDED_volk_32f_s32f_convert_16i_u_H @@ -5,6 +27,63 @@ #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value + \param inputVector The floating point input data buffer + \param outputVector The 16 bit output data buffer + \param scalar The value multiplied against each point in the input buffer + \param num_points The number of data values to be converted + */ +static inline void volk_32f_s32f_convert_16i_u_avx(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){ + unsigned int number = 0; + + const unsigned int eighthPoints = num_points / 8; + + const float* inputVectorPtr = (const float*)inputVector; + int16_t* outputVectorPtr = outputVector; + + float min_val = -32768; + float max_val = 32767; + float r; + + __m256 vScalar = _mm256_set1_ps(scalar); + __m256 inputVal, ret; + __m256i intInputVal; + __m128i intInputVal1, intInputVal2; + __m256 vmin_val = _mm256_set1_ps(min_val); + __m256 vmax_val = _mm256_set1_ps(max_val); + + for(;number < eighthPoints; number++){ + inputVal = _mm256_loadu_ps(inputVectorPtr); inputVectorPtr += 8; + + // Scale and clip + ret = _mm256_max_ps(_mm256_min_ps(_mm256_mul_ps(inputVal, vScalar), vmax_val), vmin_val); + + intInputVal = _mm256_cvtps_epi32(ret); + + intInputVal1 = _mm256_extractf128_si256(intInputVal, 0); + intInputVal2 = _mm256_extractf128_si256(intInputVal, 1); + + intInputVal1 = _mm_packs_epi32(intInputVal1, intInputVal2); + + _mm_storeu_si128((__m128i*)outputVectorPtr, intInputVal1); + outputVectorPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + r = inputVector[number] * scalar; + if(r > max_val) + r = max_val; + else if(r < min_val) + r = min_val; + outputVector[number] = (int16_t)rintf(r); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE2 #include <emmintrin.h> /*! @@ -158,6 +237,63 @@ static inline void volk_32f_s32f_convert_16i_generic(int16_t* outputVector, cons #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies each point in the input buffer by the scalar value, then converts the result into a 16 bit integer value + \param inputVector The floating point input data buffer + \param outputVector The 16 bit output data buffer + \param scalar The value multiplied against each point in the input buffer + \param num_points The number of data values to be converted + */ +static inline void volk_32f_s32f_convert_16i_a_avx(int16_t* outputVector, const float* inputVector, const float scalar, unsigned int num_points){ + unsigned int number = 0; + + const unsigned int eighthPoints = num_points / 8; + + const float* inputVectorPtr = (const float*)inputVector; + int16_t* outputVectorPtr = outputVector; + + float min_val = -32768; + float max_val = 32767; + float r; + + __m256 vScalar = _mm256_set1_ps(scalar); + __m256 inputVal, ret; + __m256i intInputVal; + __m128i intInputVal1, intInputVal2; + __m256 vmin_val = _mm256_set1_ps(min_val); + __m256 vmax_val = _mm256_set1_ps(max_val); + + for(;number < eighthPoints; number++){ + inputVal = _mm256_load_ps(inputVectorPtr); inputVectorPtr += 8; + + // Scale and clip + ret = _mm256_max_ps(_mm256_min_ps(_mm256_mul_ps(inputVal, vScalar), vmax_val), vmin_val); + + intInputVal = _mm256_cvtps_epi32(ret); + + intInputVal1 = _mm256_extractf128_si256(intInputVal, 0); + intInputVal2 = _mm256_extractf128_si256(intInputVal, 1); + + intInputVal1 = _mm_packs_epi32(intInputVal1, intInputVal2); + + _mm_store_si128((__m128i*)outputVectorPtr, intInputVal1); + outputVectorPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + r = inputVector[number] * scalar; + if(r > max_val) + r = max_val; + else if(r < min_val) + r = min_val; + outputVector[number] = (int16_t)rintf(r); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE2 #include <emmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32f_s32f_convert_32i.h b/volk/kernels/volk/volk_32f_s32f_convert_32i.h index 1a46093ee2..f8e804572f 100644 --- a/volk/kernels/volk/volk_32f_s32f_convert_32i.h +++ b/volk/kernels/volk/volk_32f_s32f_convert_32i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_convert_32i_u_H #define INCLUDED_volk_32f_s32f_convert_32i_u_H diff --git a/volk/kernels/volk/volk_32f_s32f_convert_8i.h b/volk/kernels/volk/volk_32f_s32f_convert_8i.h index b451505221..2f0cee98dd 100644 --- a/volk/kernels/volk/volk_32f_s32f_convert_8i.h +++ b/volk/kernels/volk/volk_32f_s32f_convert_8i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_convert_8i_u_H #define INCLUDED_volk_32f_s32f_convert_8i_u_H diff --git a/volk/kernels/volk/volk_32f_s32f_multiply_32f.h b/volk/kernels/volk/volk_32f_s32f_multiply_32f.h index 8665d4e90e..ee9e2b5c8b 100644 --- a/volk/kernels/volk/volk_32f_s32f_multiply_32f.h +++ b/volk/kernels/volk/volk_32f_s32f_multiply_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_multiply_32f_u_H #define INCLUDED_volk_32f_s32f_multiply_32f_u_H diff --git a/volk/kernels/volk/volk_32f_s32f_normalize.h b/volk/kernels/volk/volk_32f_s32f_normalize.h index a0bd33c7dc..95a25f53b4 100644 --- a/volk/kernels/volk/volk_32f_s32f_normalize.h +++ b/volk/kernels/volk/volk_32f_s32f_normalize.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_normalize_a_H #define INCLUDED_volk_32f_s32f_normalize_a_H diff --git a/volk/kernels/volk/volk_32f_s32f_power_32f.h b/volk/kernels/volk/volk_32f_s32f_power_32f.h index 2822444686..b8b441311f 100644 --- a/volk/kernels/volk/volk_32f_s32f_power_32f.h +++ b/volk/kernels/volk/volk_32f_s32f_power_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_power_32f_a_H #define INCLUDED_volk_32f_s32f_power_32f_a_H diff --git a/volk/kernels/volk/volk_32f_s32f_stddev_32f.h b/volk/kernels/volk/volk_32f_s32f_stddev_32f.h index 0622b278a6..590a7d26f1 100644 --- a/volk/kernels/volk/volk_32f_s32f_stddev_32f.h +++ b/volk/kernels/volk/volk_32f_s32f_stddev_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_s32f_stddev_32f_a_H #define INCLUDED_volk_32f_s32f_stddev_32f_a_H diff --git a/volk/kernels/volk/volk_32f_sin_32f.h b/volk/kernels/volk/volk_32f_sin_32f.h new file mode 100644 index 0000000000..48ce60c7ed --- /dev/null +++ b/volk/kernels/volk/volk_32f_sin_32f.h @@ -0,0 +1,211 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +#ifndef INCLUDED_volk_32f_sin_32f_a_H +#define INCLUDED_volk_32f_sin_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes sine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which sine is to be computed +*/ +static inline void volk_32f_sin_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + unsigned int i = 0; + + __m128 aVal, s, m4pi, pio4A, pio4B, cp1, cp2, cp3, cp4, cp5, ffours, ftwos, fones, fzeroes; + __m128 sine, cosine, condition1, condition2; + __m128i q, r, ones, twos, fours; + + m4pi = _mm_set1_ps(1.273239545); + pio4A = _mm_set1_ps(0.78515625); + pio4B = _mm_set1_ps(0.241876e-3); + ffours = _mm_set1_ps(4.0); + ftwos = _mm_set1_ps(2.0); + fones = _mm_set1_ps(1.0); + fzeroes = _mm_setzero_ps(); + ones = _mm_set1_epi32(1); + twos = _mm_set1_epi32(2); + fours = _mm_set1_epi32(4); + + cp1 = _mm_set1_ps(1.0); + cp2 = _mm_set1_ps(0.83333333e-1); + cp3 = _mm_set1_ps(0.2777778e-2); + cp4 = _mm_set1_ps(0.49603e-4); + cp5 = _mm_set1_ps(0.551e-6); + + for(;number < quarterPoints; number++){ + aVal = _mm_load_ps(aPtr); + s = _mm_sub_ps(aVal, _mm_and_ps(_mm_mul_ps(aVal, ftwos), _mm_cmplt_ps(aVal, fzeroes))); + q = _mm_cvtps_epi32(_mm_mul_ps(s, m4pi)); + r = _mm_add_epi32(q, _mm_and_si128(q, ones)); + + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4A)); + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4B)); + + s = _mm_div_ps(s, _mm_set1_ps(8.0)); // The constant is 2^N, for 3 times argument reduction + s = _mm_mul_ps(s, s); + // Evaluate Taylor series + s = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(s, cp5), cp4), s), cp3), s), cp2), s), cp1), s); + + for(i = 0; i < 3; i++) { + s = _mm_mul_ps(s, _mm_sub_ps(ffours, s)); + } + s = _mm_div_ps(s, ftwos); + + sine = _mm_sqrt_ps(_mm_mul_ps(_mm_sub_ps(ftwos, s), s)); + cosine = _mm_sub_ps(fones, s); + + condition1 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, ones), twos)), fzeroes); + condition2 = _mm_cmpneq_ps(_mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(q, fours)), fzeroes), _mm_cmplt_ps(aVal, fzeroes)); + // Need this condition only for cos + //condition3 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, twos), fours)), fzeroes); + + sine = _mm_add_ps(sine, _mm_and_ps(_mm_sub_ps(cosine, sine), condition1)); + sine = _mm_sub_ps(sine, _mm_and_ps(_mm_mul_ps(sine, _mm_set1_ps(2.0f)), condition2)); + _mm_store_ps(bPtr, sine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = sin(*aPtr++); + } +} +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_sin_32f_a_H */ + +#ifndef INCLUDED_volk_32f_sin_32f_u_H +#define INCLUDED_volk_32f_sin_32f_u_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes sine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which sine is to be computed +*/ +static inline void volk_32f_sin_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + unsigned int i = 0; + + __m128 aVal, s, m4pi, pio4A, pio4B, cp1, cp2, cp3, cp4, cp5, ffours, ftwos, fones, fzeroes; + __m128 sine, cosine, condition1, condition2; + __m128i q, r, ones, twos, fours; + + m4pi = _mm_set1_ps(1.273239545); + pio4A = _mm_set1_ps(0.78515625); + pio4B = _mm_set1_ps(0.241876e-3); + ffours = _mm_set1_ps(4.0); + ftwos = _mm_set1_ps(2.0); + fones = _mm_set1_ps(1.0); + fzeroes = _mm_setzero_ps(); + ones = _mm_set1_epi32(1); + twos = _mm_set1_epi32(2); + fours = _mm_set1_epi32(4); + + cp1 = _mm_set1_ps(1.0); + cp2 = _mm_set1_ps(0.83333333e-1); + cp3 = _mm_set1_ps(0.2777778e-2); + cp4 = _mm_set1_ps(0.49603e-4); + cp5 = _mm_set1_ps(0.551e-6); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + s = _mm_sub_ps(aVal, _mm_and_ps(_mm_mul_ps(aVal, ftwos), _mm_cmplt_ps(aVal, fzeroes))); + q = _mm_cvtps_epi32(_mm_mul_ps(s, m4pi)); + r = _mm_add_epi32(q, _mm_and_si128(q, ones)); + + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4A)); + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4B)); + + s = _mm_div_ps(s, _mm_set1_ps(8.0)); // The constant is 2^N, for 3 times argument reduction + s = _mm_mul_ps(s, s); + // Evaluate Taylor series + s = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(s, cp5), cp4), s), cp3), s), cp2), s), cp1), s); + + for(i = 0; i < 3; i++) { + s = _mm_mul_ps(s, _mm_sub_ps(ffours, s)); + } + s = _mm_div_ps(s, ftwos); + + sine = _mm_sqrt_ps(_mm_mul_ps(_mm_sub_ps(ftwos, s), s)); + cosine = _mm_sub_ps(fones, s); + + condition1 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, ones), twos)), fzeroes); + condition2 = _mm_cmpneq_ps(_mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(q, fours)), fzeroes), _mm_cmplt_ps(aVal, fzeroes)); + + sine = _mm_add_ps(sine, _mm_and_ps(_mm_sub_ps(cosine, sine), condition1)); + sine = _mm_sub_ps(sine, _mm_and_ps(_mm_mul_ps(sine, _mm_set1_ps(2.0f)), condition2)); + _mm_storeu_ps(bPtr, sine); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = sin(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes sine of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which sine is to be computed +*/ +static inline void volk_32f_sin_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *bPtr++ = sin(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_sin_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_sqrt_32f.h b/volk/kernels/volk/volk_32f_sqrt_32f.h index f8f8cbd221..fb70b29125 100644 --- a/volk/kernels/volk/volk_32f_sqrt_32f.h +++ b/volk/kernels/volk/volk_32f_sqrt_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_sqrt_32f_a_H #define INCLUDED_volk_32f_sqrt_32f_a_H diff --git a/volk/kernels/volk/volk_32f_stddev_and_mean_32f_x2.h b/volk/kernels/volk/volk_32f_stddev_and_mean_32f_x2.h index 9bded6713d..9d5f709943 100644 --- a/volk/kernels/volk/volk_32f_stddev_and_mean_32f_x2.h +++ b/volk/kernels/volk/volk_32f_stddev_and_mean_32f_x2.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_stddev_and_mean_32f_x2_a_H #define INCLUDED_volk_32f_stddev_and_mean_32f_x2_a_H diff --git a/volk/kernels/volk/volk_32f_tan_32f.h b/volk/kernels/volk/volk_32f_tan_32f.h new file mode 100644 index 0000000000..05e52aa809 --- /dev/null +++ b/volk/kernels/volk/volk_32f_tan_32f.h @@ -0,0 +1,220 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <math.h> +#include <inttypes.h> + +#ifndef INCLUDED_volk_32f_tan_32f_a_H +#define INCLUDED_volk_32f_tan_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes tangent of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which tangent is to be computed +*/ +static inline void volk_32f_tan_32f_a_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + unsigned int i = 0; + + __m128 aVal, s, m4pi, pio4A, pio4B, cp1, cp2, cp3, cp4, cp5, ffours, ftwos, fones, fzeroes; + __m128 sine, cosine, tangent, condition1, condition2, condition3; + __m128i q, r, ones, twos, fours; + + m4pi = _mm_set1_ps(1.273239545); + pio4A = _mm_set1_ps(0.78515625); + pio4B = _mm_set1_ps(0.241876e-3); + ffours = _mm_set1_ps(4.0); + ftwos = _mm_set1_ps(2.0); + fones = _mm_set1_ps(1.0); + fzeroes = _mm_setzero_ps(); + ones = _mm_set1_epi32(1); + twos = _mm_set1_epi32(2); + fours = _mm_set1_epi32(4); + + cp1 = _mm_set1_ps(1.0); + cp2 = _mm_set1_ps(0.83333333e-1); + cp3 = _mm_set1_ps(0.2777778e-2); + cp4 = _mm_set1_ps(0.49603e-4); + cp5 = _mm_set1_ps(0.551e-6); + + for(;number < quarterPoints; number++){ + aVal = _mm_load_ps(aPtr); + s = _mm_sub_ps(aVal, _mm_and_ps(_mm_mul_ps(aVal, ftwos), _mm_cmplt_ps(aVal, fzeroes))); + q = _mm_cvtps_epi32(_mm_mul_ps(s, m4pi)); + r = _mm_add_epi32(q, _mm_and_si128(q, ones)); + + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4A)); + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4B)); + + s = _mm_div_ps(s, _mm_set1_ps(8.0)); // The constant is 2^N, for 3 times argument reduction + s = _mm_mul_ps(s, s); + // Evaluate Taylor series + s = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(s, cp5), cp4), s), cp3), s), cp2), s), cp1), s); + + for(i = 0; i < 3; i++){ + s = _mm_mul_ps(s, _mm_sub_ps(ffours, s)); + } + s = _mm_div_ps(s, ftwos); + + sine = _mm_sqrt_ps(_mm_mul_ps(_mm_sub_ps(ftwos, s), s)); + cosine = _mm_sub_ps(fones, s); + + condition1 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, ones), twos)), fzeroes); + condition2 = _mm_cmpneq_ps(_mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(q, fours)), fzeroes), _mm_cmplt_ps(aVal, fzeroes)); + condition3 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, twos), fours)), fzeroes); + + __m128 temp = cosine; + cosine = _mm_add_ps(cosine, _mm_and_ps(_mm_sub_ps(sine, cosine), condition1)); + sine = _mm_add_ps(sine, _mm_and_ps(_mm_sub_ps(temp, sine), condition1)); + sine = _mm_sub_ps(sine, _mm_and_ps(_mm_mul_ps(sine, _mm_set1_ps(2.0f)), condition2)); + cosine = _mm_sub_ps(cosine, _mm_and_ps(_mm_mul_ps(cosine, _mm_set1_ps(2.0f)), condition3)); + tangent = _mm_div_ps(sine, cosine); + _mm_store_ps(bPtr, tangent); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = tan(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_tan_32f_a_H */ + +#ifndef INCLUDED_volk_32f_tan_32f_u_H +#define INCLUDED_volk_32f_tan_32f_u_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes tangent of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which tangent is to be computed +*/ +static inline void volk_32f_tan_32f_u_sse4_1(float* bVector, const float* aVector, unsigned int num_points){ + + float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + unsigned int quarterPoints = num_points / 4; + unsigned int i = 0; + + __m128 aVal, s, m4pi, pio4A, pio4B, cp1, cp2, cp3, cp4, cp5, ffours, ftwos, fones, fzeroes; + __m128 sine, cosine, tangent, condition1, condition2, condition3; + __m128i q, r, ones, twos, fours; + + m4pi = _mm_set1_ps(1.273239545); + pio4A = _mm_set1_ps(0.78515625); + pio4B = _mm_set1_ps(0.241876e-3); + ffours = _mm_set1_ps(4.0); + ftwos = _mm_set1_ps(2.0); + fones = _mm_set1_ps(1.0); + fzeroes = _mm_setzero_ps(); + ones = _mm_set1_epi32(1); + twos = _mm_set1_epi32(2); + fours = _mm_set1_epi32(4); + + cp1 = _mm_set1_ps(1.0); + cp2 = _mm_set1_ps(0.83333333e-1); + cp3 = _mm_set1_ps(0.2777778e-2); + cp4 = _mm_set1_ps(0.49603e-4); + cp5 = _mm_set1_ps(0.551e-6); + + for(;number < quarterPoints; number++){ + aVal = _mm_loadu_ps(aPtr); + s = _mm_sub_ps(aVal, _mm_and_ps(_mm_mul_ps(aVal, ftwos), _mm_cmplt_ps(aVal, fzeroes))); + q = _mm_cvtps_epi32(_mm_mul_ps(s, m4pi)); + r = _mm_add_epi32(q, _mm_and_si128(q, ones)); + + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4A)); + s = _mm_sub_ps(s, _mm_mul_ps(_mm_cvtepi32_ps(r), pio4B)); + + s = _mm_div_ps(s, _mm_set1_ps(8.0)); // The constant is 2^N, for 3 times argument reduction + s = _mm_mul_ps(s, s); + // Evaluate Taylor series + s = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_sub_ps(_mm_mul_ps(s, cp5), cp4), s), cp3), s), cp2), s), cp1), s); + + for(i = 0; i < 3; i++){ + s = _mm_mul_ps(s, _mm_sub_ps(ffours, s)); + } + s = _mm_div_ps(s, ftwos); + + sine = _mm_sqrt_ps(_mm_mul_ps(_mm_sub_ps(ftwos, s), s)); + cosine = _mm_sub_ps(fones, s); + + condition1 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, ones), twos)), fzeroes); + condition2 = _mm_cmpneq_ps(_mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(q, fours)), fzeroes), _mm_cmplt_ps(aVal, fzeroes)); + condition3 = _mm_cmpneq_ps(_mm_cvtepi32_ps(_mm_and_si128(_mm_add_epi32(q, twos), fours)), fzeroes); + + __m128 temp = cosine; + cosine = _mm_add_ps(cosine, _mm_and_ps(_mm_sub_ps(sine, cosine), condition1)); + sine = _mm_add_ps(sine, _mm_and_ps(_mm_sub_ps(temp, sine), condition1)); + sine = _mm_sub_ps(sine, _mm_and_ps(_mm_mul_ps(sine, _mm_set1_ps(2.0f)), condition2)); + cosine = _mm_sub_ps(cosine, _mm_and_ps(_mm_mul_ps(cosine, _mm_set1_ps(2.0f)), condition3)); + tangent = _mm_div_ps(sine, cosine); + _mm_storeu_ps(bPtr, tangent); + aPtr += 4; + bPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *bPtr++ = tan(*aPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes tangent of input vector and stores results in output vector + \param bVector The vector where results will be stored + \param aVector The input vector of floats + \param num_points Number of points for which tangent is to be computed +*/ +static inline void volk_32f_tan_32f_generic(float* bVector, const float* aVector, unsigned int num_points){ + float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(; number < num_points; number++){ + *bPtr++ = tan(*aPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_tan_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_tanh_32f.h b/volk/kernels/volk/volk_32f_tanh_32f.h new file mode 100644 index 0000000000..cdb685f811 --- /dev/null +++ b/volk/kernels/volk/volk_32f_tanh_32f.h @@ -0,0 +1,318 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_tanh_32f_a_H +#define INCLUDED_volk_32f_tanh_32f_a_H + +#include <inttypes.h> +#include <stdio.h> +#include <math.h> +#include <string.h> + +#ifdef LV_HAVE_GENERIC +/*! +\brief Calculates tanh(x) +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_generic(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + float* cPtr = cVector; + const float* aPtr = aVector; + for(; number < num_points; number++) { + *cPtr++ = tanh(*aPtr++); + } +} + +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_GENERIC +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_series(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + float* cPtr = cVector; + const float* aPtr = aVector; + for(; number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} + +#endif /* LV_HAVE_GENERIC */ + + + +#ifdef LV_HAVE_SSE +#include <xmmintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_a_sse(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m128 aVal, cVal, x2, a, b; + __m128 const1, const2, const3, const4, const5, const6; + const1 = _mm_set_ps1(135135.0f); + const2 = _mm_set_ps1(17325.0f); + const3 = _mm_set_ps1(378.0f); + const4 = _mm_set_ps1(62370.0f); + const5 = _mm_set_ps1(3150.0f); + const6 = _mm_set_ps1(28.0f); + for(;number < quarterPoints; number++){ + + aVal = _mm_load_ps(aPtr); + x2 = _mm_mul_ps(aVal, aVal); + a = _mm_mul_ps(aVal, _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const2, _mm_mul_ps(x2, _mm_add_ps(const3, x2)))))); + b = _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const4, _mm_mul_ps(x2, _mm_add_ps(const5, _mm_mul_ps(x2, const6)))))); + + cVal = _mm_div_ps(a, b); + + _mm_store_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_SSE */ + + +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_a_avx(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m256 aVal, cVal, x2, a, b; + __m256 const1, const2, const3, const4, const5, const6; + const1 = _mm256_set1_ps(135135.0f); + const2 = _mm256_set1_ps(17325.0f); + const3 = _mm256_set1_ps(378.0f); + const4 = _mm256_set1_ps(62370.0f); + const5 = _mm256_set1_ps(3150.0f); + const6 = _mm256_set1_ps(28.0f); + for(;number < eighthPoints; number++){ + + aVal = _mm256_load_ps(aPtr); + x2 = _mm256_mul_ps(aVal, aVal); + a = _mm256_mul_ps(aVal, _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const2, _mm256_mul_ps(x2, _mm256_add_ps(const3, x2)))))); + b = _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const4, _mm256_mul_ps(x2, _mm256_add_ps(const5, _mm256_mul_ps(x2, const6)))))); + + cVal = _mm256_div_ps(a, b); + + _mm256_store_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 8; + cPtr += 8; + } + + number = eighthPoints * 8; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_AVX */ + + + + +#ifdef LV_HAVE_SSE +#include <xmmintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_u_sse(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m128 aVal, cVal, x2, a, b; + __m128 const1, const2, const3, const4, const5, const6; + const1 = _mm_set_ps1(135135.0f); + const2 = _mm_set_ps1(17325.0f); + const3 = _mm_set_ps1(378.0f); + const4 = _mm_set_ps1(62370.0f); + const5 = _mm_set_ps1(3150.0f); + const6 = _mm_set_ps1(28.0f); + for(;number < quarterPoints; number++){ + + aVal = _mm_loadu_ps(aPtr); + x2 = _mm_mul_ps(aVal, aVal); + a = _mm_mul_ps(aVal, _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const2, _mm_mul_ps(x2, _mm_add_ps(const3, x2)))))); + b = _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const4, _mm_mul_ps(x2, _mm_add_ps(const5, _mm_mul_ps(x2, const6)))))); + + cVal = _mm_div_ps(a, b); + + _mm_storeu_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_SSE */ + + + +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_u_avx(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m256 aVal, cVal, x2, a, b; + __m256 const1, const2, const3, const4, const5, const6; + const1 = _mm256_set1_ps(135135.0f); + const2 = _mm256_set1_ps(17325.0f); + const3 = _mm256_set1_ps(378.0f); + const4 = _mm256_set1_ps(62370.0f); + const5 = _mm256_set1_ps(3150.0f); + const6 = _mm256_set1_ps(28.0f); + for(;number < eighthPoints; number++){ + + aVal = _mm256_loadu_ps(aPtr); + x2 = _mm256_mul_ps(aVal, aVal); + a = _mm256_mul_ps(aVal, _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const2, _mm256_mul_ps(x2, _mm256_add_ps(const3, x2)))))); + b = _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const4, _mm256_mul_ps(x2, _mm256_add_ps(const5, _mm256_mul_ps(x2, const6)))))); + + cVal = _mm256_div_ps(a, b); + + _mm256_storeu_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 8; + cPtr += 8; + } + + number = eighthPoints * 8; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_AVX */ + +#endif /* INCLUDED_volk_32f_tanh_32f_a_H */ diff --git a/volk/kernels/volk/volk_32f_x2_add_32f.h b/volk/kernels/volk/volk_32f_x2_add_32f.h index a9a1d4fbf0..0c66b271ae 100644 --- a/volk/kernels/volk/volk_32f_x2_add_32f.h +++ b/volk/kernels/volk/volk_32f_x2_add_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_add_32f_u_H #define INCLUDED_volk_32f_x2_add_32f_u_H @@ -136,7 +158,7 @@ static inline void volk_32f_x2_add_32f_u_neon(float* cVector, const float* aVect // vector add cVal = vaddq_f32(aVal, bVal); // Store the results back into the C container - vst1q_f32(cPtr,cVal); + vst1q_f32(cPtr,cVal); aPtr += 4; // q uses quadwords, 4 floats per vadd bPtr += 4; diff --git a/volk/kernels/volk/volk_32f_x2_divide_32f.h b/volk/kernels/volk/volk_32f_x2_divide_32f.h index d5a7c7d7c0..bbb5cbc9c4 100644 --- a/volk/kernels/volk/volk_32f_x2_divide_32f.h +++ b/volk/kernels/volk/volk_32f_x2_divide_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_divide_32f_a_H #define INCLUDED_volk_32f_x2_divide_32f_a_H diff --git a/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h b/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h index b637f17777..6e38e33dc7 100644 --- a/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h +++ b/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_dot_prod_16i_H #define INCLUDED_volk_32f_x2_dot_prod_16i_H diff --git a/volk/kernels/volk/volk_32f_x2_dot_prod_32f.h b/volk/kernels/volk/volk_32f_x2_dot_prod_32f.h index ac6f56976b..a98802b4b5 100644 --- a/volk/kernels/volk/volk_32f_x2_dot_prod_32f.h +++ b/volk/kernels/volk/volk_32f_x2_dot_prod_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_dot_prod_32f_u_H #define INCLUDED_volk_32f_x2_dot_prod_32f_u_H diff --git a/volk/kernels/volk/volk_32f_x2_interleave_32fc.h b/volk/kernels/volk/volk_32f_x2_interleave_32fc.h index 3591b24d69..bf7e9250cf 100644 --- a/volk/kernels/volk/volk_32f_x2_interleave_32fc.h +++ b/volk/kernels/volk/volk_32f_x2_interleave_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_interleave_32fc_a_H #define INCLUDED_volk_32f_x2_interleave_32fc_a_H @@ -70,7 +92,7 @@ static inline void volk_32f_x2_interleave_32fc_neon(lv_32fc_t* complexVector, co iBuffer += 4; qBuffer += 4; complexVectorPtr += 8; - } + } for(number=quarter_points * 4; number < num_points; ++number) { *complexVectorPtr++ = *iBuffer++; diff --git a/volk/kernels/volk/volk_32f_x2_max_32f.h b/volk/kernels/volk/volk_32f_x2_max_32f.h index a1403fba18..7e4e2afc8e 100644 --- a/volk/kernels/volk/volk_32f_x2_max_32f.h +++ b/volk/kernels/volk/volk_32f_x2_max_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_max_32f_a_H #define INCLUDED_volk_32f_x2_max_32f_a_H @@ -60,7 +82,7 @@ static inline void volk_32f_x2_max_32f_neon(float* cVector, const float* aVector const float* aPtr = aVector; const float* bPtr= bVector; unsigned int number = 0; - + float32x4_t a_vec, b_vec, c_vec; for(number = 0; number < quarter_points; number++){ a_vec = vld1q_f32(aPtr); diff --git a/volk/kernels/volk/volk_32f_x2_min_32f.h b/volk/kernels/volk/volk_32f_x2_min_32f.h index f7598d6354..b67c7b8471 100644 --- a/volk/kernels/volk/volk_32f_x2_min_32f.h +++ b/volk/kernels/volk/volk_32f_x2_min_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_min_32f_a_H #define INCLUDED_volk_32f_x2_min_32f_a_H diff --git a/volk/kernels/volk/volk_32f_x2_multiply_32f.h b/volk/kernels/volk/volk_32f_x2_multiply_32f.h index 00b31859d6..b05421573d 100644 --- a/volk/kernels/volk/volk_32f_x2_multiply_32f.h +++ b/volk/kernels/volk/volk_32f_x2_multiply_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_multiply_32f_u_H #define INCLUDED_volk_32f_x2_multiply_32f_u_H diff --git a/volk/kernels/volk/volk_32f_x2_pow_32f.h b/volk/kernels/volk/volk_32f_x2_pow_32f.h new file mode 100644 index 0000000000..431c4c7021 --- /dev/null +++ b/volk/kernels/volk/volk_32f_x2_pow_32f.h @@ -0,0 +1,298 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <math.h> + +#define POLY0(x, c0) _mm_set1_ps(c0) +#define POLY1(x, c0, c1) _mm_add_ps(_mm_mul_ps(POLY0(x, c1), x), _mm_set1_ps(c0)) +#define POLY2(x, c0, c1, c2) _mm_add_ps(_mm_mul_ps(POLY1(x, c1, c2), x), _mm_set1_ps(c0)) +#define POLY3(x, c0, c1, c2, c3) _mm_add_ps(_mm_mul_ps(POLY2(x, c1, c2, c3), x), _mm_set1_ps(c0)) +#define POLY4(x, c0, c1, c2, c3, c4) _mm_add_ps(_mm_mul_ps(POLY3(x, c1, c2, c3, c4), x), _mm_set1_ps(c0)) +#define POLY5(x, c0, c1, c2, c3, c4, c5) _mm_add_ps(_mm_mul_ps(POLY4(x, c1, c2, c3, c4, c5), x), _mm_set1_ps(c0)) + +#define LOG_POLY_DEGREE 3 + +#ifndef INCLUDED_volk_32f_x2_pow_32f_a_H +#define INCLUDED_volk_32f_x2_pow_32f_a_H + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes pow(x,y) by using exp and log + \param cVector The vector where results will be stored + \param aVector The input vector of bases + \param bVector The input vector of indices + \param num_points Number of points for which pow is to be computed +*/ +static inline void volk_32f_x2_pow_32f_a_sse4_1(float* cVector, const float* bVector, const float* aVector, unsigned int num_points){ + + float* cPtr = cVector; + const float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m128 aVal, bVal, cVal, logarithm, mantissa, frac, leadingOne; + __m128 tmp, fx, mask, pow2n, z, y; + __m128 one, exp_hi, exp_lo, ln2, log2EF, half, exp_C1, exp_C2; + __m128 exp_p0, exp_p1, exp_p2, exp_p3, exp_p4, exp_p5; + __m128i bias, exp, emm0, pi32_0x7f; + + one = _mm_set1_ps(1.0); + exp_hi = _mm_set1_ps(88.3762626647949); + exp_lo = _mm_set1_ps(-88.3762626647949); + ln2 = _mm_set1_ps(0.6931471805); + log2EF = _mm_set1_ps(1.44269504088896341); + half = _mm_set1_ps(0.5); + exp_C1 = _mm_set1_ps(0.693359375); + exp_C2 = _mm_set1_ps(-2.12194440e-4); + pi32_0x7f = _mm_set1_epi32(0x7f); + + exp_p0 = _mm_set1_ps(1.9875691500e-4); + exp_p1 = _mm_set1_ps(1.3981999507e-3); + exp_p2 = _mm_set1_ps(8.3334519073e-3); + exp_p3 = _mm_set1_ps(4.1665795894e-2); + exp_p4 = _mm_set1_ps(1.6666665459e-1); + exp_p5 = _mm_set1_ps(5.0000001201e-1); + + for(;number < quarterPoints; number++){ + // First compute the logarithm + aVal = _mm_load_ps(aPtr); + bias = _mm_set1_epi32(127); + leadingOne = _mm_set1_ps(1.0f); + exp = _mm_sub_epi32(_mm_srli_epi32(_mm_and_si128(_mm_castps_si128(aVal), _mm_set1_epi32(0x7f800000)), 23), bias); + logarithm = _mm_cvtepi32_ps(exp); + + frac = _mm_or_ps(leadingOne, _mm_and_ps(aVal, _mm_castsi128_ps(_mm_set1_epi32(0x7fffff)))); + + #if LOG_POLY_DEGREE == 6 + mantissa = POLY5( frac, 3.1157899f, -3.3241990f, 2.5988452f, -1.2315303f, 3.1821337e-1f, -3.4436006e-2f); + #elif LOG_POLY_DEGREE == 5 + mantissa = POLY4( frac, 2.8882704548164776201f, -2.52074962577807006663f, 1.48116647521213171641f, -0.465725644288844778798f, 0.0596515482674574969533f); + #elif LOG_POLY_DEGREE == 4 + mantissa = POLY3( frac, 2.61761038894603480148f, -1.75647175389045657003f, 0.688243882994381274313f, -0.107254423828329604454f); + #elif LOG_POLY_DEGREE == 3 + mantissa = POLY2( frac, 2.28330284476918490682f, -1.04913055217340124191f, 0.204446009836232697516f); + #else + #error + #endif + + logarithm = _mm_add_ps(logarithm, _mm_mul_ps(mantissa, _mm_sub_ps(frac, leadingOne))); + logarithm = _mm_mul_ps(logarithm, ln2); + + + // Now calculate b*lna + bVal = _mm_load_ps(bPtr); + bVal = _mm_mul_ps(bVal, logarithm); + + // Now compute exp(b*lna) + tmp = _mm_setzero_ps(); + + bVal = _mm_max_ps(_mm_min_ps(bVal, exp_hi), exp_lo); + + fx = _mm_add_ps(_mm_mul_ps(bVal, log2EF), half); + + emm0 = _mm_cvttps_epi32(fx); + tmp = _mm_cvtepi32_ps(emm0); + + mask = _mm_and_ps(_mm_cmpgt_ps(tmp, fx), one); + fx = _mm_sub_ps(tmp, mask); + + tmp = _mm_mul_ps(fx, exp_C1); + z = _mm_mul_ps(fx, exp_C2); + bVal = _mm_sub_ps(_mm_sub_ps(bVal, tmp), z); + z = _mm_mul_ps(bVal, bVal); + + y = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(exp_p0, bVal), exp_p1), bVal); + y = _mm_add_ps(_mm_mul_ps(_mm_add_ps(y, exp_p2), bVal), exp_p3); + y = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(y, bVal), exp_p4), bVal); + y = _mm_add_ps(_mm_mul_ps(_mm_add_ps(y, exp_p5), z), bVal); + y = _mm_add_ps(y, one); + + emm0 = _mm_slli_epi32(_mm_add_epi32(_mm_cvttps_epi32(fx), pi32_0x7f), 23); + + pow2n = _mm_castsi128_ps(emm0); + cVal = _mm_mul_ps(y, pow2n); + + _mm_store_ps(cPtr, cVal); + + aPtr += 4; + bPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *cPtr++ = pow(*aPtr++, *bPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for aligned */ + +#endif /* INCLUDED_volk_32f_x2_pow_32f_a_H */ + +#ifndef INCLUDED_volk_32f_x2_pow_32f_u_H +#define INCLUDED_volk_32f_x2_pow_32f_u_H + +#ifdef LV_HAVE_GENERIC +/*! + \brief Computes pow(x,y) by using exp and log + \param cVector The vector where results will be stored + \param aVector The input vector of bases + \param bVector The input vector of indices + \param num_points Number of points for which pow is to be computed +*/ +static inline void volk_32f_x2_pow_32f_generic(float* cVector, const float* bVector, const float* aVector, unsigned int num_points){ + float* cPtr = cVector; + const float* bPtr = bVector; + const float* aPtr = aVector; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + *cPtr++ = pow(*aPtr++, *bPtr++); + } + +} +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> +/*! + \brief Computes pow(x,y) by using exp and log + \param cVector The vector where results will be stored + \param aVector The input vector of bases + \param bVector The input vector of indices + \param num_points Number of points for which pow is to be computed +*/ +static inline void volk_32f_x2_pow_32f_u_sse4_1(float* cVector, const float* bVector, const float* aVector, unsigned int num_points){ + + float* cPtr = cVector; + const float* bPtr = bVector; + const float* aPtr = aVector; + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m128 aVal, bVal, cVal, logarithm, mantissa, frac, leadingOne; + __m128 tmp, fx, mask, pow2n, z, y; + __m128 one, exp_hi, exp_lo, ln2, log2EF, half, exp_C1, exp_C2; + __m128 exp_p0, exp_p1, exp_p2, exp_p3, exp_p4, exp_p5; + __m128i bias, exp, emm0, pi32_0x7f; + + one = _mm_set1_ps(1.0); + exp_hi = _mm_set1_ps(88.3762626647949); + exp_lo = _mm_set1_ps(-88.3762626647949); + ln2 = _mm_set1_ps(0.6931471805); + log2EF = _mm_set1_ps(1.44269504088896341); + half = _mm_set1_ps(0.5); + exp_C1 = _mm_set1_ps(0.693359375); + exp_C2 = _mm_set1_ps(-2.12194440e-4); + pi32_0x7f = _mm_set1_epi32(0x7f); + + exp_p0 = _mm_set1_ps(1.9875691500e-4); + exp_p1 = _mm_set1_ps(1.3981999507e-3); + exp_p2 = _mm_set1_ps(8.3334519073e-3); + exp_p3 = _mm_set1_ps(4.1665795894e-2); + exp_p4 = _mm_set1_ps(1.6666665459e-1); + exp_p5 = _mm_set1_ps(5.0000001201e-1); + + for(;number < quarterPoints; number++){ + + // First compute the logarithm + aVal = _mm_loadu_ps(aPtr); + bias = _mm_set1_epi32(127); + leadingOne = _mm_set1_ps(1.0f); + exp = _mm_sub_epi32(_mm_srli_epi32(_mm_and_si128(_mm_castps_si128(aVal), _mm_set1_epi32(0x7f800000)), 23), bias); + logarithm = _mm_cvtepi32_ps(exp); + + frac = _mm_or_ps(leadingOne, _mm_and_ps(aVal, _mm_castsi128_ps(_mm_set1_epi32(0x7fffff)))); + + #if LOG_POLY_DEGREE == 6 + mantissa = POLY5( frac, 3.1157899f, -3.3241990f, 2.5988452f, -1.2315303f, 3.1821337e-1f, -3.4436006e-2f); + #elif LOG_POLY_DEGREE == 5 + mantissa = POLY4( frac, 2.8882704548164776201f, -2.52074962577807006663f, 1.48116647521213171641f, -0.465725644288844778798f, 0.0596515482674574969533f); + #elif LOG_POLY_DEGREE == 4 + mantissa = POLY3( frac, 2.61761038894603480148f, -1.75647175389045657003f, 0.688243882994381274313f, -0.107254423828329604454f); + #elif LOG_POLY_DEGREE == 3 + mantissa = POLY2( frac, 2.28330284476918490682f, -1.04913055217340124191f, 0.204446009836232697516f); + #else + #error + #endif + + logarithm = _mm_add_ps(logarithm, _mm_mul_ps(mantissa, _mm_sub_ps(frac, leadingOne))); + logarithm = _mm_mul_ps(logarithm, ln2); + + + // Now calculate b*lna + bVal = _mm_loadu_ps(bPtr); + bVal = _mm_mul_ps(bVal, logarithm); + + // Now compute exp(b*lna) + tmp = _mm_setzero_ps(); + + bVal = _mm_max_ps(_mm_min_ps(bVal, exp_hi), exp_lo); + + fx = _mm_add_ps(_mm_mul_ps(bVal, log2EF), half); + + emm0 = _mm_cvttps_epi32(fx); + tmp = _mm_cvtepi32_ps(emm0); + + mask = _mm_and_ps(_mm_cmpgt_ps(tmp, fx), one); + fx = _mm_sub_ps(tmp, mask); + + tmp = _mm_mul_ps(fx, exp_C1); + z = _mm_mul_ps(fx, exp_C2); + bVal = _mm_sub_ps(_mm_sub_ps(bVal, tmp), z); + z = _mm_mul_ps(bVal, bVal); + + y = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(exp_p0, bVal), exp_p1), bVal); + y = _mm_add_ps(_mm_mul_ps(_mm_add_ps(y, exp_p2), bVal), exp_p3); + y = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(y, bVal), exp_p4), bVal); + y = _mm_add_ps(_mm_mul_ps(_mm_add_ps(y, exp_p5), z), bVal); + y = _mm_add_ps(y, one); + + emm0 = _mm_slli_epi32(_mm_add_epi32(_mm_cvttps_epi32(fx), pi32_0x7f), 23); + + pow2n = _mm_castsi128_ps(emm0); + cVal = _mm_mul_ps(y, pow2n); + + _mm_storeu_ps(cPtr, cVal); + + aPtr += 4; + bPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *cPtr++ = pow(*aPtr++, *bPtr++); + } +} + +#endif /* LV_HAVE_SSE4_1 for unaligned */ + +#endif /* INCLUDED_volk_32f_x2_log2_32f_u_H */ diff --git a/volk/kernels/volk/volk_32f_x2_s32f_interleave_16ic.h b/volk/kernels/volk/volk_32f_x2_s32f_interleave_16ic.h index ce7b91a318..5d7eca8f4c 100644 --- a/volk/kernels/volk/volk_32f_x2_s32f_interleave_16ic.h +++ b/volk/kernels/volk/volk_32f_x2_s32f_interleave_16ic.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_s32f_interleave_16ic_a_H #define INCLUDED_volk_32f_x2_s32f_interleave_16ic_a_H diff --git a/volk/kernels/volk/volk_32f_x2_subtract_32f.h b/volk/kernels/volk/volk_32f_x2_subtract_32f.h index c725ef8d4f..a3aa8e0d6b 100644 --- a/volk/kernels/volk/volk_32f_x2_subtract_32f.h +++ b/volk/kernels/volk/volk_32f_x2_subtract_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x2_subtract_32f_a_H #define INCLUDED_volk_32f_x2_subtract_32f_a_H diff --git a/volk/kernels/volk/volk_32f_x3_sum_of_poly_32f.h b/volk/kernels/volk/volk_32f_x3_sum_of_poly_32f.h index 0d3c2168c7..cc40c67a66 100644 --- a/volk/kernels/volk/volk_32f_x3_sum_of_poly_32f.h +++ b/volk/kernels/volk/volk_32f_x3_sum_of_poly_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32f_x3_sum_of_poly_32f_a_H #define INCLUDED_volk_32f_x3_sum_of_poly_32f_a_H diff --git a/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h b/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h index 6d0c8480e0..0c3ef0d8b7 100644 --- a/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h +++ b/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_32f_dot_prod_32fc_a_H #define INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H @@ -296,7 +318,7 @@ static inline void volk_32fc_32f_dot_prod_32fc_neon_unroll ( lv_32fc_t* __restri const float* inputPtr = (float*)input; const float* tapsPtr = taps; float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f }; - float accVector_real[4]; + float accVector_real[4]; float accVector_imag[4]; float32x4x2_t inputVector0, inputVector1; @@ -305,14 +327,14 @@ static inline void volk_32fc_32f_dot_prod_32fc_neon_unroll ( lv_32fc_t* __restri float32x4_t tmp_real1, tmp_imag1; float32x4_t real_accumulator0, imag_accumulator0; float32x4_t real_accumulator1, imag_accumulator1; - + // zero out accumulators // take a *float, return float32x4_t real_accumulator0 = vld1q_f32( zero ); imag_accumulator0 = vld1q_f32( zero ); real_accumulator1 = vld1q_f32( zero ); imag_accumulator1 = vld1q_f32( zero ); - + for(number=0 ;number < quarterPoints; number++){ // load doublewords and duplicate in to second lane tapsVector0 = vld1q_f32(tapsPtr ); @@ -338,7 +360,7 @@ static inline void volk_32fc_32f_dot_prod_32fc_neon_unroll ( lv_32fc_t* __restri tapsPtr += 8; inputPtr += 16; } - + real_accumulator0 = vaddq_f32( real_accumulator0, real_accumulator1); imag_accumulator0 = vaddq_f32( imag_accumulator0, imag_accumulator1); // void vst1q_f32( float32_t * ptr, float32x4_t val); diff --git a/volk/kernels/volk/volk_32fc_32f_multiply_32fc.h b/volk/kernels/volk/volk_32fc_32f_multiply_32fc.h index 21b71998c2..0f5a141107 100644 --- a/volk/kernels/volk/volk_32fc_32f_multiply_32fc.h +++ b/volk/kernels/volk/volk_32fc_32f_multiply_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_32f_multiply_32fc_a_H #define INCLUDED_volk_32fc_32f_multiply_32fc_a_H diff --git a/volk/kernels/volk/volk_32fc_conjugate_32fc.h b/volk/kernels/volk/volk_32fc_conjugate_32fc.h index 0f74b01816..49d8a0fbda 100644 --- a/volk/kernels/volk/volk_32fc_conjugate_32fc.h +++ b/volk/kernels/volk/volk_32fc_conjugate_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_conjugate_32fc_u_H #define INCLUDED_volk_32fc_conjugate_32fc_u_H @@ -6,6 +28,44 @@ #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Takes the conjugate of a complex vector. + \param cVector The vector where the results will be stored + \param aVector Vector to be conjugated + \param num_points The number of complex values in aVector to be conjugated and stored into cVector + */ +static inline void volk_32fc_conjugate_32fc_u_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + + __m256 conjugator = _mm256_setr_ps(0, -0.f, 0, -0.f, 0, -0.f, 0, -0.f); + + for(;number < quarterPoints; number++){ + + x = _mm256_loadu_ps((float*)a); // Load the complex data as ar,ai,br,bi + + x = _mm256_xor_ps(x, conjugator); // conjugate register + + _mm256_storeu_ps((float*)c,x); // Store the results back into the C container + + a += 4; + c += 4; + } + + number = quarterPoints * 4; + + for(;number < num_points; number++) { + *c++ = lv_conj(*a++); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -70,6 +130,44 @@ static inline void volk_32fc_conjugate_32fc_generic(lv_32fc_t* cVector, const lv #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Takes the conjugate of a complex vector. + \param cVector The vector where the results will be stored + \param aVector Vector to be conjugated + \param num_points The number of complex values in aVector to be conjugated and stored into cVector + */ +static inline void volk_32fc_conjugate_32fc_a_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + + __m256 conjugator = _mm256_setr_ps(0, -0.f, 0, -0.f, 0, -0.f, 0, -0.f); + + for(;number < quarterPoints; number++){ + + x = _mm256_load_ps((float*)a); // Load the complex data as ar,ai,br,bi + + x = _mm256_xor_ps(x, conjugator); // conjugate register + + _mm256_store_ps((float*)c,x); // Store the results back into the C container + + a += 4; + c += 4; + } + + number = quarterPoints * 4; + + for(;number < num_points; number++) { + *c++ = lv_conj(*a++); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32fc_deinterleave_32f_x2.h b/volk/kernels/volk/volk_32fc_deinterleave_32f_x2.h index 0d33ed7e28..aed7f097b8 100644 --- a/volk/kernels/volk/volk_32fc_deinterleave_32f_x2.h +++ b/volk/kernels/volk/volk_32fc_deinterleave_32f_x2.h @@ -1,9 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_deinterleave_32f_x2_a_H #define INCLUDED_volk_32fc_deinterleave_32f_x2_a_H #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the complex vector into I & Q vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_32f_x2_a_avx(float* iBuffer, float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + const float* complexVectorPtr = (float*)complexVector; + float* iBufferPtr = iBuffer; + float* qBufferPtr = qBuffer; + + unsigned int number = 0; + // Mask for real and imaginary parts + const unsigned int eighthPoints = num_points / 8; + __m256 cplxValue1, cplxValue2, complex1, complex2, iValue, qValue; + for(;number < eighthPoints; number++){ + + cplxValue1 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue2 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20); + complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31); + + // Arrange in i1i2i3i4 format + iValue = _mm256_shuffle_ps(complex1, complex2, 0x88); + // Arrange in q1q2q3q4 format + qValue = _mm256_shuffle_ps(complex1, complex2, 0xdd); + + _mm256_store_ps(iBufferPtr, iValue); + _mm256_store_ps(qBufferPtr, qValue); + + iBufferPtr += 8; + qBufferPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE #include <xmmintrin.h> /*! @@ -49,6 +120,39 @@ static inline void volk_32fc_deinterleave_32f_x2_a_sse(float* iBuffer, float* qB } #endif /* LV_HAVE_SSE */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Deinterleaves the complex vector into I & Q vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_32f_x2_neon(float* iBuffer, float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + unsigned int quarter_points = num_points / 4; + const float* complexVectorPtr = (float*)complexVector; + float* iBufferPtr = iBuffer; + float* qBufferPtr = qBuffer; + float32x4x2_t complexInput; + + for(number = 0; number < quarter_points; number++){ + complexInput = vld2q_f32(complexVectorPtr); + vst1q_f32( iBufferPtr, complexInput.val[0] ); + vst1q_f32( qBufferPtr, complexInput.val[1] ); + complexVectorPtr += 8; + iBufferPtr += 4; + qBufferPtr += 4; + } + + for(number = quarter_points*4; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Deinterleaves the complex vector into I & Q vector data diff --git a/volk/kernels/volk/volk_32fc_deinterleave_64f_x2.h b/volk/kernels/volk/volk_32fc_deinterleave_64f_x2.h index 4a4c5509bd..9b872e05e2 100644 --- a/volk/kernels/volk/volk_32fc_deinterleave_64f_x2.h +++ b/volk/kernels/volk/volk_32fc_deinterleave_64f_x2.h @@ -1,9 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_deinterleave_64f_x2_u_H #define INCLUDED_volk_32fc_deinterleave_64f_x2_u_H #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_64f_x2_u_avx(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + + const float* complexVectorPtr = (float*)complexVector; + double* iBufferPtr = iBuffer; + double* qBufferPtr = qBuffer; + + const unsigned int quarterPoints = num_points / 4; + __m256 cplxValue; + __m128 complexH, complexL, fVal; + __m256d dVal; + + for(;number < quarterPoints; number++){ + + cplxValue = _mm256_loadu_ps(complexVectorPtr); + complexVectorPtr += 8; + + complexH = _mm256_extractf128_ps(cplxValue, 1); + complexL = _mm256_extractf128_ps(cplxValue, 0); + + // Arrange in i1i2i1i2 format + fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(2,0,2,0)); + dVal = _mm256_cvtps_pd(fVal); + _mm256_storeu_pd(iBufferPtr, dVal); + + // Arrange in q1q2q1q2 format + fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(3,1,3,1)); + dVal = _mm256_cvtps_pd(fVal); + _mm256_storeu_pd(qBufferPtr, dVal); + + iBufferPtr += 4; + qBufferPtr += 4; + } + + number = quarterPoints * 4; + for(; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE2 #include <emmintrin.h> /*! @@ -82,6 +155,57 @@ static inline void volk_32fc_deinterleave_64f_x2_generic(double* iBuffer, double #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_64f_x2_a_avx(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + + const float* complexVectorPtr = (float*)complexVector; + double* iBufferPtr = iBuffer; + double* qBufferPtr = qBuffer; + + const unsigned int quarterPoints = num_points / 4; + __m256 cplxValue; + __m128 complexH, complexL, fVal; + __m256d dVal; + + for(;number < quarterPoints; number++){ + + cplxValue = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + complexH = _mm256_extractf128_ps(cplxValue, 1); + complexL = _mm256_extractf128_ps(cplxValue, 0); + + // Arrange in i1i2i1i2 format + fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(2,0,2,0)); + dVal = _mm256_cvtps_pd(fVal); + _mm256_store_pd(iBufferPtr, dVal); + + // Arrange in q1q2q1q2 format + fVal = _mm_shuffle_ps(complexL, complexH, _MM_SHUFFLE(3,1,3,1)); + dVal = _mm256_cvtps_pd(fVal); + _mm256_store_pd(qBufferPtr, dVal); + + iBufferPtr += 4; + qBufferPtr += 4; + } + + number = quarterPoints * 4; + for(; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE2 #include <emmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32fc_deinterleave_imag_32f.h b/volk/kernels/volk/volk_32fc_deinterleave_imag_32f.h index b1968296f5..a590c83d7a 100644 --- a/volk/kernels/volk/volk_32fc_deinterleave_imag_32f.h +++ b/volk/kernels/volk/volk_32fc_deinterleave_imag_32f.h @@ -1,9 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_deinterleave_imag_32f_a_H #define INCLUDED_volk_32fc_deinterleave_imag_32f_a_H #include <inttypes.h> #include <stdio.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the complex vector into Q vector data + \param complexVector The complex input vector + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_imag_32f_a_avx(float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + const float* complexVectorPtr = (const float*)complexVector; + float* qBufferPtr = qBuffer; + + __m256 cplxValue1, cplxValue2, complex1, complex2, qValue; + for(;number < eighthPoints; number++){ + + cplxValue1 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue2 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20); + complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31); + + // Arrange in q1q2q3q4 format + qValue = _mm256_shuffle_ps(complex1, complex2, 0xdd); + + _mm256_store_ps(qBufferPtr, qValue); + + qBufferPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE #include <xmmintrin.h> /*! @@ -44,6 +108,35 @@ static inline void volk_32fc_deinterleave_imag_32f_a_sse(float* qBuffer, const l } #endif /* LV_HAVE_SSE */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Deinterleaves the complex vector into Q vector data + \param complexVector The complex input vector + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_imag_32f_neon(float* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + unsigned int quarter_points = num_points / 4; + const float* complexVectorPtr = (float*)complexVector; + float* qBufferPtr = qBuffer; + float32x4x2_t complexInput; + + for(number = 0; number < quarter_points; number++){ + complexInput = vld2q_f32(complexVectorPtr); + vst1q_f32( qBufferPtr, complexInput.val[1] ); + complexVectorPtr += 8; + qBufferPtr += 4; + } + + for(number = quarter_points*4; number < num_points; number++){ + complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Deinterleaves the complex vector into Q vector data diff --git a/volk/kernels/volk/volk_32fc_deinterleave_real_32f.h b/volk/kernels/volk/volk_32fc_deinterleave_real_32f.h index 3d57598135..c0e8d8fb34 100644 --- a/volk/kernels/volk/volk_32fc_deinterleave_real_32f.h +++ b/volk/kernels/volk/volk_32fc_deinterleave_real_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_deinterleave_real_32f_a_H #define INCLUDED_volk_32fc_deinterleave_real_32f_a_H @@ -62,7 +84,33 @@ static inline void volk_32fc_deinterleave_real_32f_generic(float* iBuffer, const } #endif /* LV_HAVE_GENERIC */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Deinterleaves the complex vector into I vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_real_32f_neon(float* iBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + unsigned int quarter_points = num_points / 4; + const float* complexVectorPtr = (float*)complexVector; + float* iBufferPtr = iBuffer; + float32x4x2_t complexInput; + for(number = 0; number < quarter_points; number++){ + complexInput = vld2q_f32(complexVectorPtr); + vst1q_f32( iBufferPtr, complexInput.val[0] ); + complexVectorPtr += 8; + iBufferPtr += 4; + } + for(number = quarter_points*4; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + complexVectorPtr++; + } +} +#endif /* LV_HAVE_NEON */ #endif /* INCLUDED_volk_32fc_deinterleave_real_32f_a_H */ diff --git a/volk/kernels/volk/volk_32fc_deinterleave_real_64f.h b/volk/kernels/volk/volk_32fc_deinterleave_real_64f.h index 1fa66e8add..eb1df386a8 100644 --- a/volk/kernels/volk/volk_32fc_deinterleave_real_64f.h +++ b/volk/kernels/volk/volk_32fc_deinterleave_real_64f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_deinterleave_real_64f_a_H #define INCLUDED_volk_32fc_deinterleave_real_64f_a_H diff --git a/volk/kernels/volk/volk_32fc_index_max_16u.h b/volk/kernels/volk/volk_32fc_index_max_16u.h index c8d7212401..bc47f7983b 100644 --- a/volk/kernels/volk/volk_32fc_index_max_16u.h +++ b/volk/kernels/volk/volk_32fc_index_max_16u.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_index_max_16u_a_H #define INCLUDED_volk_32fc_index_max_16u_a_H diff --git a/volk/kernels/volk/volk_32fc_magnitude_32f.h b/volk/kernels/volk/volk_32fc_magnitude_32f.h index b6da7f3630..d057b70f5e 100644 --- a/volk/kernels/volk/volk_32fc_magnitude_32f.h +++ b/volk/kernels/volk/volk_32fc_magnitude_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_magnitude_32f_u_H #define INCLUDED_volk_32fc_magnitude_32f_u_H @@ -5,6 +27,52 @@ #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector + \param complexVector The vector containing the complex input values + \param magnitudeVector The vector containing the real output values + \param num_points The number of complex values in complexVector to be calculated and stored into cVector + */ +static inline void volk_32fc_magnitude_32f_u_avx(float* magnitudeVector, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + const float* complexVectorPtr = (float*)complexVector; + float* magnitudeVectorPtr = magnitudeVector; + + __m256 cplxValue1, cplxValue2, complex1, complex2, result; + for(;number < eighthPoints; number++){ + cplxValue1 = _mm256_loadu_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue2 = _mm256_loadu_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue1 = _mm256_mul_ps(cplxValue1, cplxValue1); // Square the values + cplxValue2 = _mm256_mul_ps(cplxValue2, cplxValue2); // Square the Values + + complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20); + complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31); + + result = _mm256_hadd_ps(complex1, complex2); // Add the I2 and Q2 values + + result = _mm256_sqrt_ps(result); + + _mm256_storeu_ps(magnitudeVectorPtr, result); + magnitudeVectorPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + float val1Real = *complexVectorPtr++; + float val1Imag = *complexVectorPtr++; + *magnitudeVectorPtr++ = sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -123,6 +191,52 @@ static inline void volk_32fc_magnitude_32f_generic(float* magnitudeVector, const #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Calculates the magnitude of the complexVector and stores the results in the magnitudeVector + \param complexVector The vector containing the complex input values + \param magnitudeVector The vector containing the real output values + \param num_points The number of complex values in complexVector to be calculated and stored into cVector + */ +static inline void volk_32fc_magnitude_32f_a_avx(float* magnitudeVector, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + const float* complexVectorPtr = (float*)complexVector; + float* magnitudeVectorPtr = magnitudeVector; + + __m256 cplxValue1, cplxValue2, complex1, complex2, result; + for(;number < eighthPoints; number++){ + cplxValue1 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue2 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue1 = _mm256_mul_ps(cplxValue1, cplxValue1); // Square the values + cplxValue2 = _mm256_mul_ps(cplxValue2, cplxValue2); // Square the Values + + complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20); + complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31); + + result = _mm256_hadd_ps(complex1, complex2); // Add the I2 and Q2 values + + result = _mm256_sqrt_ps(result); + + _mm256_store_ps(magnitudeVectorPtr, result); + magnitudeVectorPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + float val1Real = *complexVectorPtr++; + float val1Imag = *complexVectorPtr++; + *magnitudeVectorPtr++ = sqrtf((val1Real * val1Real) + (val1Imag * val1Imag)); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32fc_magnitude_squared_32f.h b/volk/kernels/volk/volk_32fc_magnitude_squared_32f.h index 878794ba79..ed8eac62d9 100644 --- a/volk/kernels/volk/volk_32fc_magnitude_squared_32f.h +++ b/volk/kernels/volk/volk_32fc_magnitude_squared_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_magnitude_squared_32f_u_H #define INCLUDED_volk_32fc_magnitude_squared_32f_u_H @@ -5,6 +27,50 @@ #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Calculates the magnitude squared of the complexVector and stores the results in the magnitudeVector + \param complexVector The vector containing the complex input values + \param magnitudeVector The vector containing the real output values + \param num_points The number of complex values in complexVector to be calculated and stored into cVector + */ +static inline void volk_32fc_magnitude_squared_32f_u_avx(float* magnitudeVector, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + const float* complexVectorPtr = (float*)complexVector; + float* magnitudeVectorPtr = magnitudeVector; + + __m256 cplxValue1, cplxValue2, complex1, complex2, result; + for(;number < eighthPoints; number++){ + cplxValue1 = _mm256_loadu_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue2 = _mm256_loadu_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue1 = _mm256_mul_ps(cplxValue1, cplxValue1); // Square the values + cplxValue2 = _mm256_mul_ps(cplxValue2, cplxValue2); // Square the Values + + complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20); + complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31); + + result = _mm256_hadd_ps(complex1, complex2); // Add the I2 and Q2 values + + _mm256_storeu_ps(magnitudeVectorPtr, result); + magnitudeVectorPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + float val1Real = *complexVectorPtr++; + float val1Imag = *complexVectorPtr++; + *magnitudeVectorPtr++ = (val1Real * val1Real) + (val1Imag * val1Imag); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -119,6 +185,50 @@ static inline void volk_32fc_magnitude_squared_32f_generic(float* magnitudeVecto #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Calculates the magnitude squared of the complexVector and stores the results in the magnitudeVector + \param complexVector The vector containing the complex input values + \param magnitudeVector The vector containing the real output values + \param num_points The number of complex values in complexVector to be calculated and stored into cVector + */ +static inline void volk_32fc_magnitude_squared_32f_a_avx(float* magnitudeVector, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + const float* complexVectorPtr = (float*)complexVector; + float* magnitudeVectorPtr = magnitudeVector; + + __m256 cplxValue1, cplxValue2, complex1, complex2, result; + for(;number < eighthPoints; number++){ + cplxValue1 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue2 = _mm256_load_ps(complexVectorPtr); + complexVectorPtr += 8; + + cplxValue1 = _mm256_mul_ps(cplxValue1, cplxValue1); // Square the values + cplxValue2 = _mm256_mul_ps(cplxValue2, cplxValue2); // Square the Values + + complex1 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x20); + complex2 = _mm256_permute2f128_ps(cplxValue1, cplxValue2, 0x31); + + result = _mm256_hadd_ps(complex1, complex2); // Add the I2 and Q2 values + + _mm256_store_ps(magnitudeVectorPtr, result); + magnitudeVectorPtr += 8; + } + + number = eighthPoints * 8; + for(; number < num_points; number++){ + float val1Real = *complexVectorPtr++; + float val1Imag = *complexVectorPtr++; + *magnitudeVectorPtr++ = (val1Real * val1Real) + (val1Imag * val1Imag); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32fc_s32f_atan2_32f.h b/volk/kernels/volk/volk_32fc_s32f_atan2_32f.h index b076ab44ef..2e9221b593 100644 --- a/volk/kernels/volk/volk_32fc_s32f_atan2_32f.h +++ b/volk/kernels/volk/volk_32fc_s32f_atan2_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32f_atan2_32f_a_H #define INCLUDED_volk_32fc_s32f_atan2_32f_a_H diff --git a/volk/kernels/volk/volk_32fc_s32f_deinterleave_real_16i.h b/volk/kernels/volk/volk_32fc_s32f_deinterleave_real_16i.h index 9e10217a0f..0f24512b0e 100644 --- a/volk/kernels/volk/volk_32fc_s32f_deinterleave_real_16i.h +++ b/volk/kernels/volk/volk_32fc_s32f_deinterleave_real_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32f_deinterleave_real_16i_a_H #define INCLUDED_volk_32fc_s32f_deinterleave_real_16i_a_H diff --git a/volk/kernels/volk/volk_32fc_s32f_magnitude_16i.h b/volk/kernels/volk/volk_32fc_s32f_magnitude_16i.h index 09abd967d6..b8ac93a0ec 100644 --- a/volk/kernels/volk/volk_32fc_s32f_magnitude_16i.h +++ b/volk/kernels/volk/volk_32fc_s32f_magnitude_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32f_magnitude_16i_a_H #define INCLUDED_volk_32fc_s32f_magnitude_16i_a_H diff --git a/volk/kernels/volk/volk_32fc_s32f_power_32fc.h b/volk/kernels/volk/volk_32fc_s32f_power_32fc.h index b9dd13baf0..9ecca50d5c 100644 --- a/volk/kernels/volk/volk_32fc_s32f_power_32fc.h +++ b/volk/kernels/volk/volk_32fc_s32f_power_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32f_power_32fc_a_H #define INCLUDED_volk_32fc_s32f_power_32fc_a_H diff --git a/volk/kernels/volk/volk_32fc_s32f_power_spectrum_32f.h b/volk/kernels/volk/volk_32fc_s32f_power_spectrum_32f.h index f76d9d35e4..8927112344 100644 --- a/volk/kernels/volk/volk_32fc_s32f_power_spectrum_32f.h +++ b/volk/kernels/volk/volk_32fc_s32f_power_spectrum_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32f_power_spectrum_32f_a_H #define INCLUDED_volk_32fc_s32f_power_spectrum_32f_a_H diff --git a/volk/kernels/volk/volk_32fc_s32f_x2_power_spectral_density_32f.h b/volk/kernels/volk/volk_32fc_s32f_x2_power_spectral_density_32f.h index e73eb09f8f..517ade4822 100644 --- a/volk/kernels/volk/volk_32fc_s32f_x2_power_spectral_density_32f.h +++ b/volk/kernels/volk/volk_32fc_s32f_x2_power_spectral_density_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32f_x2_power_spectral_density_32f_a_H #define INCLUDED_volk_32fc_s32f_x2_power_spectral_density_32f_a_H @@ -5,6 +27,98 @@ #include <stdio.h> #include <math.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + +#ifdef LV_HAVE_LIB_SIMDMATH +#include <simdmath.h> +#endif /* LV_HAVE_LIB_SIMDMATH */ + +/*! + \brief Calculates the log10 power value divided by the RBW for each input point + \param logPowerOutput The 10.0 * log10((r*r + i*i)/RBW) for each data point + \param complexFFTInput The complex data output from the FFT point + \param normalizationFactor This value is divided against all the input values before the power is calculated + \param rbw The resolution bandwith of the fft spectrum + \param num_points The number of fft data points +*/ +static inline void volk_32fc_s32f_x2_power_spectral_density_32f_a_avx(float* logPowerOutput, const lv_32fc_t* complexFFTInput, const float normalizationFactor, const float rbw, unsigned int num_points){ + const float* inputPtr = (const float*)complexFFTInput; + float* destPtr = logPowerOutput; + uint64_t number = 0; + const float iRBW = 1.0 / rbw; + const float iNormalizationFactor = 1.0 / normalizationFactor; + +#ifdef LV_HAVE_LIB_SIMDMATH + __m256 magScalar = _mm256_set1_ps(10.0); + magScalar = _mm256_div_ps(magScalar, logf4(magScalar)); + + __m256 invRBW = _mm256_set1_ps(iRBW); + + __m256 invNormalizationFactor = _mm256_set1_ps(iNormalizationFactor); + + __m256 power; + __m256 input1, input2; + const uint64_t eighthPoints = num_points / 8; + for(;number < eighthPoints; number++){ + // Load the complex values + input1 =_mm256_load_ps(inputPtr); + inputPtr += 8; + input2 =_mm256_load_ps(inputPtr); + inputPtr += 8; + + // Apply the normalization factor + input1 = _mm256_mul_ps(input1, invNormalizationFactor); + input2 = _mm256_mul_ps(input2, invNormalizationFactor); + + // Multiply each value by itself + // (r1*r1), (i1*i1), (r2*r2), (i2*i2) + input1 = _mm256_mul_ps(input1, input1); + // (r3*r3), (i3*i3), (r4*r4), (i4*i4) + input2 = _mm256_mul_ps(input2, input2); + + // Horizontal add, to add (r*r) + (i*i) for each complex value + // (r1*r1)+(i1*i1), (r2*r2) + (i2*i2), (r3*r3)+(i3*i3), (r4*r4)+(i4*i4) + inputVal1 = _mm256_permute2f128_ps(input1, input2, 0x20); + inputVal2 = _mm256_permute2f128_ps(input1, input2, 0x31); + + power = _mm256_hadd_ps(inputVal1, inputVal2); + + // Divide by the rbw + power = _mm256_mul_ps(power, invRBW); + + // Calculate the natural log power + power = logf4(power); + + // Convert to log10 and multiply by 10.0 + power = _mm256_mul_ps(power, magScalar); + + // Store the floating point results + _mm256_store_ps(destPtr, power); + + destPtr += 8; + } + + number = eighthPoints*8; +#endif /* LV_HAVE_LIB_SIMDMATH */ + // Calculate the FFT for any remaining points + for(; number < num_points; number++){ + // Calculate dBm + // 50 ohm load assumption + // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10) + // 75 ohm load assumption + // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15) + + const float real = *inputPtr++ * iNormalizationFactor; + const float imag = *inputPtr++ * iNormalizationFactor; + + *destPtr = 10.0*log10f((((real * real) + (imag * imag)) + 1e-20) * iRBW); + destPtr++; + } + +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> diff --git a/volk/kernels/volk/volk_32fc_s32fc_multiply_32fc.h b/volk/kernels/volk/volk_32fc_s32fc_multiply_32fc.h index 668a047609..474b982887 100644 --- a/volk/kernels/volk/volk_32fc_s32fc_multiply_32fc.h +++ b/volk/kernels/volk/volk_32fc_s32fc_multiply_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32fc_multiply_32fc_u_H #define INCLUDED_volk_32fc_s32fc_multiply_32fc_u_H @@ -6,6 +28,52 @@ #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies the two input complex vectors and stores their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be multiplied + \param bVector One of the vectors to be multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_s32fc_multiply_32fc_u_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t scalar, unsigned int num_points){ + unsigned int number = 0; + unsigned int i = 0; + const unsigned int quarterPoints = num_points / 4; + unsigned int isodd = num_points & 3; + __m256 x, yl, yh, z, tmp1, tmp2; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + + // Set up constant scalar vector + yl = _mm256_set1_ps(lv_creal(scalar)); + yh = _mm256_set1_ps(lv_cimag(scalar)); + + for(;number < quarterPoints; number++){ + x = _mm256_loadu_ps((float*)a); // Load the ar + ai, br + bi as ar,ai,br,bi + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + + _mm256_storeu_ps((float*)c,z); // Store the results back into the C container + + a += 4; + c += 4; + } + + for(i = num_points-isodd; i < num_points; i++) { + *c++ = (*a++) * scalar; + } + +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -93,6 +161,52 @@ static inline void volk_32fc_s32fc_multiply_32fc_generic(lv_32fc_t* cVector, con #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies the two input complex vectors and stores their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be multiplied + \param bVector One of the vectors to be multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_s32fc_multiply_32fc_a_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t scalar, unsigned int num_points){ + unsigned int number = 0; + unsigned int i = 0; + const unsigned int quarterPoints = num_points / 4; + unsigned int isodd = num_points & 3; + __m256 x, yl, yh, z, tmp1, tmp2; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + + // Set up constant scalar vector + yl = _mm256_set1_ps(lv_creal(scalar)); + yh = _mm256_set1_ps(lv_cimag(scalar)); + + for(;number < quarterPoints; number++){ + x = _mm256_load_ps((float*)a); // Load the ar + ai, br + bi as ar,ai,br,bi + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + + _mm256_store_ps((float*)c,z); // Store the results back into the C container + + a += 4; + c += 4; + } + + for(i = num_points-isodd; i < num_points; i++) { + *c++ = (*a++) * scalar; + } + +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -138,6 +252,43 @@ static inline void volk_32fc_s32fc_multiply_32fc_a_sse3(lv_32fc_t* cVector, cons } #endif /* LV_HAVE_SSE */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> + /*! + \brief Multiplies the two input complex vectors and stores their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be multiplied + \param bVector One of the vectors to be multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_s32fc_multiply_32fc_neon(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t scalar, unsigned int num_points){ + lv_32fc_t* cPtr = cVector; + const lv_32fc_t* aPtr = aVector; + unsigned int number = num_points; + unsigned int quarter_points = num_points / 4; + + float32x4x2_t a_val, scalar_val; + float32x4x2_t tmp_imag; + + scalar_val = vld2q_f32((const float*)&scalar); + for(number = 0; number < quarter_points; ++number) { + a_val = vld2q_f32((float*)aPtr); + tmp_imag.val[1] = vmulq_f32(a_val.val[1], scalar_val.val[0]); + tmp_imag.val[0] = vmulq_f32(a_val.val[0], scalar_val.val[0]); + + tmp_imag.val[1] = vmlaq_f32(tmp_imag.val[1], a_val.val[0], scalar_val.val[1]); + tmp_imag.val[0] = vmlaq_f32(tmp_imag.val[0], a_val.val[1], scalar_val.val[1]); + + vst2q_f32((float*)cVector, tmp_imag); + aPtr += 4; + cVector += 4; + } + + for(number = quarter_points*4; number < num_points; number++){ + *cPtr++ = *aPtr++ * scalar; + } +} +#endif /* LV_HAVE_NEON */ #ifdef LV_HAVE_GENERIC /*! @@ -171,8 +322,4 @@ static inline void volk_32fc_s32fc_multiply_32fc_a_generic(lv_32fc_t* cVector, c } #endif /* LV_HAVE_GENERIC */ - - - - #endif /* INCLUDED_volk_32fc_x2_multiply_32fc_a_H */ diff --git a/volk/kernels/volk/volk_32fc_s32fc_rotatorpuppet_32fc.h b/volk/kernels/volk/volk_32fc_s32fc_rotatorpuppet_32fc.h index c7b46e7e99..cbbc43624b 100644 --- a/volk/kernels/volk/volk_32fc_s32fc_rotatorpuppet_32fc.h +++ b/volk/kernels/volk/volk_32fc_s32fc_rotatorpuppet_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32fc_rotatorpuppet_32fc_a_H #define INCLUDED_volk_32fc_s32fc_rotatorpuppet_32fc_a_H diff --git a/volk/kernels/volk/volk_32fc_s32fc_x2_rotator_32fc.h b/volk/kernels/volk/volk_32fc_s32fc_x2_rotator_32fc.h index 0ed9d67cb5..06500784a1 100644 --- a/volk/kernels/volk/volk_32fc_s32fc_x2_rotator_32fc.h +++ b/volk/kernels/volk/volk_32fc_s32fc_x2_rotator_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_s32fc_rotator_32fc_a_H #define INCLUDED_volk_32fc_s32fc_rotator_32fc_a_H diff --git a/volk/kernels/volk/volk_32fc_x2_conjugate_dot_prod_32fc.h b/volk/kernels/volk/volk_32fc_x2_conjugate_dot_prod_32fc.h index e6ccf5c384..8964434bef 100644 --- a/volk/kernels/volk/volk_32fc_x2_conjugate_dot_prod_32fc.h +++ b/volk/kernels/volk/volk_32fc_x2_conjugate_dot_prod_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_x2_conjugate_dot_prod_32fc_u_H #define INCLUDED_volk_32fc_x2_conjugate_dot_prod_32fc_u_H @@ -142,10 +164,57 @@ static inline void volk_32fc_x2_conjugate_dot_prod_32fc_u_sse3(lv_32fc_t* result #endif /*LV_HAVE_SSE3*/ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +static inline void volk_32fc_x2_conjugate_dot_prod_32fc_neon(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_points) { + + unsigned int quarter_points = num_points / 4; + unsigned int number; + + lv_32fc_t* a_ptr = (lv_32fc_t*) taps; + lv_32fc_t* b_ptr = (lv_32fc_t*) input; + // for 2-lane vectors, 1st lane holds the real part, + // 2nd lane holds the imaginary part + float32x4x2_t a_val, b_val, accumulator; + float32x4x2_t tmp_imag; + accumulator.val[0] = vdupq_n_f32(0); + accumulator.val[1] = vdupq_n_f32(0); + + for(number = 0; number < quarter_points; ++number) { + a_val = vld2q_f32((float*)a_ptr); // a0r|a1r|a2r|a3r || a0i|a1i|a2i|a3i + b_val = vld2q_f32((float*)b_ptr); // b0r|b1r|b2r|b3r || b0i|b1i|b2i|b3i + __builtin_prefetch(a_ptr+8); + __builtin_prefetch(b_ptr+8); + + // do the first multiply + tmp_imag.val[1] = vmulq_f32(a_val.val[1], b_val.val[0]); + tmp_imag.val[0] = vmulq_f32(a_val.val[0], b_val.val[0]); + + // use multiply accumulate/subtract to get result + tmp_imag.val[1] = vmlsq_f32(tmp_imag.val[1], a_val.val[0], b_val.val[1]); + tmp_imag.val[0] = vmlaq_f32(tmp_imag.val[0], a_val.val[1], b_val.val[1]); + + accumulator.val[0] = vaddq_f32(accumulator.val[0], tmp_imag.val[0]); + accumulator.val[1] = vaddq_f32(accumulator.val[1], tmp_imag.val[1]); + + // increment pointers + a_ptr += 4; + b_ptr += 4; + } + lv_32fc_t accum_result[4]; + vst2q_f32((float*)accum_result, accumulator); + *result = accum_result[0] + accum_result[1] + accum_result[2] + accum_result[3]; -#endif /*INCLUDED_volk_32fc_x2_conjugate_dot_prod_32fc_u_H*/ + // tail case + for(number = quarter_points*4; number < num_points; ++number) { + *result += (*a_ptr++) * lv_conj(*b_ptr++); + } + *result = lv_conj(*result); +} +#endif /*LV_HAVE_NEON*/ +#endif /*INCLUDED_volk_32fc_x2_conjugate_dot_prod_32fc_u_H*/ #ifndef INCLUDED_volk_32fc_x2_conjugate_dot_prod_32fc_a_H #define INCLUDED_volk_32fc_x2_conjugate_dot_prod_32fc_a_H diff --git a/volk/kernels/volk/volk_32fc_x2_dot_prod_32fc.h b/volk/kernels/volk/volk_32fc_x2_dot_prod_32fc.h index 430b747ff2..c65d0984c5 100644 --- a/volk/kernels/volk/volk_32fc_x2_dot_prod_32fc.h +++ b/volk/kernels/volk/volk_32fc_x2_dot_prod_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_x2_dot_prod_32fc_u_H #define INCLUDED_volk_32fc_x2_dot_prod_32fc_u_H @@ -316,10 +338,66 @@ static inline void volk_32fc_x2_dot_prod_32fc_u_sse4_1(lv_32fc_t* result, const #endif /*LV_HAVE_SSE4_1*/ +#ifdef LV_HAVE_AVX + +#include <immintrin.h> + +static inline void volk_32fc_x2_dot_prod_32fc_u_avx(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_points) { + + unsigned int isodd = num_points & 3; + unsigned int i = 0; + lv_32fc_t dotProduct; + memset(&dotProduct, 0x0, 2*sizeof(float)); + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x, y, yl, yh, z, tmp1, tmp2, dotProdVal; + + const lv_32fc_t* a = input; + const lv_32fc_t* b = taps; + + dotProdVal = _mm256_setzero_ps(); + + for(;number < quarterPoints; number++){ + x = _mm256_loadu_ps((float*)a); // Load a,b,e,f as ar,ai,br,bi,er,ei,fr,fi + y = _mm256_loadu_ps((float*)b); // Load c,d,g,h as cr,ci,dr,di,gr,gi,hr,hi + + yl = _mm256_moveldup_ps(y); // Load yl with cr,cr,dr,dr,gr,gr,hr,hr + yh = _mm256_movehdup_ps(y); // Load yh with ci,ci,di,di,gi,gi,hi,hi + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr ... + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br,ei,er,fi,fr + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di ... + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + + dotProdVal = _mm256_add_ps(dotProdVal, z); // Add the complex multiplication results together + + a += 4; + b += 4; + } + + __VOLK_ATTR_ALIGNED(32) lv_32fc_t dotProductVector[4]; + + _mm256_storeu_ps((float*)dotProductVector,dotProdVal); // Store the results back into the dot product vector + + dotProduct += ( dotProductVector[0] + dotProductVector[1] + dotProductVector[2] + dotProductVector[3]); + + for(i = num_points-isodd; i < num_points; i++) { + dotProduct += input[i] * taps[i]; + } + + *result = dotProduct; +} + +#endif /*LV_HAVE_AVX*/ #endif /*INCLUDED_volk_32fc_x2_dot_prod_32fc_u_H*/ + #ifndef INCLUDED_volk_32fc_x2_dot_prod_32fc_a_H #define INCLUDED_volk_32fc_x2_dot_prod_32fc_a_H @@ -680,6 +758,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse3(lv_32fc_t* result, const lv #endif /*LV_HAVE_SSE3*/ + #ifdef LV_HAVE_SSE4_1 #include <smmintrin.h> @@ -817,7 +896,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_neon(lv_32fc_t* result, const lv_3 #endif /*LV_HAVE_NEON*/ #ifdef LV_HAVE_NEON - +#include <arm_neon.h> static inline void volk_32fc_x2_dot_prod_32fc_neon_opttests(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_points) { unsigned int quarter_points = num_points / 4; @@ -976,4 +1055,62 @@ static inline void volk_32fc_x2_dot_prod_32fc_neon_optfmaunroll(lv_32fc_t* resul #endif /*LV_HAVE_NEON*/ +#ifdef LV_HAVE_AVX + +#include <immintrin.h> + +static inline void volk_32fc_x2_dot_prod_32fc_a_avx(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_points) { + + unsigned int isodd = num_points & 3; + unsigned int i = 0; + lv_32fc_t dotProduct; + memset(&dotProduct, 0x0, 2*sizeof(float)); + + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x, y, yl, yh, z, tmp1, tmp2, dotProdVal; + + const lv_32fc_t* a = input; + const lv_32fc_t* b = taps; + + dotProdVal = _mm256_setzero_ps(); + + for(;number < quarterPoints; number++){ + + x = _mm256_load_ps((float*)a); // Load a,b,e,f as ar,ai,br,bi,er,ei,fr,fi + y = _mm256_load_ps((float*)b); // Load c,d,g,h as cr,ci,dr,di,gr,gi,hr,hi + + yl = _mm256_moveldup_ps(y); // Load yl with cr,cr,dr,dr,gr,gr,hr,hr + yh = _mm256_movehdup_ps(y); // Load yh with ci,ci,di,di,gi,gi,hi,hi + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr ... + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br,ei,er,fi,fr + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di ... + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + + dotProdVal = _mm256_add_ps(dotProdVal, z); // Add the complex multiplication results together + + a += 4; + b += 4; + } + + __VOLK_ATTR_ALIGNED(32) lv_32fc_t dotProductVector[4]; + + _mm256_store_ps((float*)dotProductVector,dotProdVal); // Store the results back into the dot product vector + + dotProduct += ( dotProductVector[0] + dotProductVector[1] + dotProductVector[2] + dotProductVector[3]); + + for(i = num_points-isodd; i < num_points; i++) { + dotProduct += input[i] * taps[i]; + } + + *result = dotProduct; +} + +#endif /*LV_HAVE_AVX*/ + #endif /*INCLUDED_volk_32fc_x2_dot_prod_32fc_a_H*/ diff --git a/volk/kernels/volk/volk_32fc_x2_multiply_32fc.h b/volk/kernels/volk/volk_32fc_x2_multiply_32fc.h index 7c723bcdb6..4575439e94 100644 --- a/volk/kernels/volk/volk_32fc_x2_multiply_32fc.h +++ b/volk/kernels/volk/volk_32fc_x2_multiply_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_x2_multiply_32fc_u_H #define INCLUDED_volk_32fc_x2_multiply_32fc_u_H @@ -6,6 +28,55 @@ #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies the two input complex vectors and stores their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be multiplied + \param bVector One of the vectors to be multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_x2_multiply_32fc_u_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t* bVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x, y, yl, yh, z, tmp1, tmp2; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + const lv_32fc_t* b = bVector; + + for(;number < quarterPoints; number++){ + + x = _mm256_loadu_ps((float*)a); // Load the ar + ai, br + bi ... as ar,ai,br,bi ... + y = _mm256_loadu_ps((float*)b); // Load the cr + ci, dr + di ... as cr,ci,dr,di ... + + yl = _mm256_moveldup_ps(y); // Load yl with cr,cr,dr,dr ... + yh = _mm256_movehdup_ps(y); // Load yh with ci,ci,di,di ... + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr ... + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br ... + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + + _mm256_storeu_ps((float*)c,z); // Store the results back into the C container + + a += 4; + b += 4; + c += 4; + } + + number = quarterPoints * 4; + + for(; number < num_points; number++) { + *c++ = (*a++) * (*b++); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -83,6 +154,55 @@ static inline void volk_32fc_x2_multiply_32fc_generic(lv_32fc_t* cVector, const #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies the two input complex vectors and stores their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be multiplied + \param bVector One of the vectors to be multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_x2_multiply_32fc_a_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t* bVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x, y, yl, yh, z, tmp1, tmp2; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + const lv_32fc_t* b = bVector; + + for(;number < quarterPoints; number++){ + + x = _mm256_load_ps((float*)a); // Load the ar + ai, br + bi ... as ar,ai,br,bi ... + y = _mm256_load_ps((float*)b); // Load the cr + ci, dr + di ... as cr,ci,dr,di ... + + yl = _mm256_moveldup_ps(y); // Load yl with cr,cr,dr,dr ... + yh = _mm256_movehdup_ps(y); // Load yh with ci,ci,di,di ... + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr ... + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br ... + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + + _mm256_store_ps((float*)c,z); // Store the results back into the C container + + a += 4; + b += 4; + c += 4; + } + + number = quarterPoints * 4; + + for(; number < num_points; number++) { + *c++ = (*a++) * (*b++); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32fc_x2_multiply_conjugate_32fc.h b/volk/kernels/volk/volk_32fc_x2_multiply_conjugate_32fc.h index dbc123ff25..c9b3bbc70b 100644 --- a/volk/kernels/volk/volk_32fc_x2_multiply_conjugate_32fc.h +++ b/volk/kernels/volk/volk_32fc_x2_multiply_conjugate_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_x2_multiply_conjugate_32fc_u_H #define INCLUDED_volk_32fc_x2_multiply_conjugate_32fc_u_H @@ -6,6 +28,59 @@ #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies vector a by the conjugate of vector b and stores the results in the third vector + \param cVector The vector where the results will be stored + \param aVector First vector to be multiplied + \param bVector Second vector that is conjugated before being multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_x2_multiply_conjugate_32fc_u_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t* bVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x, y, yl, yh, z, tmp1, tmp2; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + const lv_32fc_t* b = bVector; + + __m256 conjugator = _mm256_setr_ps(0, -0.f, 0, -0.f, 0, -0.f, 0, -0.f); + + for(;number < quarterPoints; number++){ + + x = _mm256_loadu_ps((float*)a); // Load the ar + ai, br + bi ... as ar,ai,br,bi ... + y = _mm256_loadu_ps((float*)b); // Load the cr + ci, dr + di ... as cr,ci,dr,di ... + + y = _mm256_xor_ps(y, conjugator); // conjugate y + + yl = _mm256_moveldup_ps(y); // Load yl with cr,cr,dr,dr ... + yh = _mm256_movehdup_ps(y); // Load yh with ci,ci,di,di ... + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr ... + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br ... + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di ... + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di ... + + _mm256_storeu_ps((float*)c,z); // Store the results back into the C container + + a += 4; + b += 4; + c += 4; + } + + number = quarterPoints * 4; + + for(; number < num_points; number++) { + *c++ = (*a++) * lv_conj(*b++); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! @@ -87,6 +162,59 @@ static inline void volk_32fc_x2_multiply_conjugate_32fc_generic(lv_32fc_t* cVect #include <volk/volk_complex.h> #include <float.h> +#ifdef LV_HAVE_AVX +#include <immintrin.h> + /*! + \brief Multiplies vector a by the conjugate of vector b and stores the results in the third vector + \param cVector The vector where the results will be stored + \param aVector First vector to be multiplied + \param bVector Second vector that is conjugated before being multiplied + \param num_points The number of complex values in aVector and bVector to be multiplied together and stored into cVector + */ +static inline void volk_32fc_x2_multiply_conjugate_32fc_a_avx(lv_32fc_t* cVector, const lv_32fc_t* aVector, const lv_32fc_t* bVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + __m256 x, y, yl, yh, z, tmp1, tmp2; + lv_32fc_t* c = cVector; + const lv_32fc_t* a = aVector; + const lv_32fc_t* b = bVector; + + __m256 conjugator = _mm256_setr_ps(0, -0.f, 0, -0.f, 0, -0.f, 0, -0.f); + + for(;number < quarterPoints; number++){ + + x = _mm256_load_ps((float*)a); // Load the ar + ai, br + bi ... as ar,ai,br,bi ... + y = _mm256_load_ps((float*)b); // Load the cr + ci, dr + di ... as cr,ci,dr,di ... + + y = _mm256_xor_ps(y, conjugator); // conjugate y + + yl = _mm256_moveldup_ps(y); // Load yl with cr,cr,dr,dr ... + yh = _mm256_movehdup_ps(y); // Load yh with ci,ci,di,di ... + + tmp1 = _mm256_mul_ps(x,yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr ... + + x = _mm256_shuffle_ps(x,x,0xB1); // Re-arrange x to be ai,ar,bi,br ... + + tmp2 = _mm256_mul_ps(x,yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di ... + + z = _mm256_addsub_ps(tmp1,tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di ... + + _mm256_store_ps((float*)c,z); // Store the results back into the C container + + a += 4; + b += 4; + c += 4; + } + + number = quarterPoints * 4; + + for(; number < num_points; number++) { + *c++ = (*a++) * lv_conj(*b++); + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_SSE3 #include <pmmintrin.h> /*! diff --git a/volk/kernels/volk/volk_32fc_x2_s32f_square_dist_scalar_mult_32f.h b/volk/kernels/volk/volk_32fc_x2_s32f_square_dist_scalar_mult_32f.h index cb2e945015..a25a6866b7 100644 --- a/volk/kernels/volk/volk_32fc_x2_s32f_square_dist_scalar_mult_32f.h +++ b/volk/kernels/volk/volk_32fc_x2_s32f_square_dist_scalar_mult_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_x2_s32f_square_dist_scalar_mult_32f_a_H #define INCLUDED_volk_32fc_x2_s32f_square_dist_scalar_mult_32f_a_H diff --git a/volk/kernels/volk/volk_32fc_x2_square_dist_32f.h b/volk/kernels/volk/volk_32fc_x2_square_dist_32f.h index 56b3d5c230..2984beaa17 100644 --- a/volk/kernels/volk/volk_32fc_x2_square_dist_32f.h +++ b/volk/kernels/volk/volk_32fc_x2_square_dist_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32fc_x2_square_dist_32f_a_H #define INCLUDED_volk_32fc_x2_square_dist_32f_a_H diff --git a/volk/kernels/volk/volk_32i_s32f_convert_32f.h b/volk/kernels/volk/volk_32i_s32f_convert_32f.h index 7a09883453..dd965bc9b2 100644 --- a/volk/kernels/volk/volk_32i_s32f_convert_32f.h +++ b/volk/kernels/volk/volk_32i_s32f_convert_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32i_s32f_convert_32f_u_H #define INCLUDED_volk_32i_s32f_convert_32f_u_H diff --git a/volk/kernels/volk/volk_32i_x2_and_32i.h b/volk/kernels/volk/volk_32i_x2_and_32i.h index 54ecb79812..c138540e69 100644 --- a/volk/kernels/volk/volk_32i_x2_and_32i.h +++ b/volk/kernels/volk/volk_32i_x2_and_32i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32i_x2_and_32i_a_H #define INCLUDED_volk_32i_x2_and_32i_a_H @@ -43,6 +65,40 @@ static inline void volk_32i_x2_and_32i_a_sse(int32_t* cVector, const int32_t* aV } #endif /* LV_HAVE_SSE */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Ands the two input vectors and store their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors + \param bVector One of the vectors + \param num_points The number of values in aVector and bVector to be anded together and stored into cVector +*/ +static inline void volk_32i_x2_and_32i_neon(int32_t* cVector, const int32_t* aVector, const int32_t* bVector, unsigned int num_points){ + int32_t* cPtr = cVector; + const int32_t* aPtr = aVector; + const int32_t* bPtr= bVector; + unsigned int number = 0; + unsigned int quarter_points = num_points / 4; + + int32x4_t a_val, b_val, c_val; + + for(number = 0; number < quarter_points; number++){ + a_val = vld1q_s32(aPtr); + b_val = vld1q_s32(bPtr); + c_val = vandq_s32(a_val, b_val); + vst1q_s32(cPtr, c_val); + aPtr += 4; + bPtr += 4; + cPtr += 4; + } + + for(number = quarter_points * 4; number < num_points; number++){ + *cPtr++ = (*aPtr++) & (*bPtr++); + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Ands the two input vectors and store their results in the third vector diff --git a/volk/kernels/volk/volk_32i_x2_or_32i.h b/volk/kernels/volk/volk_32i_x2_or_32i.h index acadd5a57f..544a71c67c 100644 --- a/volk/kernels/volk/volk_32i_x2_or_32i.h +++ b/volk/kernels/volk/volk_32i_x2_or_32i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32i_x2_or_32i_a_H #define INCLUDED_volk_32i_x2_or_32i_a_H @@ -43,6 +65,40 @@ static inline void volk_32i_x2_or_32i_a_sse(int32_t* cVector, const int32_t* aVe } #endif /* LV_HAVE_SSE */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Ands the two input vectors and store their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors + \param bVector One of the vectors + \param num_points The number of values in aVector and bVector to be anded together and stored into cVector +*/ +static inline void volk_32i_x2_or_32i_neon(int32_t* cVector, const int32_t* aVector, const int32_t* bVector, unsigned int num_points){ + int32_t* cPtr = cVector; + const int32_t* aPtr = aVector; + const int32_t* bPtr= bVector; + unsigned int number = 0; + unsigned int quarter_points = num_points / 4; + + int32x4_t a_val, b_val, c_val; + + for(number = 0; number < quarter_points; number++){ + a_val = vld1q_s32(aPtr); + b_val = vld1q_s32(bPtr); + c_val = vorrq_s32(a_val, b_val); + vst1q_s32(cPtr, c_val); + aPtr += 4; + bPtr += 4; + cPtr += 4; + } + + for(number = quarter_points * 4; number < num_points; number++){ + *cPtr++ = (*aPtr++) | (*bPtr++); + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Ors the two input vectors and store their results in the third vector diff --git a/volk/kernels/volk/volk_32u_byteswap.h b/volk/kernels/volk/volk_32u_byteswap.h index 8f6e3ad7b5..0194efc12c 100644 --- a/volk/kernels/volk/volk_32u_byteswap.h +++ b/volk/kernels/volk/volk_32u_byteswap.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32u_byteswap_u_H #define INCLUDED_volk_32u_byteswap_u_H @@ -51,6 +73,59 @@ static inline void volk_32u_byteswap_u_sse2(uint32_t* intsToSwap, unsigned int n } #endif /* LV_HAVE_SSE2 */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Byteswaps (in-place) an aligned vector of int32_t's. + \param intsToSwap The vector of data to byte swap + \param numDataPoints The number of data points +*/ +static inline void volk_32u_byteswap_neon(uint32_t* intsToSwap, unsigned int num_points){ + uint32_t* inputPtr = intsToSwap; + unsigned int number = 0; + unsigned int n8points = num_points / 8; + + uint8x8x4_t input_table; + uint8x8_t int_lookup01, int_lookup23, int_lookup45, int_lookup67; + uint8x8_t swapped_int01, swapped_int23, swapped_int45, swapped_int67; + + /* these magic numbers are used as byte-indeces in the LUT. + they are pre-computed to save time. A simple C program + can calculate them; for example for lookup01: + uint8_t chars[8] = {24, 16, 8, 0, 25, 17, 9, 1}; + for(ii=0; ii < 8; ++ii) { + index += ((uint64_t)(*(chars+ii))) << (ii*8); + } + */ + int_lookup01 = vcreate_u8(74609667900706840); + int_lookup23 = vcreate_u8(219290013576860186); + int_lookup45 = vcreate_u8(363970359253013532); + int_lookup67 = vcreate_u8(508650704929166878); + + for(number = 0; number < n8points; ++number){ + input_table = vld4_u8((uint8_t*) inputPtr); + swapped_int01 = vtbl4_u8(input_table, int_lookup01); + swapped_int23 = vtbl4_u8(input_table, int_lookup23); + swapped_int45 = vtbl4_u8(input_table, int_lookup45); + swapped_int67 = vtbl4_u8(input_table, int_lookup67); + vst1_u8((uint8_t*) inputPtr, swapped_int01); + vst1_u8((uint8_t*) (inputPtr+2), swapped_int23); + vst1_u8((uint8_t*) (inputPtr+4), swapped_int45); + vst1_u8((uint8_t*) (inputPtr+6), swapped_int67); + + inputPtr += 8; + } + + for(number = n8points * 8; number < num_points; ++number){ + uint32_t output = *inputPtr; + output = (((output >> 24) & 0xff) | ((output >> 8) & 0x0000ff00) | ((output << 8) & 0x00ff0000) | ((output << 24) & 0xff000000)); + + *inputPtr = output; + inputPtr++; + } +} +#endif /* LV_HAVE_NEON */ + #ifdef LV_HAVE_GENERIC /*! \brief Byteswaps (in-place) an aligned vector of int32_t's. @@ -72,8 +147,6 @@ static inline void volk_32u_byteswap_generic(uint32_t* intsToSwap, unsigned int #endif /* LV_HAVE_GENERIC */ - - #endif /* INCLUDED_volk_32u_byteswap_u_H */ #ifndef INCLUDED_volk_32u_byteswap_a_H #define INCLUDED_volk_32u_byteswap_a_H diff --git a/volk/kernels/volk/volk_32u_byteswappuppet_32u.h b/volk/kernels/volk/volk_32u_byteswappuppet_32u.h new file mode 100644 index 0000000000..bf7055e241 --- /dev/null +++ b/volk/kernels/volk/volk_32u_byteswappuppet_32u.h @@ -0,0 +1,45 @@ +#ifndef INCLUDED_volk_32u_byteswappuppet_32u_H +#define INCLUDED_volk_32u_byteswappuppet_32u_H + + +#include <stdint.h> +#include <volk/volk_32u_byteswap.h> + +#ifdef LV_HAVE_GENERIC +static inline void volk_32u_byteswappuppet_32u_generic(uint32_t*output, uint32_t* intsToSwap, unsigned int num_points){ + + volk_32u_byteswap_generic((uint32_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint32_t)); + +} +#endif + +#ifdef LV_HAVE_NEON +static inline void volk_32u_byteswappuppet_32u_neon(uint32_t*output, uint32_t* intsToSwap, unsigned int num_points){ + + volk_32u_byteswap_neon((uint32_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint32_t)); + +} +#endif + +#ifdef LV_HAVE_SSE2 +static inline void volk_32u_byteswappuppet_32u_u_sse2(uint32_t *output, uint32_t* intsToSwap, unsigned int num_points){ + + volk_32u_byteswap_u_sse2((uint32_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint32_t)); + +} +#endif + +#ifdef LV_HAVE_SSE2 +static inline void volk_32u_byteswappuppet_32u_a_sse2(uint32_t* output, uint32_t* intsToSwap, unsigned int num_points){ + + volk_32u_byteswap_a_sse2((uint32_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint32_t)); + +} +#endif + + +#endif diff --git a/volk/kernels/volk/volk_32u_popcnt.h b/volk/kernels/volk/volk_32u_popcnt.h index 9783569729..8d613754df 100644 --- a/volk/kernels/volk/volk_32u_popcnt.h +++ b/volk/kernels/volk/volk_32u_popcnt.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_VOLK_32u_POPCNT_A16_H #define INCLUDED_VOLK_32u_POPCNT_A16_H diff --git a/volk/kernels/volk/volk_32u_popcntpuppet_32u.h b/volk/kernels/volk/volk_32u_popcntpuppet_32u.h new file mode 100644 index 0000000000..056983e817 --- /dev/null +++ b/volk/kernels/volk/volk_32u_popcntpuppet_32u.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_32u_popcntpuppet_32u_H +#define INCLUDED_volk_32u_popcntpuppet_32u_H + +#include <stdint.h> +#include <volk/volk_32u_popcnt.h> + +#ifdef LV_HAVE_GENERIC +static inline void volk_32u_popcntpuppet_32u_generic(uint32_t* outVector, const uint32_t* inVector, unsigned int num_points){ + unsigned int ii; + for(ii=0; ii < num_points; ++ii) { + volk_32u_popcnt_generic(outVector+ii, *(inVector+ii) ); + } +} +#endif /* LV_HAVE_GENERIC */ + +#ifdef LV_HAVE_SSE_4_2 +static inline void volk_32u_popcntpuppet_32u_a_sse4_2(uint32_t* outVector, const uint32_t* inVector, unsigned int num_points){ + unsigned int ii; + for(ii=0; ii < num_points; ++ii) { + volk_32u_popcnt_a_sse4_2(outVector+ii, *(inVector+ii) ); + } +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32fc_s32fc_rotatorpuppet_32fc_a_H */ diff --git a/volk/kernels/volk/volk_64f_convert_32f.h b/volk/kernels/volk/volk_64f_convert_32f.h index c27526ffaf..39a7ae8fd0 100644 --- a/volk/kernels/volk/volk_64f_convert_32f.h +++ b/volk/kernels/volk/volk_64f_convert_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_64f_convert_32f_u_H #define INCLUDED_volk_64f_convert_32f_u_H diff --git a/volk/kernels/volk/volk_64f_x2_max_64f.h b/volk/kernels/volk/volk_64f_x2_max_64f.h index f9a04c2c40..7bf09e8514 100644 --- a/volk/kernels/volk/volk_64f_x2_max_64f.h +++ b/volk/kernels/volk/volk_64f_x2_max_64f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_64f_x2_max_64f_a_H #define INCLUDED_volk_64f_x2_max_64f_a_H diff --git a/volk/kernels/volk/volk_64f_x2_min_64f.h b/volk/kernels/volk/volk_64f_x2_min_64f.h index c77ca87fbd..8d8b377503 100644 --- a/volk/kernels/volk/volk_64f_x2_min_64f.h +++ b/volk/kernels/volk/volk_64f_x2_min_64f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_64f_x2_min_64f_a_H #define INCLUDED_volk_64f_x2_min_64f_a_H diff --git a/volk/kernels/volk/volk_64u_byteswap.h b/volk/kernels/volk/volk_64u_byteswap.h index e05daf6d5c..dce883278d 100644 --- a/volk/kernels/volk/volk_64u_byteswap.h +++ b/volk/kernels/volk/volk_64u_byteswap.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_64u_byteswap_u_H #define INCLUDED_volk_64u_byteswap_u_H @@ -82,7 +104,62 @@ static inline void volk_64u_byteswap_generic(uint64_t* intsToSwap, unsigned int } #endif /* LV_HAVE_GENERIC */ +#ifdef LV_HAVE_NEON +#include <arm_neon.h> +/*! + \brief Byteswaps (in-place) a vector of int64_t's. + \param intsToSwap The vector of data to byte swap + \param numDataPoints The number of data points +*/ +static inline void volk_64u_byteswap_neon(uint64_t* intsToSwap, unsigned int num_points){ + uint32_t* inputPtr = (uint32_t*)intsToSwap; + unsigned int number = 0; + unsigned int n8points = num_points / 4; + + uint8x8x4_t input_table; + uint8x8_t int_lookup01, int_lookup23, int_lookup45, int_lookup67; + uint8x8_t swapped_int01, swapped_int23, swapped_int45, swapped_int67; + + /* these magic numbers are used as byte-indeces in the LUT. + they are pre-computed to save time. A simple C program + can calculate them; for example for lookup01: + uint8_t chars[8] = {24, 16, 8, 0, 25, 17, 9, 1}; + for(ii=0; ii < 8; ++ii) { + index += ((uint64_t)(*(chars+ii))) << (ii*8); + } + */ + int_lookup01 = vcreate_u8(2269495096316185); + int_lookup23 = vcreate_u8(146949840772469531); + int_lookup45 = vcreate_u8(291630186448622877); + int_lookup67 = vcreate_u8(436310532124776223); + + for(number = 0; number < n8points; ++number){ + input_table = vld4_u8((uint8_t*) inputPtr); + swapped_int01 = vtbl4_u8(input_table, int_lookup01); + swapped_int23 = vtbl4_u8(input_table, int_lookup23); + swapped_int45 = vtbl4_u8(input_table, int_lookup45); + swapped_int67 = vtbl4_u8(input_table, int_lookup67); + vst1_u8((uint8_t*) inputPtr, swapped_int01); + vst1_u8((uint8_t*) (inputPtr+2), swapped_int23); + vst1_u8((uint8_t*) (inputPtr+4), swapped_int45); + vst1_u8((uint8_t*) (inputPtr+6), swapped_int67); + + inputPtr += 4; + } + for(number = n8points * 4; number < num_points; ++number){ + uint32_t output1 = *inputPtr; + uint32_t output2 = inputPtr[1]; + + output1 = (((output1 >> 24) & 0xff) | ((output1 >> 8) & 0x0000ff00) | ((output1 << 8) & 0x00ff0000) | ((output1 << 24) & 0xff000000)); + output2 = (((output2 >> 24) & 0xff) | ((output2 >> 8) & 0x0000ff00) | ((output2 << 8) & 0x00ff0000) | ((output2 << 24) & 0xff000000)); + + *inputPtr++ = output2; + *inputPtr++ = output1; + } + +} +#endif /* LV_HAVE_NEON */ #endif /* INCLUDED_volk_64u_byteswap_u_H */ diff --git a/volk/kernels/volk/volk_64u_byteswappuppet_64u.h b/volk/kernels/volk/volk_64u_byteswappuppet_64u.h new file mode 100644 index 0000000000..ac5b16e212 --- /dev/null +++ b/volk/kernels/volk/volk_64u_byteswappuppet_64u.h @@ -0,0 +1,45 @@ +#ifndef INCLUDED_volk_64u_byteswappuppet_64u_H +#define INCLUDED_volk_64u_byteswappuppet_64u_H + + +#include <stdint.h> +#include <volk/volk_64u_byteswap.h> + +#ifdef LV_HAVE_GENERIC +static inline void volk_64u_byteswappuppet_64u_generic(uint64_t*output, uint64_t* intsToSwap, unsigned int num_points){ + + volk_64u_byteswap_generic((uint64_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint64_t)); + +} +#endif + +#ifdef LV_HAVE_NEON +static inline void volk_64u_byteswappuppet_64u_neon(uint64_t*output, uint64_t* intsToSwap, unsigned int num_points){ + + volk_64u_byteswap_neon((uint64_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint64_t)); + +} +#endif + +#ifdef LV_HAVE_SSE2 +static inline void volk_64u_byteswappuppet_64u_u_sse2(uint64_t* output, uint64_t* intsToSwap, unsigned int num_points){ + + volk_64u_byteswap_u_sse2((uint64_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint64_t)); + +} +#endif + +#ifdef LV_HAVE_SSE2 +static inline void volk_64u_byteswappuppet_64u_a_sse2(uint64_t* output, uint64_t* intsToSwap, unsigned int num_points){ + + volk_64u_byteswap_a_sse2((uint64_t*)intsToSwap, num_points); + memcpy((void*)output, (void*)intsToSwap, num_points * sizeof(uint64_t)); + +} +#endif + + +#endif diff --git a/volk/kernels/volk/volk_64u_popcnt.h b/volk/kernels/volk/volk_64u_popcnt.h index 466cfa5dad..0ec72e3404 100644 --- a/volk/kernels/volk/volk_64u_popcnt.h +++ b/volk/kernels/volk/volk_64u_popcnt.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_64u_popcnt_a_H #define INCLUDED_volk_64u_popcnt_a_H @@ -49,4 +71,24 @@ static inline void volk_64u_popcnt_a_sse4_2(uint64_t* ret, const uint64_t value) #endif /*LV_HAVE_SSE4_2*/ +#if LV_HAVE_NEON +#include <arm_neon.h> +static inline void volk_64u_popcnt_neon(uint64_t* ret, const uint64_t value) { + uint8x8_t input_val, count8x8_val; + uint16x4_t count16x4_val; + uint32x2_t count32x2_val; + uint64x1_t count64x1_val; + + input_val = vld1_u8((unsigned char *) &value); + count8x8_val = vcnt_u8(input_val); + count16x4_val = vpaddl_u8(count8x8_val); + count32x2_val = vpaddl_u16(count16x4_val); + count64x1_val = vpaddl_u32(count32x2_val); + vst1_u64(ret, count64x1_val); + + //*ret = _mm_popcnt_u64(value); + +} +#endif /*LV_HAVE_NEON*/ + #endif /*INCLUDED_volk_64u_popcnt_a_H*/ diff --git a/volk/kernels/volk/volk_64u_popcntpuppet_64u.h b/volk/kernels/volk/volk_64u_popcntpuppet_64u.h new file mode 100644 index 0000000000..3903e0d561 --- /dev/null +++ b/volk/kernels/volk/volk_64u_popcntpuppet_64u.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_64u_popcntpuppet_64u_H +#define INCLUDED_volk_64u_popcntpuppet_64u_H + +#include <stdint.h> +#include <volk/volk_64u_popcnt.h> + +#ifdef LV_HAVE_GENERIC +static inline void volk_64u_popcntpuppet_64u_generic(uint64_t* outVector, const uint64_t* inVector, unsigned int num_points){ + unsigned int ii; + for(ii=0; ii < num_points; ++ii) { + volk_64u_popcnt_generic(outVector+ii, num_points ); + + } +} +#endif /* LV_HAVE_GENERIC */ + +#ifdef LV_HAVE_NEON +static inline void volk_64u_popcntpuppet_64u_neon(uint64_t* outVector, const uint64_t* inVector, unsigned int num_points){ + unsigned int ii; + for(ii=0; ii < num_points; ++ii) { + volk_64u_popcnt_neon(outVector+ii, num_points ); + } +} +#endif /* LV_HAVE_NEON */ + +#endif /* INCLUDED_volk_32fc_s32fc_rotatorpuppet_32fc_a_H */ diff --git a/volk/kernels/volk/volk_8i_convert_16i.h b/volk/kernels/volk/volk_8i_convert_16i.h index 9776dfdc66..549ba4e388 100644 --- a/volk/kernels/volk/volk_8i_convert_16i.h +++ b/volk/kernels/volk/volk_8i_convert_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8i_convert_16i_u_H #define INCLUDED_volk_8i_convert_16i_u_H diff --git a/volk/kernels/volk/volk_8i_s32f_convert_32f.h b/volk/kernels/volk/volk_8i_s32f_convert_32f.h index bd7ff82d9a..5e959c8692 100644 --- a/volk/kernels/volk/volk_8i_s32f_convert_32f.h +++ b/volk/kernels/volk/volk_8i_s32f_convert_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8i_s32f_convert_32f_u_H #define INCLUDED_volk_8i_s32f_convert_32f_u_H diff --git a/volk/kernels/volk/volk_8ic_deinterleave_16i_x2.h b/volk/kernels/volk/volk_8ic_deinterleave_16i_x2.h index b59d22d186..818d309013 100644 --- a/volk/kernels/volk/volk_8ic_deinterleave_16i_x2.h +++ b/volk/kernels/volk/volk_8ic_deinterleave_16i_x2.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8ic_deinterleave_16i_x2_a_H #define INCLUDED_volk_8ic_deinterleave_16i_x2_a_H @@ -13,30 +35,31 @@ \param qBuffer The Q buffer output data \param num_points The number of complex data values to be deinterleaved */ + static inline void volk_8ic_deinterleave_16i_x2_a_sse4_1(int16_t* iBuffer, int16_t* qBuffer, const lv_8sc_t* complexVector, unsigned int num_points){ unsigned int number = 0; const int8_t* complexVectorPtr = (int8_t*)complexVector; int16_t* iBufferPtr = iBuffer; int16_t* qBufferPtr = qBuffer; - __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0); + __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0); // set 16 byte values __m128i qMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 13, 11, 9, 7, 5, 3, 1); __m128i complexVal, iOutputVal, qOutputVal; unsigned int eighthPoints = num_points / 8; for(number = 0; number < eighthPoints; number++){ - complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16; + complexVal = _mm_load_si128((__m128i*)complexVectorPtr); complexVectorPtr += 16; // aligned load - iOutputVal = _mm_shuffle_epi8(complexVal, iMoveMask); + iOutputVal = _mm_shuffle_epi8(complexVal, iMoveMask); // shuffle 16 bytes of 128bit complexVal qOutputVal = _mm_shuffle_epi8(complexVal, qMoveMask); - iOutputVal = _mm_cvtepi8_epi16(iOutputVal); - iOutputVal = _mm_slli_epi16(iOutputVal, 8); + iOutputVal = _mm_cvtepi8_epi16(iOutputVal); // fills 2-byte sign extended versions of lower 8 bytes of input to output + iOutputVal = _mm_slli_epi16(iOutputVal, 8); // shift in left by 8 bits, each of the 8 16-bit integers, shift in with zeros qOutputVal = _mm_cvtepi8_epi16(qOutputVal); qOutputVal = _mm_slli_epi16(qOutputVal, 8); - _mm_store_si128((__m128i*)iBufferPtr, iOutputVal); + _mm_store_si128((__m128i*)iBufferPtr, iOutputVal); // aligned store _mm_store_si128((__m128i*)qBufferPtr, qOutputVal); iBufferPtr += 8; @@ -45,12 +68,78 @@ static inline void volk_8ic_deinterleave_16i_x2_a_sse4_1(int16_t* iBuffer, int16 number = eighthPoints * 8; for(; number < num_points; number++){ - *iBufferPtr++ = ((int16_t)*complexVectorPtr++) * 256; + *iBufferPtr++ = ((int16_t)*complexVectorPtr++) * 256; // load 8 bit Complexvector into 16 bit, shift left by 8 bits and store *qBufferPtr++ = ((int16_t)*complexVectorPtr++) * 256; } } #endif /* LV_HAVE_SSE4_1 */ +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the complex 8 bit vector into I & Q 16 bit vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_8ic_deinterleave_16i_x2_a_avx(int16_t* iBuffer, int16_t* qBuffer, const lv_8sc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const int8_t* complexVectorPtr = (int8_t*)complexVector; + int16_t* iBufferPtr = iBuffer; + int16_t* qBufferPtr = qBuffer; + __m128i iMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0); // set 16 byte values + __m128i qMoveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 15, 13, 11, 9, 7, 5, 3, 1); + __m256i complexVal, iOutputVal, qOutputVal; + __m128i complexVal1, complexVal0; + __m128i iOutputVal1, iOutputVal0, qOutputVal1, qOutputVal0; + + unsigned int sixteenthPoints = num_points / 16; + + for(number = 0; number < sixteenthPoints; number++){ + complexVal = _mm256_load_si256((__m256i*)complexVectorPtr); complexVectorPtr += 32; // aligned load + + // Extract from complexVal to iOutputVal and qOutputVal + complexVal1 = _mm256_extractf128_si256(complexVal, 1); + complexVal0 = _mm256_extractf128_si256(complexVal, 0); + + iOutputVal1 = _mm_shuffle_epi8(complexVal1, iMoveMask); // shuffle 16 bytes of 128bit complexVal + iOutputVal0 = _mm_shuffle_epi8(complexVal0, iMoveMask); + qOutputVal1 = _mm_shuffle_epi8(complexVal1, qMoveMask); + qOutputVal0 = _mm_shuffle_epi8(complexVal0, qMoveMask); + + iOutputVal1 = _mm_cvtepi8_epi16(iOutputVal1); // fills 2-byte sign extended versions of lower 8 bytes of input to output + iOutputVal1 = _mm_slli_epi16(iOutputVal1, 8); // shift in left by 8 bits, each of the 8 16-bit integers, shift in with zeros + iOutputVal0 = _mm_cvtepi8_epi16(iOutputVal0); + iOutputVal0 = _mm_slli_epi16(iOutputVal0, 8); + + qOutputVal1 = _mm_cvtepi8_epi16(qOutputVal1); + qOutputVal1 = _mm_slli_epi16(qOutputVal1, 8); + qOutputVal0 = _mm_cvtepi8_epi16(qOutputVal0); + qOutputVal0 = _mm_slli_epi16(qOutputVal0, 8); + + // Pack iOutputVal0,1 to iOutputVal + __m256i dummy = _mm256_setzero_si256(); + iOutputVal = _mm256_insertf128_si256(dummy, iOutputVal0, 0); + iOutputVal = _mm256_insertf128_si256(iOutputVal, iOutputVal1, 1); + qOutputVal = _mm256_insertf128_si256(dummy, qOutputVal0, 0); + qOutputVal = _mm256_insertf128_si256(qOutputVal, qOutputVal1, 1); + + _mm256_store_si256((__m256i*)iBufferPtr, iOutputVal); // aligned store + _mm256_store_si256((__m256i*)qBufferPtr, qOutputVal); + + iBufferPtr += 16; + qBufferPtr += 16; + } + + number = sixteenthPoints * 16; + for(; number < num_points; number++){ + *iBufferPtr++ = ((int16_t)*complexVectorPtr++) * 256; // load 8 bit Complexvector into 16 bit, shift left by 8 bits and store + *qBufferPtr++ = ((int16_t)*complexVectorPtr++) * 256; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_GENERIC /*! \brief Deinterleaves the complex 8 bit vector into I & Q 16 bit vector data diff --git a/volk/kernels/volk/volk_8ic_deinterleave_real_16i.h b/volk/kernels/volk/volk_8ic_deinterleave_real_16i.h index 82cedb2bb7..c22f828a88 100644 --- a/volk/kernels/volk/volk_8ic_deinterleave_real_16i.h +++ b/volk/kernels/volk/volk_8ic_deinterleave_real_16i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8ic_deinterleave_real_16i_a_H #define INCLUDED_volk_8ic_deinterleave_real_16i_a_H @@ -41,6 +63,54 @@ static inline void volk_8ic_deinterleave_real_16i_a_sse4_1(int16_t* iBuffer, con } #endif /* LV_HAVE_SSE4_1 */ +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the complex 8 bit vector into I 16 bit vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_8ic_deinterleave_real_16i_a_avx(int16_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const int8_t* complexVectorPtr = (int8_t*)complexVector; + int16_t* iBufferPtr = iBuffer; + __m128i moveMask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0); + __m256i complexVal, outputVal; + __m128i complexVal1, complexVal0, outputVal1, outputVal0; + + unsigned int sixteenthPoints = num_points / 16; + + for(number = 0; number < sixteenthPoints; number++){ + complexVal = _mm256_load_si256((__m256i*)complexVectorPtr); complexVectorPtr += 32; + + complexVal1 = _mm256_extractf128_si256(complexVal, 1); + complexVal0 = _mm256_extractf128_si256(complexVal, 0); + + outputVal1 = _mm_shuffle_epi8(complexVal1, moveMask); + outputVal0 = _mm_shuffle_epi8(complexVal0, moveMask); + + outputVal1 = _mm_cvtepi8_epi16(outputVal1); + outputVal1 = _mm_slli_epi16(outputVal1, 7); + outputVal0 = _mm_cvtepi8_epi16(outputVal0); + outputVal0 = _mm_slli_epi16(outputVal0, 7); + + __m256i dummy = _mm256_setzero_si256(); + outputVal = _mm256_insertf128_si256(dummy, outputVal0, 0); + outputVal = _mm256_insertf128_si256(outputVal, outputVal1, 1); + _mm256_store_si256((__m256i*)iBufferPtr, outputVal); + + iBufferPtr += 16; + } + + number = sixteenthPoints * 16; + for(; number < num_points; number++){ + *iBufferPtr++ = ((int16_t)*complexVectorPtr++) * 128; + complexVectorPtr++; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_GENERIC /*! diff --git a/volk/kernels/volk/volk_8ic_deinterleave_real_8i.h b/volk/kernels/volk/volk_8ic_deinterleave_real_8i.h index 427c9abf55..e333306fac 100644 --- a/volk/kernels/volk/volk_8ic_deinterleave_real_8i.h +++ b/volk/kernels/volk/volk_8ic_deinterleave_real_8i.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_VOLK_8sc_DEINTERLEAVE_REAL_8s_ALIGNED8_H #define INCLUDED_VOLK_8sc_DEINTERLEAVE_REAL_8s_ALIGNED8_H @@ -43,6 +65,64 @@ static inline void volk_8ic_deinterleave_real_8i_a_ssse3(int8_t* iBuffer, const } #endif /* LV_HAVE_SSSE3 */ +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! + \brief Deinterleaves the complex 8 bit vector into I vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ + +static inline void volk_8ic_deinterleave_real_8i_a_avx(int8_t* iBuffer, const lv_8sc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const int8_t* complexVectorPtr = (int8_t*)complexVector; + int8_t* iBufferPtr = iBuffer; + __m128i moveMaskL = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 14, 12, 10, 8, 6, 4, 2, 0); + __m128i moveMaskH = _mm_set_epi8(14, 12, 10, 8, 6, 4, 2, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); + __m256i complexVal1, complexVal2, outputVal; + __m128i complexVal1H, complexVal1L, complexVal2H, complexVal2L, outputVal1, outputVal2; + + unsigned int thirtysecondPoints = num_points / 32; + + for(number = 0; number < thirtysecondPoints; number++){ + + complexVal1 = _mm256_load_si256((__m256i*)complexVectorPtr); + complexVectorPtr += 32; + complexVal2 = _mm256_load_si256((__m256i*)complexVectorPtr); + complexVectorPtr += 32; + + complexVal1H = _mm256_extractf128_si256(complexVal1, 1); + complexVal1L = _mm256_extractf128_si256(complexVal1, 0); + complexVal2H = _mm256_extractf128_si256(complexVal2, 1); + complexVal2L = _mm256_extractf128_si256(complexVal2, 0); + + complexVal1H = _mm_shuffle_epi8(complexVal1H, moveMaskH); + complexVal1L = _mm_shuffle_epi8(complexVal1L, moveMaskL); + outputVal1 = _mm_or_si128(complexVal1H, complexVal1L); + + + complexVal2H = _mm_shuffle_epi8(complexVal2H, moveMaskH); + complexVal2L = _mm_shuffle_epi8(complexVal2L, moveMaskL); + outputVal2 = _mm_or_si128(complexVal2H, complexVal2L); + + __m256i dummy = _mm256_setzero_si256(); + outputVal = _mm256_insertf128_si256(dummy, outputVal1, 0); + outputVal = _mm256_insertf128_si256(outputVal, outputVal2, 1); + + + _mm256_store_si256((__m256i*)iBufferPtr, outputVal); + iBufferPtr += 32; + } + + number = thirtysecondPoints * 32; + for(; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + complexVectorPtr++; + } +} +#endif /* LV_HAVE_AVX */ + #ifdef LV_HAVE_GENERIC /*! \brief Deinterleaves the complex 8 bit vector into I vector data diff --git a/volk/kernels/volk/volk_8ic_s32f_deinterleave_32f_x2.h b/volk/kernels/volk/volk_8ic_s32f_deinterleave_32f_x2.h index 9e244c8fc2..a6115482ec 100644 --- a/volk/kernels/volk/volk_8ic_s32f_deinterleave_32f_x2.h +++ b/volk/kernels/volk/volk_8ic_s32f_deinterleave_32f_x2.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8ic_s32f_deinterleave_32f_x2_a_H #define INCLUDED_volk_8ic_s32f_deinterleave_32f_x2_a_H diff --git a/volk/kernels/volk/volk_8ic_s32f_deinterleave_real_32f.h b/volk/kernels/volk/volk_8ic_s32f_deinterleave_real_32f.h index 56a1adcbb5..bbe2c26b70 100644 --- a/volk/kernels/volk/volk_8ic_s32f_deinterleave_real_32f.h +++ b/volk/kernels/volk/volk_8ic_s32f_deinterleave_real_32f.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8ic_s32f_deinterleave_real_32f_a_H #define INCLUDED_volk_8ic_s32f_deinterleave_real_32f_a_H diff --git a/volk/kernels/volk/volk_8ic_x2_multiply_conjugate_16ic.h b/volk/kernels/volk/volk_8ic_x2_multiply_conjugate_16ic.h index 685a21ddcd..5b64c5218c 100644 --- a/volk/kernels/volk/volk_8ic_x2_multiply_conjugate_16ic.h +++ b/volk/kernels/volk/volk_8ic_x2_multiply_conjugate_16ic.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8ic_x2_multiply_conjugate_16ic_a_H #define INCLUDED_volk_8ic_x2_multiply_conjugate_16ic_a_H diff --git a/volk/kernels/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc.h b/volk/kernels/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc.h index edb52ff509..d6cc1f09cd 100644 --- a/volk/kernels/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc.h +++ b/volk/kernels/volk/volk_8ic_x2_s32f_multiply_conjugate_32fc.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8ic_x2_s32f_multiply_conjugate_32fc_a_H #define INCLUDED_volk_8ic_x2_s32f_multiply_conjugate_32fc_a_H diff --git a/volk/kernels/volk/volk_8u_conv_k7_r2puppet_8u.h b/volk/kernels/volk/volk_8u_conv_k7_r2puppet_8u.h index 8d31e469f2..b398556ca8 100644 --- a/volk/kernels/volk/volk_8u_conv_k7_r2puppet_8u.h +++ b/volk/kernels/volk/volk_8u_conv_k7_r2puppet_8u.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8u_conv_k7_r2puppet_8u_H #define INCLUDED_volk_8u_conv_k7_r2puppet_8u_H diff --git a/volk/kernels/volk/volk_8u_x4_conv_k7_r2_8u.h b/volk/kernels/volk/volk_8u_x4_conv_k7_r2_8u.h index ece8cf0f48..e21dfe1e01 100644 --- a/volk/kernels/volk/volk_8u_x4_conv_k7_r2_8u.h +++ b/volk/kernels/volk/volk_8u_x4_conv_k7_r2_8u.h @@ -1,3 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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_volk_8u_x4_conv_k7_r2_8u_H #define INCLUDED_volk_8u_x4_conv_k7_r2_8u_H diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt index 6cc4504cfa..37915e5552 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -406,10 +406,8 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") # if we find one that matches our current system architecture # set up the assembler flags and include the source files foreach(ARCH ${ASM_ARCHS_AVAILABLE}) - message(STATUS "--==>> -CFLAGS1: ${FULL_C_FLAGS}") string(REGEX MATCH "${ARCH}" ASM_ARCH "${FULL_C_FLAGS}") if( ASM_ARCH STREQUAL "armv7" ) - set(ASM-ATT $ENV{ASM}) message(STATUS "---- Adding ASM files") # we always use ATT syntax message(STATUS "-- Detected armv7 architecture; enabling ASM") # setup architecture specific assembler flags @@ -422,13 +420,20 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") message(STATUS "Adding source file: ${asm_file}") endforeach(asm_file) endif() - set(CMAKE_ASM-ATT_FLAGS_INIT ${ARCH_ASM_FLAGS}) - enable_language(ASM-ATT) # this must be after flags_init - message(STATUS "asm flags: ${CMAKE_ASM-ATT_FLAGS}") + enable_language(ASM) + set(CMAKE_ASM_FLAGS ${ARCH_ASM_FLAGS}) + message(STATUS "c flags: ${FULL_C_FLAGS}") + message(STATUS "asm flags: ${CMAKE_ASM_FLAGS}") endforeach(ARCH) else(${CMAKE_VERSION} VERSION_GREATER "2.8.9") message(STATUS "Not enabling ASM support. CMake >= 2.8.10 required.") + foreach(machine_name ${available_machines}) + string(REGEX MATCH "neon" NEON_MACHINE ${machine_name}) + if( NEON_MACHINE STREQUAL "neon") + message(FATAL_ERROR "CMake >= 2.8.10 is required for ARM NEON support") + endif() + endforeach() endif(${CMAKE_VERSION} VERSION_GREATER "2.8.9") ######################################################################## diff --git a/volk/lib/qa_utils.cc b/volk/lib/qa_utils.cc index f30f0097ae..be20ed6585 100644 --- a/volk/lib/qa_utils.cc +++ b/volk/lib/qa_utils.cc @@ -5,7 +5,9 @@ #include <boost/tokenizer.hpp> #include <boost/xpressive/xpressive.hpp> #include <iostream> +#include <fstream> #include <vector> +#include <map> #include <list> #include <ctime> #include <cmath> @@ -245,7 +247,7 @@ bool fcompare(t *in1, t *in2, unsigned int vlen, float tol) { } } // the primary test is the percent different greater than given tol - else if(fabs(((t *)(in1))[i] - ((t *)(in2))[i])/(((t *)in1)[i]) > tol) { + else if(fabs(((t *)(in1))[i] - ((t *)(in2))[i])/fabs(((t *)in1)[i]) > tol) { fail=true; if(print_max_errs-- > 0) { std::cout << "offset " << i << " in1: " << t(((t *)(in1))[i]) << " in2: " << t(((t *)(in2))[i]) << std::endl; @@ -328,9 +330,9 @@ bool run_volk_tests(volk_func_desc_t desc, lv_32fc_t scalar, int vlen, int iter, - std::vector<std::string> *best_arch_vector = 0, - std::string puppet_master_name = "NULL", - bool benchmark_mode, + std::vector<volk_test_results_t> *results, + std::string puppet_master_name, + bool benchmark_mode, std::string kernel_regex ) { boost::xpressive::sregex kernel_expression = boost::xpressive::sregex::compile(kernel_regex); @@ -338,6 +340,12 @@ bool run_volk_tests(volk_func_desc_t desc, // in this case we have a regex and are only looking to test one kernel return false; } + if(results) { + results->push_back(volk_test_results_t()); + results->back().name = name; + results->back().vlen = vlen; + results->back().iter = iter; + } std::cout << "RUN_VOLK_TESTS: " << name << "(" << vlen << "," << iter << ")" << std::endl; // The multiply and lv_force_cast_hf are work arounds for GNU Radio bugs 582 and 583 @@ -453,6 +461,13 @@ bool run_volk_tests(volk_func_desc_t desc, end = clock(); double arch_time = 1000.0 * (double)(end-start)/(double)CLOCKS_PER_SEC; std::cout << arch_list[i] << " completed in " << arch_time << "ms" << std::endl; + if(results) { + volk_test_time_t result; + result.name = arch_list[i]; + result.time = arch_time; + result.units = "ms"; + results->back().results[result.name] = result; + } profile_times.push_back(arch_time); } @@ -553,13 +568,14 @@ bool run_volk_tests(volk_func_desc_t desc, std::cout << "Best aligned arch: " << best_arch_a << std::endl; std::cout << "Best unaligned arch: " << best_arch_u << std::endl; - if(best_arch_vector) { + if(results) { if(puppet_master_name == "NULL") { - best_arch_vector->push_back(name + " " + best_arch_a + " " + best_arch_u); - } - else { - best_arch_vector->push_back(puppet_master_name + " " + best_arch_a + " " + best_arch_u); + results->back().config_name = name; + } else { + results->back().config_name = puppet_master_name; } + results->back().best_arch_a = best_arch_a; + results->back().best_arch_u = best_arch_u; } return fail_global; diff --git a/volk/lib/qa_utils.h b/volk/lib/qa_utils.h index fc1a0239eb..7ca8b8d1e8 100644 --- a/volk/lib/qa_utils.h +++ b/volk/lib/qa_utils.h @@ -3,7 +3,10 @@ #include <cstdlib> #include <string> +#include <iostream> +#include <fstream> #include <vector> +#include <map> #include <volk/volk.h> #include <volk/volk_common.h> @@ -21,10 +24,46 @@ volk_type_t volk_type_from_string(std::string); float uniform(void); void random_floats(float *buf, unsigned n); -bool run_volk_tests(volk_func_desc_t, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string, bool benchmark_mode=false, std::string kernel_regex=""); +class volk_test_time_t { + public: + std::string name; + double time; + std::string units; +}; + +class volk_test_results_t { + public: + std::string name; + std::string config_name; + int vlen; + int iter; + std::map<std::string, volk_test_time_t> results; + std::string best_arch_a; + std::string best_arch_u; +}; + +bool run_volk_tests( + volk_func_desc_t, + void(*)(), + std::string, + float, + lv_32fc_t, + int, + int, + std::vector<volk_test_results_t> *results = NULL, + std::string puppet_master_name = "NULL", + bool benchmark_mode=false, + std::string kernel_regex="" + ); -#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) BOOST_AUTO_TEST_CASE(func##_test) { BOOST_CHECK_EQUAL(run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, 0, "NULL"), 0); } +#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) \ + BOOST_AUTO_TEST_CASE(func##_test) { \ + BOOST_CHECK_EQUAL(run_volk_tests( \ + func##_get_func_desc(), (void (*)())func##_manual, \ + std::string(#func), tol, scalar, len, iter, 0, "NULL"), \ + 0); \ + } #define VOLK_PROFILE(func, tol, scalar, len, iter, results, bnmode, kernel_regex) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL", bnmode, kernel_regex) #define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results, bnmode, kernel_regex) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func), bnmode, kernel_regex) typedef void (*volk_fn_1arg)(void *, unsigned int, const char*); //one input, operate in place diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc index bc97ad16e5..7807ce40a6 100644 --- a/volk/lib/testqa.cc +++ b/volk/lib/testqa.cc @@ -44,6 +44,15 @@ VOLK_RUN_TESTS(volk_16u_byteswap, 0, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_accumulator_s32f, 1e-4, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_x2_add_32f, 1e-4, 0, 20462, 1); VOLK_RUN_TESTS(volk_32fc_32f_multiply_32fc, 1e-4, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_log2_32f, 1.5e-1, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_expfast_32f, 1e-1, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_x2_pow_32f, 1e-2, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_sin_32f, 1e-6, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_cos_32f, 1e-6, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_tan_32f, 1e-6, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_atan_32f, 1e-3, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_asin_32f, 1e-3, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_acos_32f, 1e-3, 0, 20462, 1); VOLK_RUN_TESTS(volk_32fc_s32f_power_32fc, 1e-4, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_s32f_calc_spectral_noise_floor_32f, 1e-4, 20.0, 20462, 1); VOLK_RUN_TESTS(volk_32fc_s32f_atan2_32f, 1e-4, 10.0, 20462, 1); @@ -88,12 +97,12 @@ VOLK_RUN_TESTS(volk_32i_x2_and_32i, 0, 0, 20462, 1); VOLK_RUN_TESTS(volk_32i_s32f_convert_32f, 1e-4, 100, 20462, 1); VOLK_RUN_TESTS(volk_32i_x2_or_32i, 0, 0, 20462, 1); VOLK_RUN_TESTS(volk_32u_byteswap, 0, 0, 20462, 1); -//VOLK_RUN_TESTS(volk_32u_popcnt, 0, 0, 2046, 10000); +VOLK_RUN_TESTS(volk_32u_popcntpuppet_32u, 0, 0, 2046, 10000); VOLK_RUN_TESTS(volk_64f_convert_32f, 1e-4, 0, 20462, 1); VOLK_RUN_TESTS(volk_64f_x2_max_64f, 1e-4, 0, 20462, 1); VOLK_RUN_TESTS(volk_64f_x2_min_64f, 1e-4, 0, 20462, 1); VOLK_RUN_TESTS(volk_64u_byteswap, 0, 0, 20462, 1); -//VOLK_RUN_TESTS(volk_64u_popcnt, 0, 0, 2046, 10000); +VOLK_RUN_TESTS(volk_64u_popcntpuppet_64u, 0, 0, 2046, 10000); VOLK_RUN_TESTS(volk_8ic_deinterleave_16i_x2, 0, 0, 20462, 1); VOLK_RUN_TESTS(volk_8ic_s32f_deinterleave_32f_x2, 1e-4, 100, 20462, 1); VOLK_RUN_TESTS(volk_8ic_deinterleave_real_16i, 0, 256, 20462, 1); @@ -114,3 +123,4 @@ VOLK_RUN_TESTS(volk_8u_conv_k7_r2puppet_8u, 0, 0, 2060, 1); VOLK_RUN_TESTS(volk_32f_invsqrt_32f, 1e-2, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_binary_slicer_32i, 0, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_binary_slicer_8i, 0, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_tanh_32f, 1e-6, 0, 20462, 1); |