summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Modules/GrBoost.cmake2
-rw-r--r--docs/doxygen/Doxyfile.in3
-rw-r--r--docs/doxygen/other/main_page.dox73
-rw-r--r--gnuradio-core/gnuradio-core.conf3
-rw-r--r--gnuradio-core/src/lib/general/gr_prefs.cc152
-rw-r--r--gnuradio-core/src/lib/general/gr_prefs.h10
-rw-r--r--gnuradio-core/src/lib/general/gr_prefs.i3
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.cc1
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.cc9
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.h13
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc85
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h41
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.i9
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.cc137
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.h15
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc12
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.h4
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/__init__.py2
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pdu.py2
-rw-r--r--gr-blocks/include/blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/include/blocks/count_bits.h46
-rw-r--r--gr-blocks/lib/CMakeLists.txt1
-rw-r--r--gr-blocks/lib/count_bits.cc78
-rw-r--r--gr-blocks/lib/file_source_impl.cc1
-rw-r--r--gr-digital/grc/digital_block_tree.xml1
-rw-r--r--gr-digital/grc/digital_simple_correlator.xml25
-rw-r--r--gr-digital/include/CMakeLists.txt1
-rw-r--r--gr-digital/include/digital_simple_correlator.h107
-rw-r--r--gr-digital/lib/CMakeLists.txt1
-rw-r--r--gr-digital/lib/digital_simple_correlator.cc231
-rwxr-xr-xgr-digital/python/qa_simple_correlator.py62
-rw-r--r--gr-digital/swig/CMakeLists.txt1
-rw-r--r--gr-digital/swig/digital_simple_correlator.i31
-rw-r--r--gr-digital/swig/digital_swig.i2
-rw-r--r--gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py103
-rw-r--r--gr-howto-write-a-block/docs/doxygen/swig_doc.py159
-rw-r--r--gr-utils/src/python/modtool/templates.py14
-rw-r--r--grc/blocks/gr_message_debug.xml2
-rw-r--r--grc/blocks/gr_pdu_to_tagged_stream.xml6
-rw-r--r--grc/blocks/gr_tagged_stream_to_pdu.xml6
-rw-r--r--grc/python/extract_docs.py8
-rw-r--r--volk/CMakeLists.txt14
-rw-r--r--volk/apps/volk_profile.cc37
43 files changed, 1371 insertions, 143 deletions
diff --git a/cmake/Modules/GrBoost.cmake b/cmake/Modules/GrBoost.cmake
index 38cb027f8..01378df66 100644
--- a/cmake/Modules/GrBoost.cmake
+++ b/cmake/Modules/GrBoost.cmake
@@ -39,6 +39,8 @@ if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
if(MSVC)
+ set(BOOST_REQUIRED_COMPONENTS ${BOOST_REQUIRED_COMPONENTS} chrono)
+
if (NOT DEFINED BOOST_ALL_DYN_LINK)
set(BOOST_ALL_DYN_LINK TRUE)
endif()
diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in
index 78a7a5d16..536661996 100644
--- a/docs/doxygen/Doxyfile.in
+++ b/docs/doxygen/Doxyfile.in
@@ -633,7 +633,8 @@ EXCLUDE = @abs_top_builddir@/docs/doxygen/html \
@abs_top_builddir@/_CPack_Packages \
@abs_top_srcdir@/cmake \
@abs_top_srcdir@/gr-qtgui/lib \
- @abs_top_srcdir@/gr-howto-write-a-block
+ @abs_top_srcdir@/gr-howto-write-a-block \
+ @abs_top_srcdir@/gr-utils/src/python/modtool/gr-newmod
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox
index abdc21b0c..e7d4685f7 100644
--- a/docs/doxygen/other/main_page.dox
+++ b/docs/doxygen/other/main_page.dox
@@ -329,4 +329,77 @@ they can also serve as examples. See the gr_complex_to_xxx.h file for
examples of various blocks that make use of Volk.
+\section prefs Configuration / Preference Files
+
+GNU Radio defines some of its basic behavior through a set of
+configuration files located in
+${prefix}/etc/gnuradio/conf.d. Different components have different
+files listed in here for the various properties. These will be read
+once when starting a GNU Radio application, so updates during runtime
+will not affect them.
+
+The configuration files use the following format:
+
+\code
+# Stuff from section 1
+[section1]
+var1 = value1
+var2 = value2 # value of 2
+
+# Stuff from section 2
+[section2]
+var3 = value3
+\endcode
+
+In this file, the hash mark ('#') indicates a comment and blank lines
+are ignored. Section labels are defined inside square brackets as a
+group distinguisher. All options must be associated with a section
+name. The options are listed one per line with the option name is
+given followed by an equals ('=') sign and then the value. All section
+and option names must not have white spaces (actually, all white
+spaces are ignored).
+
+The value of an option can be a string or number and retrieved through
+a few different interfaces. There is a single preference object
+created when GNU Radio is launched. In Python, you can get this by
+making a new variable:
+
+\code
+p = gr.prefs()
+\endcode
+
+Similarly, in C++, we get a reference to the object by explicitly
+calling for the singleton of the object:
+
+\code
+ gr_prefs *p = gr_prefs::singleton();
+\endcode
+
+The methods associated with this preferences object are (from class gr_prefs):
+
+\code
+ bool has_section(string section)
+ bool has_option(string section, string option)
+ string get_string(string section, string option, string default_val)
+ bool get_bool(string section, string option, bool default_val)
+ long get_long(string section, string option, long default_val)
+ double get_double(string section, string option, double default_val)
+\endcode
+
+When setting a Boolean value, we can use 0, 1, "True", "true",
+"False", "false", "On", "on", "Off", and "off".
+
+All configuration preferences in these files can also be overloaded by
+an environmental variable. The environmental variable is named based
+on the section and option name from the configuration file as:
+
+\code
+ GR_CONF_<SECTION>_<OPTION> = <value>
+\endcode
+
+The "GR_CONF_" is a prefix to identify this as a GNU Radio
+configuration variable and the section and option names are in
+uppercase. The value is the same format that would be used in the
+config file itself.
+
*/
diff --git a/gnuradio-core/gnuradio-core.conf b/gnuradio-core/gnuradio-core.conf
index 178b288e8..70eb00236 100644
--- a/gnuradio-core/gnuradio-core.conf
+++ b/gnuradio-core/gnuradio-core.conf
@@ -5,3 +5,6 @@
[DEFAULT]
verbose = False
+
+[PerfCounters]
+on = False
diff --git a/gnuradio-core/src/lib/general/gr_prefs.cc b/gnuradio-core/src/lib/general/gr_prefs.cc
index 20aead8e3..953143bc5 100644
--- a/gnuradio-core/src/lib/general/gr_prefs.cc
+++ b/gnuradio-core/src/lib/general/gr_prefs.cc
@@ -25,6 +25,14 @@
#endif
#include <gr_prefs.h>
+#include <gr_sys_paths.h>
+#include <gr_constants.h>
+#include <algorithm>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/fstream.hpp>
+namespace fs = boost::filesystem;
/*
* Stub implementations
@@ -45,44 +53,176 @@ gr_prefs::set_singleton(gr_prefs *p)
s_singleton = p;
}
+gr_prefs::gr_prefs()
+{
+ _read_files();
+}
+
gr_prefs::~gr_prefs()
{
// nop
}
+std::vector<std::string>
+gr_prefs::_sys_prefs_filenames()
+{
+ std::vector<std::string> fnames;
+
+ fs::path dir = gr_prefsdir();
+ if(!fs::is_directory(dir))
+ return fnames;
+
+ fs::directory_iterator diritr(dir);
+ while(diritr != fs::directory_iterator()) {
+ fs::path p = *diritr++;
+ fnames.push_back(p.string());
+ }
+ std::sort(fnames.begin(), fnames.end());
+
+ // Find if there is a ~/.gnuradio/config file and add this to the
+ // beginning of the file list to override any preferences in the
+ // installed path config files.
+ fs::path homedir = fs::path(gr_appdata_path());
+ homedir /= ".gnuradio/config.conf";
+ if(fs::exists(homedir)) {
+ fnames.insert(fnames.begin(), homedir.string());
+ }
+
+ return fnames;
+}
+
+void
+gr_prefs::_read_files()
+{
+ std::vector<std::string> filenames = _sys_prefs_filenames();
+ std::vector<std::string>::iterator sitr;
+ char tmp[1024];
+ for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) {
+ fs::ifstream fin(*sitr);
+ while(!fin.eof()) {
+ fin.getline(tmp, 1024);
+ std::string t(tmp);
+ // ignore empty lines or lines of just comments
+ if((t.size() > 0) && (t[0] != '#')) {
+ // remove any comments in the line
+ size_t hash = t.find("#");
+
+ // Use hash marks at the end of each segment as a delimiter
+ d_configs += t.substr(0, hash) + '#';
+ }
+ }
+ fin.close();
+ }
+
+ // Remove all whitespace
+ d_configs.erase(std::remove_if(d_configs.begin(), d_configs.end(), ::isspace), d_configs.end());
+}
+
bool
gr_prefs::has_section(const std::string section)
{
- return false;
+ size_t t = d_configs.find("[" + section + "]#");
+ return t != std::string::npos;
}
bool
gr_prefs::has_option(const std::string section, const std::string option)
{
- return false;
+ if(has_section(section)) {
+ size_t sec = d_configs.find("[" + section + "]#");
+ size_t opt = d_configs.find("#" + option + "=", sec);
+ return opt != std::string::npos;
+ }
+ else {
+ return false;
+ }
}
const std::string
gr_prefs::get_string(const std::string section, const std::string option, const std::string default_val)
{
- return default_val;
+ std::stringstream envname;
+ std::string secname=section, optname=option;
+
+ std::transform(section.begin(), section.end(), secname.begin(), ::toupper);
+ std::transform(option.begin(), option.end(), optname.begin(), ::toupper);
+ envname << "GR_CONF_" << secname << "_" << optname;
+
+ char *v = getenv(envname.str().c_str());
+ if(v) {
+ return std::string(v);
+ }
+
+ if(has_option(section, option)) {
+ std::string optname = "#" + option + "=";
+ size_t sec = d_configs.find("[" + section + "]#");
+ size_t opt = d_configs.find(optname, sec);
+
+ size_t start = opt + optname.size();
+ size_t end = d_configs.find("#", start);
+ size_t len = end - start;
+
+ return d_configs.substr(start, len);
+ }
+ else {
+ return default_val;
+ }
}
bool
gr_prefs::get_bool(const std::string section, const std::string option, bool default_val)
{
- return default_val;
+ if(has_option(section, option)) {
+ std::string str = get_string(section, option, "");
+ if(str == "") {
+ return default_val;
+ }
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+ if((str == "true") || (str == "on") || (str == "1"))
+ return true;
+ else if((str == "false") || (str == "off") || (str == "0"))
+ return false;
+ else
+ return default_val;
+ }
+ else {
+ return default_val;
+ }
}
long
gr_prefs::get_long(const std::string section, const std::string option, long default_val)
{
- return default_val;
+ if(has_option(section, option)) {
+ std::string str = get_string(section, option, "");
+ if(str == "") {
+ return default_val;
+ }
+ std::stringstream sstr(str);
+ long n;
+ sstr >> n;
+ return n;
+ }
+ else {
+ return default_val;
+ }
}
double
gr_prefs::get_double(const std::string section, const std::string option, double default_val)
{
- return default_val;
+ if(has_option(section, option)) {
+ std::string str = get_string(section, option, "");
+ if(str == "") {
+ return default_val;
+ }
+ std::stringstream sstr(str);
+ double n;
+ sstr >> n;
+ return n;
+ }
+ else {
+ return default_val;
+ }
}
diff --git a/gnuradio-core/src/lib/general/gr_prefs.h b/gnuradio-core/src/lib/general/gr_prefs.h
index b1c354bd3..90d602741 100644
--- a/gnuradio-core/src/lib/general/gr_prefs.h
+++ b/gnuradio-core/src/lib/general/gr_prefs.h
@@ -24,6 +24,7 @@
#include <gr_core_api.h>
#include <string>
+#include <gruel/thread.h>
/*!
* \brief Base class for representing user preferences a la windows INI files.
@@ -39,6 +40,7 @@ public:
static gr_prefs *singleton();
static void set_singleton(gr_prefs *p);
+ gr_prefs();
virtual ~gr_prefs();
/*!
@@ -78,6 +80,14 @@ public:
virtual double get_double(const std::string section,
const std::string option,
double default_val);
+
+ protected:
+ virtual std::vector<std::string> _sys_prefs_filenames();
+ virtual void _read_files();
+
+ private:
+ gruel::mutex d_mutex;
+ std::string d_configs;
};
diff --git a/gnuradio-core/src/lib/general/gr_prefs.i b/gnuradio-core/src/lib/general/gr_prefs.i
index f44dcc944..cfb4cdb4e 100644
--- a/gnuradio-core/src/lib/general/gr_prefs.i
+++ b/gnuradio-core/src/lib/general/gr_prefs.i
@@ -20,9 +20,6 @@
* Boston, MA 02110-1301, USA.
*/
-// Generate SWIG directors for gr_prefs.
-%feature("director") gr_prefs;
-
class gr_prefs
{
public:
diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc
index f3def0721..6da7abac2 100644
--- a/gnuradio-core/src/lib/io/gr_file_source.cc
+++ b/gnuradio-core/src/lib/io/gr_file_source.cc
@@ -24,6 +24,7 @@
#include "config.h"
#endif
+#include <gruel/thread.h>
#include <gr_file_source.h>
#include <gr_io_signature.h>
#include <cstdio>
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc
index 1327c31ba..9eb1bb639 100644
--- a/gnuradio-core/src/lib/io/gr_message_debug.cc
+++ b/gnuradio-core/src/lib/io/gr_message_debug.cc
@@ -59,10 +59,10 @@ gr_message_debug::store(pmt::pmt_t msg)
}
void
-gr_message_debug::print_verbose(pmt::pmt_t msg)
+gr_message_debug::print_pdu(pmt::pmt_t pdu)
{
- pmt::pmt_t meta = pmt::pmt_car(msg);
- pmt::pmt_t vector = pmt::pmt_cdr(msg);
+ pmt::pmt_t meta = pmt::pmt_car(pdu);
+ pmt::pmt_t vector = pmt::pmt_cdr(pdu);
std::cout << "* MESSAGE DEBUG PRINT PDU VERBOSE *\n";
pmt::pmt_print(meta);
size_t len = pmt::pmt_length(vector);
@@ -110,6 +110,9 @@ gr_message_debug::gr_message_debug()
message_port_register_in(pmt::mp("store"));
set_msg_handler(pmt::mp("store"), boost::bind(&gr_message_debug::store, this, _1));
+
+ message_port_register_in(pmt::mp("print_pdu"));
+ set_msg_handler(pmt::mp("print_pdu"), boost::bind(&gr_message_debug::print_pdu, this, _1));
}
gr_message_debug::~gr_message_debug()
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h
index 6e6e5103c..f1374e806 100644
--- a/gnuradio-core/src/lib/io/gr_message_debug.h
+++ b/gnuradio-core/src/lib/io/gr_message_debug.h
@@ -55,7 +55,18 @@ class GR_CORE_API gr_message_debug : public gr_block
* \param msg A pmt message passed from the scheduler's message handling.
*/
void print(pmt::pmt_t msg);
- void print_verbose(pmt::pmt_t msg);
+
+ /*!
+ * \brief PDU formatted messages received in this port are printed to stdout.
+ *
+ * This port receives messages from the scheduler's message handling
+ * mechanism and prints it to stdout. This message handler function
+ * is only meant to be used by the scheduler to handle messages
+ * posted to port 'print'.
+ *
+ * \param pdu A PDU message passed from the scheduler's message handling.
+ */
+ void print_pdu(pmt::pmt_t pdu);
/*!
* \brief Messages received in this port are stored in a vector.
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index f52f7a6ba..54d267620 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -282,6 +282,17 @@ gr_block::pc_noutput_items()
}
float
+gr_block::pc_noutput_items_var()
+{
+ if(d_detail) {
+ return d_detail->pc_noutput_items_var();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
gr_block::pc_nproduced()
{
if(d_detail) {
@@ -293,6 +304,17 @@ gr_block::pc_nproduced()
}
float
+gr_block::pc_nproduced_var()
+{
+ if(d_detail) {
+ return d_detail->pc_nproduced_var();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
gr_block::pc_input_buffers_full(int which)
{
if(d_detail) {
@@ -303,6 +325,17 @@ gr_block::pc_input_buffers_full(int which)
}
}
+float
+gr_block::pc_input_buffers_full_var(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full_var(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
std::vector<float>
gr_block::pc_input_buffers_full()
{
@@ -314,6 +347,17 @@ gr_block::pc_input_buffers_full()
}
}
+std::vector<float>
+gr_block::pc_input_buffers_full_var()
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full_var();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
float
gr_block::pc_output_buffers_full(int which)
{
@@ -325,6 +369,17 @@ gr_block::pc_output_buffers_full(int which)
}
}
+float
+gr_block::pc_output_buffers_full_var(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full_var(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
std::vector<float>
gr_block::pc_output_buffers_full()
{
@@ -336,6 +391,17 @@ gr_block::pc_output_buffers_full()
}
}
+std::vector<float>
+gr_block::pc_output_buffers_full_var()
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full_var();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
float
gr_block::pc_work_time()
{
@@ -347,6 +413,25 @@ gr_block::pc_work_time()
}
}
+float
+gr_block::pc_work_time_var()
+{
+ if(d_detail) {
+ return d_detail->pc_work_time_var();
+ }
+ else {
+ return 0;
+ }
+}
+
+void
+gr_block::reset_perf_counters()
+{
+ if(d_detail) {
+ d_detail->reset_perf_counters();
+ }
+}
+
std::ostream&
operator << (std::ostream& os, const gr_block *m)
{
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index bd9ff42df..6e21d5b97 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -383,35 +383,74 @@ class GR_CORE_API gr_block : public gr_basic_block {
float pc_noutput_items();
/*!
+ * \brief Gets variance of noutput_items performance counter.
+ */
+ float pc_noutput_items_var();
+
+ /*!
* \brief Gets average num items produced performance counter.
*/
float pc_nproduced();
/*!
- * \brief Gets average average fullness of \p which input buffer.
+ * \brief Gets variance of num items produced performance counter.
+ */
+ float pc_nproduced_var();
+
+ /*!
+ * \brief Gets average fullness of \p which input buffer.
*/
float pc_input_buffers_full(int which);
/*!
+ * \brief Gets variance of fullness of \p which input buffer.
+ */
+ float pc_input_buffers_full_var(int which);
+
+ /*!
* \brief Gets average fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full();
/*!
+ * \brief Gets variance of fullness of all input buffers.
+ */
+ std::vector<float> pc_input_buffers_full_var();
+
+ /*!
* \brief Gets average fullness of \p which input buffer.
*/
float pc_output_buffers_full(int which);
/*!
+ * \brief Gets variance of fullness of \p which input buffer.
+ */
+ float pc_output_buffers_full_var(int which);
+
+ /*!
* \brief Gets average fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full();
+ /*!
+ * \brief Gets variance of fullness of all output buffers.
+ */
+ std::vector<float> pc_output_buffers_full_var();
/*!
* \brief Gets average clock cycles spent in work.
*/
float pc_work_time();
+ /*!
+ * \brief Gets average clock cycles spent in work.
+ */
+ float pc_work_time_var();
+
+ /*!
+ * \brief Resets the performance counters
+ */
+ void reset_perf_counters();
+
// ----------------------------------------------------------------------------
// Functions to handle thread affinity
diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i
index c016f2c28..a80f64d02 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_block.i
@@ -68,13 +68,20 @@ class gr_block : public gr_basic_block {
// Methods to access performance counters
float pc_noutput_items();
+ float pc_noutput_items_var();
float pc_nproduced();
+ float pc_nproduced_var();
float pc_input_buffers_full(int which);
+ float pc_input_buffers_full_var(int which);
std::vector<float> pc_input_buffers_full();
+ std::vector<float> pc_input_buffers_full_var();
float pc_output_buffers_full(int which);
+ float pc_output_buffers_full_var(int which);
std::vector<float> pc_output_buffers_full();
+ std::vector<float> pc_output_buffers_full_var();
float pc_work_time();
-
+ float pc_work_time_var();
+
// Methods to manage processor affinity.
void set_processor_affinity(const gr_vector_uint &mask);
void unset_processor_affinity();
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
index ff20e0e85..82081039a 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
@@ -43,10 +43,17 @@ gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs)
d_ninputs (ninputs), d_noutputs (noutputs),
d_input (ninputs), d_output (noutputs),
d_done (false),
- d_avg_noutput_items(0), d_avg_nproduced(0),
+ d_avg_noutput_items(0),
+ d_var_noutput_items(0),
+ d_avg_nproduced(0),
+ d_var_nproduced(0),
d_avg_input_buffers_full(ninputs, 0),
+ d_var_input_buffers_full(ninputs, 0),
d_avg_output_buffers_full(noutputs, 0),
- d_avg_work_time(0)
+ d_var_output_buffers_full(noutputs, 0),
+ d_avg_work_time(0),
+ d_var_work_time(0),
+ d_pc_counter(0)
{
s_ncurrently_allocated++;
}
@@ -237,27 +244,68 @@ gr_block_detail::start_perf_counters()
void
gr_block_detail::stop_perf_counters(int noutput_items, int nproduced)
{
- float alpha = 0.05;
- float beta = 1.0-alpha;
-
d_end_of_work = gruel::high_res_timer_now();
gruel::high_res_timer_type diff = d_end_of_work - d_start_of_work;
- d_avg_work_time = beta*d_avg_work_time + alpha*diff;
-
- d_avg_nproduced = beta*d_avg_nproduced + alpha*nproduced;
- d_avg_noutput_items = beta*d_avg_noutput_items + alpha*noutput_items;
- for(size_t i=0; i < d_input.size(); i++) {
- float pfull = static_cast<float>(d_input[i]->items_available()) /
- static_cast<float>(d_input[i]->max_possible_items_available());
- d_avg_input_buffers_full[i] = beta*d_avg_input_buffers_full[i] + alpha*pfull;
+ if(d_pc_counter == 0) {
+ d_avg_work_time = diff;
+ d_var_work_time = 0;
+ d_avg_nproduced = nproduced;
+ d_var_nproduced = 0;
+ d_avg_noutput_items = noutput_items;
+ d_var_noutput_items = 0;
+ for(size_t i=0; i < d_input.size(); i++) {
+ float pfull = static_cast<float>(d_input[i]->items_available()) /
+ static_cast<float>(d_input[i]->max_possible_items_available());
+ d_avg_input_buffers_full[i] = pfull;
+ d_var_input_buffers_full[i] = 0;
+ }
+ for(size_t i=0; i < d_output.size(); i++) {
+ float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
+ static_cast<float>(d_output[i]->bufsize());
+ d_avg_output_buffers_full[i] = pfull;
+ d_var_output_buffers_full[i] = 0;
+ }
}
+ else {
+ float d = diff - d_avg_work_time;
+ d_avg_work_time = d_avg_work_time + d/d_pc_counter;
+ d_var_work_time = d_var_work_time + d*d;
+
+ d = nproduced - d_avg_nproduced;
+ d_avg_nproduced = d_avg_nproduced + d/d_pc_counter;
+ d_var_nproduced = d_var_nproduced + d*d;
+
+ d = noutput_items - d_avg_noutput_items;
+ d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter;
+ d_var_noutput_items = d_var_noutput_items + d*d;
+
+ for(size_t i=0; i < d_input.size(); i++) {
+ float pfull = static_cast<float>(d_input[i]->items_available()) /
+ static_cast<float>(d_input[i]->max_possible_items_available());
+
+ d = pfull - d_avg_input_buffers_full[i];
+ d_avg_input_buffers_full[i] = d_avg_input_buffers_full[i] + d/d_pc_counter;
+ d_var_input_buffers_full[i] = d_var_input_buffers_full[i] + d*d;
+ }
- for(size_t i=0; i < d_output.size(); i++) {
- float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
- static_cast<float>(d_output[i]->bufsize());
- d_avg_output_buffers_full[i] = beta*d_avg_output_buffers_full[i] + alpha*pfull;
+ for(size_t i=0; i < d_output.size(); i++) {
+ float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
+ static_cast<float>(d_output[i]->bufsize());
+
+ d = pfull - d_avg_output_buffers_full[i];
+ d_avg_output_buffers_full[i] = d_avg_output_buffers_full[i] + d/d_pc_counter;
+ d_var_output_buffers_full[i] = d_var_output_buffers_full[i] + d*d;
+ }
}
+
+ d_pc_counter++;
+}
+
+void
+gr_block_detail::reset_perf_counters()
+{
+ d_pc_counter = 0;
}
float
@@ -307,3 +355,58 @@ gr_block_detail::pc_work_time()
{
return d_avg_work_time;
}
+
+
+float
+gr_block_detail::pc_noutput_items_var()
+{
+ return d_var_noutput_items/(d_pc_counter-1);
+}
+
+float
+gr_block_detail::pc_nproduced_var()
+{
+ return d_var_nproduced/(d_pc_counter-1);
+}
+
+float
+gr_block_detail::pc_input_buffers_full_var(size_t which)
+{
+ if(which < d_avg_input_buffers_full.size())
+ return d_var_input_buffers_full[which]/(d_pc_counter-1);
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_input_buffers_full_var()
+{
+ std::vector<float> var(d_avg_input_buffers_full.size(), 0);
+ for(size_t i = 0; i < d_avg_input_buffers_full.size(); i++)
+ var[i] = d_avg_input_buffers_full[i]/(d_pc_counter-1);
+ return var;
+}
+
+float
+gr_block_detail::pc_output_buffers_full_var(size_t which)
+{
+ if(which < d_avg_output_buffers_full.size())
+ return d_var_output_buffers_full[which]/(d_pc_counter-1);
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_output_buffers_full_var()
+{
+ std::vector<float> var(d_avg_output_buffers_full.size(), 0);
+ for(size_t i = 0; i < d_avg_output_buffers_full.size(); i++)
+ var[i] = d_avg_output_buffers_full[i]/(d_pc_counter-1);
+ return var;
+}
+
+float
+gr_block_detail::pc_work_time_var()
+{
+ return d_var_work_time/(d_pc_counter-1);
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h
index a8ed8da90..32a01e763 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h
@@ -173,6 +173,7 @@ class GR_CORE_API gr_block_detail {
void start_perf_counters();
void stop_perf_counters(int noutput_items, int nproduced);
+ void reset_perf_counters();
// Calls to get performance counter items
float pc_noutput_items();
@@ -182,6 +183,14 @@ class GR_CORE_API gr_block_detail {
float pc_output_buffers_full(size_t which);
std::vector<float> pc_output_buffers_full();
float pc_work_time();
+
+ float pc_noutput_items_var();
+ float pc_nproduced_var();
+ float pc_input_buffers_full_var(size_t which);
+ std::vector<float> pc_input_buffers_full_var();
+ float pc_output_buffers_full_var(size_t which);
+ std::vector<float> pc_output_buffers_full_var();
+ float pc_work_time_var();
gr_tpb_detail d_tpb; // used by thread-per-block scheduler
int d_produce_or;
@@ -197,11 +206,17 @@ class GR_CORE_API gr_block_detail {
// Performance counters
float d_avg_noutput_items;
+ float d_var_noutput_items;
float d_avg_nproduced;
+ float d_var_nproduced;
std::vector<float> d_avg_input_buffers_full;
+ std::vector<float> d_var_input_buffers_full;
std::vector<float> d_avg_output_buffers_full;
+ std::vector<float> d_var_output_buffers_full;
gruel::high_res_timer_type d_start_of_work, d_end_of_work;
float d_avg_work_time;
+ float d_var_work_time;
+ float d_pc_counter;
gr_block_detail (unsigned int ninputs, unsigned int noutputs);
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index 27f591452..e070f3c50 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -28,6 +28,7 @@
#include <gr_block.h>
#include <gr_block_detail.h>
#include <gr_buffer.h>
+#include <gr_prefs.h>
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
@@ -165,6 +166,11 @@ gr_block_executor::gr_block_executor (gr_block_sptr block, int max_noutput_items
<< d_block << std::endl;
}
+#ifdef GR_PERFORMANCE_COUNTERS
+ gr_prefs *prefs = gr_prefs::singleton();
+ d_use_pc = prefs->get_bool("PerfCounters", "on", false);
+#endif /* GR_PERFORMANCE_COUNTERS */
+
d_block->start(); // enable any drivers, etc.
}
@@ -420,7 +426,8 @@ gr_block_executor::run_one_iteration()
d_start_nitems_read[i] = d->nitems_read(i);
#ifdef GR_PERFORMANCE_COUNTERS
- d->start_perf_counters();
+ if(d_use_pc)
+ d->start_perf_counters();
#endif /* GR_PERFORMANCE_COUNTERS */
// Do the actual work of the block
@@ -428,7 +435,8 @@ gr_block_executor::run_one_iteration()
d_input_items, d_output_items);
#ifdef GR_PERFORMANCE_COUNTERS
- d->stop_perf_counters(noutput_items, n);
+ if(d_use_pc)
+ d->stop_perf_counters(noutput_items, n);
#endif /* GR_PERFORMANCE_COUNTERS */
LOG(*d_log << " general_work: noutput_items = " << noutput_items
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.h b/gnuradio-core/src/lib/runtime/gr_block_executor.h
index 0ae5affba..fb7f9c269 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.h
@@ -53,6 +53,10 @@ protected:
std::vector<gr_tag_t> d_returned_tags;
int d_max_noutput_items;
+#ifdef GR_PERFORMANCE_COUNTERS
+ bool d_use_pc;
+#endif /* GR_PERFORMANCE_COUNTERS */
+
public:
gr_block_executor(gr_block_sptr block, int max_noutput_items=100000);
~gr_block_executor ();
diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py
index f1b971e62..1c2c4c837 100644
--- a/gnuradio-core/src/python/gnuradio/gr/__init__.py
+++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py
@@ -36,7 +36,7 @@ serial_to_parallel = stream_to_vector
parallel_to_serial = vector_to_stream
# Force the preference database to be initialized
-from prefs import prefs
+prefs = gr_prefs.singleton
#alias old gr_add_vXX and gr_multiply_vXX
add_vcc = add_cc
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
index 572d8b186..c1110c10b 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
@@ -46,7 +46,7 @@ class test_pdu(gr_unittest.TestCase):
# Test that the right number of ports exist.
pi = dbg.message_ports_in()
po = dbg.message_ports_out()
- self.assertEqual(pmt.pmt_length(pi), 2)
+ self.assertEqual(pmt.pmt_length(pi), 3)
self.assertEqual(pmt.pmt_length(po), 0)
pi = snk3.message_ports_in()
diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt
index 0459097b0..37790b7cf 100644
--- a/gr-blocks/include/blocks/CMakeLists.txt
+++ b/gr-blocks/include/blocks/CMakeLists.txt
@@ -89,6 +89,7 @@ add_custom_target(blocks_generated_includes DEPENDS
install(FILES
${generated_includes}
api.h
+ count_bits.h
add_ff.h
char_to_float.h
char_to_short.h
diff --git a/gr-blocks/include/blocks/count_bits.h b/gr-blocks/include/blocks/count_bits.h
new file mode 100644
index 000000000..ceb882f67
--- /dev/null
+++ b/gr-blocks/include/blocks/count_bits.h
@@ -0,0 +1,46 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,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.
+ */
+
+#ifndef _GR_COUNT_BITS_H_
+#define _GR_COUNT_BITS_H_
+
+#include <blocks/api.h>
+
+namespace gr {
+ namespace blocks {
+
+ //! return number of set bits in the low 8 bits of x
+ BLOCKS_API unsigned int count_bits8(unsigned int x);
+
+ //! return number of set bits in the low 16 bits of x
+ BLOCKS_API unsigned int count_bits16(unsigned int x);
+
+ //! return number of set bits in the low 32 bits of x
+ BLOCKS_API unsigned int count_bits32(unsigned int x);
+
+ //! return number of set bits in a 64-bit word
+ BLOCKS_API unsigned int count_bits64(unsigned long long int x);
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* _GR_COUNT_BITS_H_ */
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index 30eab7b75..560a55d57 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -126,6 +126,7 @@ link_directories(${Boost_LIBRARY_DIRS})
########################################################################
list(APPEND gr_blocks_sources
${generated_sources}
+ count_bits.cc
add_ff_impl.cc
char_to_float_impl.cc
char_to_short_impl.cc
diff --git a/gr-blocks/lib/count_bits.cc b/gr-blocks/lib/count_bits.cc
new file mode 100644
index 000000000..167396b57
--- /dev/null
+++ b/gr-blocks/lib/count_bits.cc
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,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.
+ */
+
+#include <blocks/count_bits.h>
+
+/*
+ * these are slow and obvious. If you need something faster, fix these
+ *
+ * Can probably replace with VOLK's popcount
+ */
+
+namespace gr {
+ namespace blocks {
+
+ unsigned int
+ count_bits8(unsigned int x)
+ {
+ int count = 0;
+
+ for(int i = 0; i < 8; i++) {
+ if(x & (1 << i))
+ count++;
+ }
+
+ return count;
+ }
+
+ unsigned int
+ count_bits16(unsigned int x)
+ {
+ int count = 0;
+
+ for(int i = 0; i < 16; i++) {
+ if(x & (1 << i))
+ count++;
+ }
+
+ return count;
+ }
+
+ unsigned int
+ count_bits32(unsigned int x)
+ {
+ unsigned res = (x & 0x55555555) + ((x >> 1) & 0x55555555);
+ res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+ res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+ res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+ return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+ }
+
+ unsigned int
+ count_bits64(unsigned long long x)
+ {
+ return count_bits32((x >> 32) & 0xffffffff) + \
+ count_bits32(x & 0xffffffff);
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/file_source_impl.cc b/gr-blocks/lib/file_source_impl.cc
index a8db31be7..dcbd04210 100644
--- a/gr-blocks/lib/file_source_impl.cc
+++ b/gr-blocks/lib/file_source_impl.cc
@@ -24,6 +24,7 @@
#include "config.h"
#endif
+#include <gruel/thread.h>
#include "file_source_impl.h"
#include <gr_io_signature.h>
#include <cstdio>
diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml
index 9efa0d3fb..36827028e 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -59,6 +59,7 @@
<block>digital_framer_sink_1</block>
<block>digital_packet_sink</block>
<block>digital_simple_framer</block>
+ <block>digital_simple_correlator</block>
</cat>
<cat>
<name>Digital Modulators</name>
diff --git a/gr-digital/grc/digital_simple_correlator.xml b/gr-digital/grc/digital_simple_correlator.xml
new file mode 100644
index 000000000..3b70e59b1
--- /dev/null
+++ b/gr-digital/grc/digital_simple_correlator.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Simple Correlator
+###################################################
+ -->
+<block>
+ <name>Simple Correlator</name>
+ <key>digital_simple_correlator</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.simple_correlator($payload_bytesize)</make>
+ <param>
+ <name>Payload Byte Size</name>
+ <key>payload_bytesize</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-digital/include/CMakeLists.txt b/gr-digital/include/CMakeLists.txt
index f863b2875..ad5baec87 100644
--- a/gr-digital/include/CMakeLists.txt
+++ b/gr-digital/include/CMakeLists.txt
@@ -123,6 +123,7 @@ install(FILES
digital_scrambler_bb.h
digital_simple_framer.h
digital_simple_framer_sync.h
+ digital_simple_correlator.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
COMPONENT "digital_devel"
)
diff --git a/gr-digital/include/digital_simple_correlator.h b/gr-digital/include/digital_simple_correlator.h
new file mode 100644
index 000000000..716c6995c
--- /dev/null
+++ b/gr-digital/include/digital_simple_correlator.h
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+#ifndef INCLUDED_GR_SIMPLE_CORRELATOR_H
+#define INCLUDED_GR_SIMPLE_CORRELATOR_H
+
+#include <digital_api.h>
+#include <gr_block.h>
+
+class digital_simple_correlator;
+typedef boost::shared_ptr<digital_simple_correlator> digital_simple_correlator_sptr;
+
+DIGITAL_API digital_simple_correlator_sptr digital_make_simple_correlator(int payload_bytesize);
+
+/*!
+ * \brief inverse of simple_framer (more or less)
+ * \ingroup sync_blk
+ */
+class DIGITAL_API digital_simple_correlator : public gr_block
+{
+ private:
+ static const int OVERSAMPLE = 8;
+ enum state_t { ST_LOOKING, ST_UNDER_THRESHOLD, ST_LOCKED };
+
+ int d_payload_bytesize;
+ state_t d_state;
+ unsigned int d_osi; // over sample index [0,OVERSAMPLE-1]
+ unsigned int d_transition_osi; // first index where Hamming dist < thresh
+ unsigned int d_center_osi; // center of bit
+ unsigned long long int d_shift_reg[OVERSAMPLE];
+ int d_bblen; // length of bitbuf
+ unsigned char *d_bitbuf; // demodulated bits
+ unsigned char *d_pktbuf; // temp packet buf
+ int d_bbi; // bitbuf index
+
+ static const int AVG_PERIOD = 512; // must be power of 2 (for freq offset correction)
+ int d_avbi;
+ float d_avgbuf[AVG_PERIOD];
+ float d_avg;
+ float d_accum;
+
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ FILE *d_debug_fp; // binary log file
+#endif
+
+ friend GR_CORE_API digital_simple_correlator_sptr
+ digital_make_simple_correlator(int payload_bytesize);
+ digital_simple_correlator(int payload_bytesize);
+
+ inline int slice(float x)
+ {
+ return x >= d_avg ? 1 : 0;
+ }
+
+ void update_avg(float x);
+
+ void enter_locked();
+ void enter_under_threshold();
+ void enter_looking();
+
+ static int add_index(int a, int b)
+ {
+ int t = a + b;
+ if(t >= OVERSAMPLE)
+ t -= OVERSAMPLE;
+ assert(t >= 0 && t < OVERSAMPLE);
+ return t;
+ }
+
+ static int sub_index(int a, int b)
+ {
+ int t = a - b;
+ if(t < 0)
+ t += OVERSAMPLE;
+ assert(t >= 0 && t < OVERSAMPLE);
+ return t;
+ }
+
+ public:
+ ~digital_simple_correlator();
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GR_SIMPLE_CORRELATOR_H */
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index 6f83ff036..7ac16602c 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -136,6 +136,7 @@ list(APPEND gr_digital_sources
digital_probe_mpsk_snr_est_c.cc
digital_scrambler_bb.cc
digital_simple_framer.cc
+ digital_simple_correlator.cc
)
list(APPEND digital_libs
diff --git a/gr-digital/lib/digital_simple_correlator.cc b/gr-digital/lib/digital_simple_correlator.cc
new file mode 100644
index 000000000..37ef2f1e5
--- /dev/null
+++ b/gr-digital/lib/digital_simple_correlator.cc
@@ -0,0 +1,231 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital_simple_correlator.h>
+#include <digital_simple_framer_sync.h>
+#include <gr_io_signature.h>
+#include <gr_count_bits.h>
+#include <assert.h>
+#include <stdexcept>
+#include <string.h>
+#include <cstdio>
+
+static const int THRESHOLD = 3;
+
+digital_simple_correlator_sptr
+digital_make_simple_correlator(int payload_bytesize)
+{
+ return gnuradio::get_initial_sptr
+ (new digital_simple_correlator(payload_bytesize));
+}
+
+digital_simple_correlator::digital_simple_correlator(int payload_bytesize)
+ : gr_block("simple_correlator",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(unsigned char))),
+ d_payload_bytesize(payload_bytesize),
+ d_state(ST_LOOKING), d_osi(0),
+ d_bblen((payload_bytesize + GRSF_PAYLOAD_OVERHEAD) * GRSF_BITS_PER_BYTE),
+ d_bitbuf(new unsigned char[d_bblen]),
+ d_pktbuf(new unsigned char[d_bblen/GRSF_BITS_PER_BYTE]),
+ d_bbi(0)
+{
+ d_avbi = 0;
+ d_accum = 0.0;
+ d_avg = 0.0;
+ for(int i = 0; i < AVG_PERIOD; i++)
+ d_avgbuf[i] = 0.0;
+
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ d_debug_fp = fopen("corr.log", "w");
+#endif
+ enter_looking();
+}
+
+digital_simple_correlator::~digital_simple_correlator()
+{
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ fclose(d_debug_fp);
+#endif
+ delete [] d_bitbuf;
+ delete [] d_pktbuf;
+}
+
+void
+digital_simple_correlator::enter_looking()
+{
+ fflush(stdout);
+ // fprintf(stderr, ">>> enter_looking\n");
+ d_state = ST_LOOKING;
+ for(int i = 0; i < OVERSAMPLE; i++)
+ d_shift_reg[i] = 0;
+ d_osi = 0;
+
+ d_avbi = 0;
+ d_avg = d_avg * 0.5;
+ d_accum = 0;
+ for(int i = 0; i < AVG_PERIOD; i++)
+ d_avgbuf[i] = 0.0;
+}
+
+void
+digital_simple_correlator::enter_under_threshold()
+{
+ fflush(stdout);
+ // fprintf(stderr, ">>> enter_under_threshold\n");
+ d_state = ST_UNDER_THRESHOLD;
+ d_transition_osi = d_osi;
+}
+
+void
+digital_simple_correlator::enter_locked()
+{
+ d_state = ST_LOCKED;
+ int delta = sub_index(d_osi, d_transition_osi);
+ d_center_osi = add_index(d_transition_osi, delta/2);
+ //d_center_osi = add_index(d_center_osi, 3); // FIXME
+ d_bbi = 0;
+ fflush(stdout);
+ // fprintf(stderr, ">>> enter_locked d_center_osi = %d\n", d_center_osi);
+
+ d_avg = std::max(-1.0, std::min(1.0, d_accum * (1.0/AVG_PERIOD)));
+ // fprintf(stderr, ">>> enter_locked d_avg = %g\n", d_avg);
+}
+
+static void
+packit(unsigned char *pktbuf, const unsigned char *bitbuf, int bitcount)
+{
+ for(int i = 0; i < bitcount; i += 8) {
+ int t = bitbuf[i+0] & 0x1;
+ t = (t << 1) | (bitbuf[i+1] & 0x1);
+ t = (t << 1) | (bitbuf[i+2] & 0x1);
+ t = (t << 1) | (bitbuf[i+3] & 0x1);
+ t = (t << 1) | (bitbuf[i+4] & 0x1);
+ t = (t << 1) | (bitbuf[i+5] & 0x1);
+ t = (t << 1) | (bitbuf[i+6] & 0x1);
+ t = (t << 1) | (bitbuf[i+7] & 0x1);
+ *pktbuf++ = t;
+ }
+}
+
+void
+digital_simple_correlator::update_avg(float x)
+{
+ d_accum -= d_avgbuf[d_avbi];
+ d_avgbuf[d_avbi] = x;
+ d_accum += x;
+ d_avbi = (d_avbi + 1) & (AVG_PERIOD-1);
+}
+
+int
+digital_simple_correlator::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const float *in = (const float*)input_items[0];
+ unsigned char *out = (unsigned char*)output_items[0];
+
+ int n = 0;
+ int nin = ninput_items[0];
+ int decision;
+ int hamming_dist;
+
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ struct debug_data {
+ float raw_data;
+ float sampled;
+ float enter_locked;
+ } debug_data;
+#endif
+
+ while(n < nin) {
+
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ debug_data.raw_data = in[n];
+ debug_data.sampled = 0.0;
+ debug_data.enter_locked = 0.0;
+#endif
+
+ switch(d_state) {
+ case ST_LOCKED:
+ if(d_osi == d_center_osi) {
+
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ debug_data.sampled = 1.0;
+#endif
+ decision = slice(in[n]);
+
+ d_bitbuf[d_bbi] = decision;
+ d_bbi++;
+ if(d_bbi >= d_bblen) {
+ // printf("got whole packet\n");
+ packit(d_pktbuf, d_bitbuf, d_bbi);
+ //printf("seqno %3d\n", d_pktbuf[0]);
+ memcpy(out, &d_pktbuf[GRSF_PAYLOAD_OVERHEAD], d_payload_bytesize);
+ enter_looking();
+ consume_each(n + 1);
+ return d_payload_bytesize;
+ }
+ }
+ break;
+
+ case ST_LOOKING:
+ case ST_UNDER_THRESHOLD:
+ update_avg(in[n]);
+ decision = slice(in[n]);
+
+ d_shift_reg[d_osi] = (d_shift_reg[d_osi] << 1) | decision;
+ hamming_dist = gr_count_bits64(d_shift_reg[d_osi] ^ GRSF_SYNC);
+ //fprintf(stderr, "%2d %d\n", hamming_dist, d_osi);
+
+ if(d_state == ST_LOOKING && hamming_dist <= THRESHOLD) {
+ // We're seeing a good PN code, remember location
+ enter_under_threshold();
+ }
+ else if(d_state == ST_UNDER_THRESHOLD && hamming_dist > THRESHOLD) {
+ // no longer seeing good PN code, compute center of goodness
+ enter_locked();
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ debug_data.enter_locked = 1.0;
+#endif
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+#ifdef DEBUG_SIMPLE_CORRELATOR
+ fwrite(&debug_data, sizeof(debug_data), 1, d_debug_fp);
+#endif
+
+ d_osi = add_index(d_osi, 1);
+ n++;
+ }
+
+ consume_each(n);
+ return 0;
+}
diff --git a/gr-digital/python/qa_simple_correlator.py b/gr-digital/python/qa_simple_correlator.py
new file mode 100755
index 000000000..124201a55
--- /dev/null
+++ b/gr-digital/python/qa_simple_correlator.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, gr_unittest
+import digital_swig as digital
+
+class test_simple_correlator(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_00(self):
+ expected_result = (
+ 0x00, 0x11, 0x22, 0x33,
+ 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb,
+ 0xcc, 0xdd, 0xee, 0xff)
+
+ # Filter taps to expand the data to oversample by 8
+ # Just using a RRC for some basic filter shape
+ taps = gr.firdes.root_raised_cosine(8, 8, 1.0, 0.5, 21)
+
+ src = gr.vector_source_b(expected_result)
+ frame = digital.simple_framer(4)
+ unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
+ expand = gr.interp_fir_filter_fff(8, taps)
+ b2f = gr.char_to_float()
+ mult2 = gr.multiply_const_ff(2)
+ sub1 = gr.add_const_ff(-1)
+ op = digital.simple_correlator(4)
+ dst = gr.vector_sink_b()
+ self.tb.connect(src, frame, unpack, b2f, mult2, sub1, expand)
+ self.tb.connect(expand, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+
+ self.assertEqual(expected_result, result_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_simple_correlator, "test_simple_correlator.xml")
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index 746bc6111..4107116bc 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -176,6 +176,7 @@ install(
digital_probe_mpsk_snr_est_c.i
digital_scrambler_bb.i
digital_simple_framer.i
+ digital_simple_correlator.i
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
COMPONENT "digital_swig"
)
diff --git a/gr-digital/swig/digital_simple_correlator.i b/gr-digital/swig/digital_simple_correlator.i
new file mode 100644
index 000000000..5ad5ca26c
--- /dev/null
+++ b/gr-digital/swig/digital_simple_correlator.i
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital,simple_correlator);
+
+digital_simple_correlator_sptr digital_make_simple_correlator(int payload_bytesize);
+
+class digital_simple_correlator : public gr_block
+{
+ private:
+ digital_simple_correlator(int payload_bytesize);
+};
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 191076d75..a5f0251a4 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -81,6 +81,7 @@ enum snr_est_type_t {
#include "digital_probe_mpsk_snr_est_c.h"
#include "digital_scrambler_bb.h"
#include "digital_simple_framer.h"
+#include "digital_simple_correlator.h"
%}
%include "digital_additive_scrambler_bb.i"
@@ -125,3 +126,4 @@ enum snr_est_type_t {
%include "digital_probe_mpsk_snr_est_c.i"
%include "digital_scrambler_bb.i"
%include "digital_simple_framer.i"
+%include "digital_simple_correlator.i"
diff --git a/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py b/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py
index 0132ab86f..304109a8e 100644
--- a/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py
+++ b/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py
@@ -1,23 +1,23 @@
#
# Copyright 2010 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.
-#
+#
"""
Classes providing more user-friendly interfaces to the doxygen xml
docs than the generated classes provide.
@@ -40,7 +40,7 @@ class DoxyIndex(Base):
if self._parsed:
return
super(DoxyIndex, self)._parse()
- self._root = index.parse(os.path.join(self._xml_path, 'index.xml'))
+ self._root = index.parse(os.path.join(self._xml_path, 'index.xml'))
for mem in self._root.compound:
converted = self.convert_mem(mem)
# For files we want the contents to be accessible directly
@@ -78,7 +78,24 @@ class DoxyCompMem(Base):
bd = description(getattr(parse_data, 'briefdescription', None))
dd = description(getattr(parse_data, 'detaileddescription', None))
self._data['brief_description'] = bd
- self._data['detailed_description'] = dd
+ self._data['detailed_description'] = dd
+
+ def set_parameters(self, data):
+ vs = [ddc.value for ddc in data.detaileddescription.content_]
+ pls = []
+ for v in vs:
+ if hasattr(v, 'parameterlist'):
+ pls += v.parameterlist
+ pis = []
+ for pl in pls:
+ pis += pl.parameteritem
+ dpis = []
+ for pi in pis:
+ dpi = DoxyParameterItem(pi)
+ dpi._parse()
+ dpis.append(dpi)
+ self._data['params'] = dpis
+
class DoxyCompound(DoxyCompMem):
pass
@@ -86,7 +103,6 @@ class DoxyCompound(DoxyCompMem):
class DoxyMember(DoxyCompMem):
pass
-
class DoxyFunction(DoxyMember):
__module__ = "gnuradio.utils.doxyxml"
@@ -98,10 +114,13 @@ class DoxyFunction(DoxyMember):
return
super(DoxyFunction, self)._parse()
self.set_descriptions(self._parse_data)
- self._data['params'] = []
- prms = self._parse_data.param
- for prm in prms:
- self._data['params'].append(DoxyParam(prm))
+ self.set_parameters(self._parse_data)
+ if not self._data['params']:
+ # If the params weren't set by a comment then just grab the names.
+ self._data['params'] = []
+ prms = self._parse_data.param
+ for prm in prms:
+ self._data['params'].append(DoxyParam(prm))
brief_description = property(lambda self: self.data()['brief_description'])
detailed_description = property(lambda self: self.data()['detailed_description'])
@@ -111,7 +130,7 @@ Base.mem_classes.append(DoxyFunction)
class DoxyParam(DoxyMember):
-
+
__module__ = "gnuradio.utils.doxyxml"
def _parse(self):
@@ -121,16 +140,46 @@ class DoxyParam(DoxyMember):
self.set_descriptions(self._parse_data)
self._data['declname'] = self._parse_data.declname
+ @property
+ def description(self):
+ descriptions = []
+ if self.brief_description:
+ descriptions.append(self.brief_description)
+ if self.detailed_description:
+ descriptions.append(self.detailed_description)
+ return '\n\n'.join(descriptions)
+
brief_description = property(lambda self: self.data()['brief_description'])
detailed_description = property(lambda self: self.data()['detailed_description'])
- declname = property(lambda self: self.data()['declname'])
+ name = property(lambda self: self.data()['declname'])
-class DoxyClass(DoxyCompound):
+class DoxyParameterItem(DoxyMember):
+ """A different representation of a parameter in Doxygen."""
+
+ def _parse(self):
+ if self._parsed:
+ return
+ super(DoxyParameterItem, self)._parse()
+ names = []
+ for nl in self._parse_data.parameternamelist:
+ for pn in nl.parametername:
+ names.append(description(pn))
+ # Just take first name
+ self._data['name'] = names[0]
+ # Get description
+ pd = description(self._parse_data.get_parameterdescription())
+ self._data['description'] = pd
+
+ description = property(lambda self: self.data()['description'])
+ name = property(lambda self: self.data()['name'])
+
+class DoxyClass(DoxyCompound):
+
__module__ = "gnuradio.utils.doxyxml"
kind = 'class'
-
+
def _parse(self):
if self._parsed:
return
@@ -139,22 +188,24 @@ class DoxyClass(DoxyCompound):
if self._error:
return
self.set_descriptions(self._retrieved_data.compounddef)
+ self.set_parameters(self._retrieved_data.compounddef)
# Sectiondef.kind tells about whether private or public.
# We just ignore this for now.
self.process_memberdefs()
brief_description = property(lambda self: self.data()['brief_description'])
detailed_description = property(lambda self: self.data()['detailed_description'])
+ params = property(lambda self: self.data()['params'])
Base.mem_classes.append(DoxyClass)
-
+
class DoxyFile(DoxyCompound):
-
+
__module__ = "gnuradio.utils.doxyxml"
kind = 'file'
-
+
def _parse(self):
if self._parsed:
return
@@ -164,7 +215,7 @@ class DoxyFile(DoxyCompound):
if self._error:
return
self.process_memberdefs()
-
+
brief_description = property(lambda self: self.data()['brief_description'])
detailed_description = property(lambda self: self.data()['detailed_description'])
@@ -172,16 +223,16 @@ Base.mem_classes.append(DoxyFile)
class DoxyNamespace(DoxyCompound):
-
+
__module__ = "gnuradio.utils.doxyxml"
kind = 'namespace'
-
+
Base.mem_classes.append(DoxyNamespace)
class DoxyGroup(DoxyCompound):
-
+
__module__ = "gnuradio.utils.doxyxml"
kind = 'group'
@@ -209,7 +260,7 @@ class DoxyGroup(DoxyCompound):
self.process_memberdefs()
title = property(lambda self: self.data()['title'])
-
+
Base.mem_classes.append(DoxyGroup)
@@ -224,7 +275,7 @@ Base.mem_classes.append(DoxyFriend)
class DoxyOther(Base):
-
+
__module__ = "gnuradio.utils.doxyxml"
kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum', 'dir', 'page'])
@@ -232,6 +283,6 @@ class DoxyOther(Base):
@classmethod
def can_parse(cls, obj):
return obj.kind in cls.kinds
-
+
Base.mem_classes.append(DoxyOther)
diff --git a/gr-howto-write-a-block/docs/doxygen/swig_doc.py b/gr-howto-write-a-block/docs/doxygen/swig_doc.py
index 4e1ce2e47..f24608b3e 100644
--- a/gr-howto-write-a-block/docs/doxygen/swig_doc.py
+++ b/gr-howto-write-a-block/docs/doxygen/swig_doc.py
@@ -1,23 +1,23 @@
#
-# Copyright 2010,2011 Free Software Foundation, Inc.
-#
+# Copyright 2010-2012 Free Software Foundation, Inc.
+#
# This file is part of GNU Radio
-#
+#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
-#
+#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
-#
+#
"""
Creates the swig_doc.i SWIG interface file.
Execute using: python swig_doc.py xml_path outputfilename
@@ -27,13 +27,10 @@ python docstrings.
"""
-import sys
-
-try:
- from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
-except ImportError:
- from gnuradio.doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
+import sys, time
+from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile
+from doxyxml import DoxyOther, base
def py_name(name):
bits = name.split('_')
@@ -56,8 +53,29 @@ class Block(object):
# Check for a parsing error.
if item.error():
return False
- return item.has_member(make_name(item.name()), DoxyFriend)
-
+ friendname = make_name(item.name())
+ is_a_block = item.has_member(friendname, DoxyFriend)
+ # But now sometimes the make function isn't a friend so check again.
+ if not is_a_block:
+ is_a_block = di.has_member(friendname, DoxyFunction)
+ return is_a_block
+
+class Block2(object):
+ """
+ Checks if doxyxml produced objects correspond to a new style
+ gnuradio block.
+ """
+
+ @classmethod
+ def includes(cls, item):
+ if not isinstance(item, DoxyClass):
+ return False
+ # Check for a parsing error.
+ if item.error():
+ return False
+ is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther)
+ return is_a_block2
+
def utoascii(text):
"""
@@ -82,13 +100,19 @@ def combine_descriptions(obj):
if dd:
description.append(dd)
return utoascii('\n\n'.join(description)).strip()
-
+
+def format_params(parameteritems):
+ output = ['Args:']
+ template = ' {0} : {1}'
+ for pi in parameteritems:
+ output.append(template.format(pi.name, pi.description))
+ return '\n'.join(output)
entry_templ = '%feature("docstring") {name} "{docstring}"'
-def make_entry(obj, name=None, templ="{description}", description=None):
+def make_entry(obj, name=None, templ="{description}", description=None, params=[]):
"""
Create a docstring entry for a swig interface file.
-
+
obj - a doxyxml object from which documentation will be extracted.
name - the name of the C object (defaults to obj.name())
templ - an optional template for the docstring containing only one
@@ -102,6 +126,9 @@ def make_entry(obj, name=None, templ="{description}", description=None):
return ''
if description is None:
description = combine_descriptions(obj)
+ if params:
+ description += '\n\n'
+ description += utoascii(format_params(params))
docstring = templ.format(description=description)
if not docstring:
return ''
@@ -121,27 +148,31 @@ def make_func_entry(func, name=None, description=None, params=None):
used as the description instead of extracting it from func.
params - a parameter list that overrides using func.params.
"""
- if params is None:
- params = func.params
- params = [prm.declname for prm in params]
- if params:
- sig = "Params: (%s)" % ", ".join(params)
- else:
- sig = "Params: (NONE)"
- templ = "{description}\n\n" + sig
- return make_entry(func, name=name, templ=utoascii(templ),
- description=description)
-
-
-def make_class_entry(klass, description=None):
+ #if params is None:
+ # params = func.params
+ #params = [prm.declname for prm in params]
+ #if params:
+ # sig = "Params: (%s)" % ", ".join(params)
+ #else:
+ # sig = "Params: (NONE)"
+ #templ = "{description}\n\n" + sig
+ #return make_entry(func, name=name, templ=utoascii(templ),
+ # description=description)
+ return make_entry(func, name=name, description=description, params=params)
+
+
+def make_class_entry(klass, description=None, ignored_methods=[], params=None):
"""
Create a class docstring for a swig interface file.
"""
+ if params is None:
+ params = klass.params
output = []
- output.append(make_entry(klass, description=description))
+ output.append(make_entry(klass, description=description, params=params))
for func in klass.in_category(DoxyFunction):
- name = klass.name() + '::' + func.name()
- output.append(make_func_entry(func, name=name))
+ if func.name() not in ignored_methods:
+ name = klass.name() + '::' + func.name()
+ output.append(make_func_entry(func, name=name))
return "\n\n".join(output)
@@ -175,18 +206,38 @@ def make_block_entry(di, block):
# the make function.
output = []
output.append(make_class_entry(block, description=super_description))
- creator = block.get_member(block.name(), DoxyFunction)
output.append(make_func_entry(make_func, description=super_description,
- params=creator.params))
+ params=block.params))
return "\n\n".join(output)
+def make_block2_entry(di, block):
+ """
+ Create class and function docstrings of a new style gnuradio block for a
+ swig interface file.
+ """
+ descriptions = []
+ # For new style blocks all the relevant documentation should be
+ # associated with the 'make' method.
+ make_func = block.get_member('make', DoxyFunction)
+ description = combine_descriptions(make_func)
+ # Associate the combined description with the class and
+ # the make function.
+ output = []
+ #output.append(make_class_entry(
+ # block, description=description,
+ # ignored_methods=['make'], params=make_func.params))
+ makename = block.name() + '::make'
+ output.append(make_func_entry(
+ make_func, name=makename, description=description,
+ params=make_func.params))
+ return "\n\n".join(output)
def make_swig_interface_file(di, swigdocfilename, custom_output=None):
-
+
output = ["""
/*
* This file was automatically generated using swig_doc.py.
- *
+ *
* Any changes to it will be lost next time it is regenerated.
*/
"""]
@@ -196,32 +247,52 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None):
# Create docstrings for the blocks.
blocks = di.in_category(Block)
+ blocks2 = di.in_category(Block2)
+
make_funcs = set([])
for block in blocks:
try:
make_func = di.get_member(make_name(block.name()), DoxyFunction)
- make_funcs.add(make_func.name())
- output.append(make_block_entry(di, block))
+ # Don't want to risk writing to output twice.
+ if make_func.name() not in make_funcs:
+ make_funcs.add(make_func.name())
+ output.append(make_block_entry(di, block))
+ except block.ParsingError:
+ sys.stderr.write('Parsing error for block {0}\n'.format(block.name()))
+ raise
+
+ for block in blocks2:
+ try:
+ make_func = block.get_member('make', DoxyFunction)
+ make_func_name = block.name() +'::make'
+ # Don't want to risk writing to output twice.
+ if make_func_name not in make_funcs:
+ make_funcs.add(make_func_name)
+ output.append(make_block2_entry(di, block))
except block.ParsingError:
- print('Parsing error for block %s' % block.name())
+ sys.stderr.write('Parsing error for block {0}\n'.format(block.name()))
+ raise
# Create docstrings for functions
# Don't include the make functions since they have already been dealt with.
- funcs = [f for f in di.in_category(DoxyFunction) if f.name() not in make_funcs]
+ funcs = [f for f in di.in_category(DoxyFunction)
+ if f.name() not in make_funcs and not f.name().startswith('std::')]
for f in funcs:
try:
output.append(make_func_entry(f))
except f.ParsingError:
- print('Parsing error for function %s' % f.name())
+ sys.stderr.write('Parsing error for function {0}\n'.format(f.name()))
# Create docstrings for classes
block_names = [block.name() for block in blocks]
- klasses = [k for k in di.in_category(DoxyClass) if k.name() not in block_names]
+ block_names += [block.name() for block in blocks2]
+ klasses = [k for k in di.in_category(DoxyClass)
+ if k.name() not in block_names and not k.name().startswith('std::')]
for k in klasses:
try:
output.append(make_class_entry(k))
except k.ParsingError:
- print('Parsing error for class %s' % k.name())
+ sys.stderr.write('Parsing error for class {0}\n'.format(k.name()))
# Docstrings are not created for anything that is not a function or a class.
# If this excludes anything important please add it here.
diff --git a/gr-utils/src/python/modtool/templates.py b/gr-utils/src/python/modtool/templates.py
index 877735711..bfdba19c0 100644
--- a/gr-utils/src/python/modtool/templates.py
+++ b/gr-utils/src/python/modtool/templates.py
@@ -495,15 +495,13 @@ gr_modtool help -- Show a list of commands.
gr_modtool help <command> -- Shows the help for a given command. '''
# SWIG string
-Templates['swig_block_magic'] = """#if $version == '37'
-#set $mod_block_sep = '/'
-#set $block_magic_version = '2'
+Templates['swig_block_magic'] = """#if $version == '36'
+GR_SWIG_BLOCK_MAGIC($modname, $blockname);
+%include "${modname}_${blockname}.h"
#else
-#set $mod_block_sep = '_'
-#set $block_magic_version = ''
-#end if
-%include "${modname}${mod_block_sep}${blockname}.h"
-GR_SWIG_BLOCK_MAGIC${block_magic_version}($modname, $blockname);
+%include "${modname}/${blockname}.h"
+GR_SWIG_BLOCK_MAGIC2($modname, $blockname);
+#end
"""
## Old stuff
diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml
index 4d73fbd9c..964f95756 100644
--- a/grc/blocks/gr_message_debug.xml
+++ b/grc/blocks/gr_message_debug.xml
@@ -20,7 +20,7 @@
<optional>1</optional>
</sink>
<sink>
- <name>print_pdu_verbose</name>
+ <name>print_pdu</name>
<type>message</type>
<optional>1</optional>
</sink>
diff --git a/grc/blocks/gr_pdu_to_tagged_stream.xml b/grc/blocks/gr_pdu_to_tagged_stream.xml
index fc1c4d16a..6d2fea97e 100644
--- a/grc/blocks/gr_pdu_to_tagged_stream.xml
+++ b/grc/blocks/gr_pdu_to_tagged_stream.xml
@@ -16,17 +16,17 @@
<option>
<name>Byte</name>
<key>byte</key>
- <opt>tv:gr.BYTE</opt>
+ <opt>tv:gr.pdu_byte</opt>
</option>
<option>
<name>Complex</name>
<key>complex</key>
- <opt>tv:gr.COMPLEX</opt>
+ <opt>tv:gr.pdu_complex</opt>
</option>
<option>
<name>Float</name>
<key>float</key>
- <opt>tv:gr.FLOAT</opt>
+ <opt>tv:gr.pdu_float</opt>
</option>
</param>
<sink>
diff --git a/grc/blocks/gr_tagged_stream_to_pdu.xml b/grc/blocks/gr_tagged_stream_to_pdu.xml
index e70a01608..e2f754c9e 100644
--- a/grc/blocks/gr_tagged_stream_to_pdu.xml
+++ b/grc/blocks/gr_tagged_stream_to_pdu.xml
@@ -16,17 +16,17 @@
<option>
<name>Byte</name>
<key>byte</key>
- <opt>tv:gr.BYTE</opt>
+ <opt>tv:gr.pdu_byte</opt>
</option>
<option>
<name>Complex</name>
<key>complex</key>
- <opt>tv:gr.COMPLEX</opt>
+ <opt>tv:gr.pdu_complex</opt>
</option>
<option>
<name>Float</name>
<key>float</key>
- <opt>tv:gr.FLOAT</opt>
+ <opt>tv:gr.pdu_float</opt>
</option>
</param>
<sink>
diff --git a/grc/python/extract_docs.py b/grc/python/extract_docs.py
index a7e945c37..33c404362 100644
--- a/grc/python/extract_docs.py
+++ b/grc/python/extract_docs.py
@@ -31,7 +31,13 @@ def _extract(key):
module_name, constructor_name = key.split('_', 1)
module = __import__('gnuradio.'+module_name)
module = getattr(module, module_name)
- except: return ''
+ except ImportError:
+ try:
+ module_name, constructor_name = key.split('_', 1)
+ module = __import__(module_name)
+ except: return ''
+ except:
+ return ''
pattern = constructor_name.replace('_', '_*').replace('x', '\w')
pattern_matcher = re.compile('^%s\w*$'%pattern)
matches = filter(lambda x: pattern_matcher.match(x), dir(module))
diff --git a/volk/CMakeLists.txt b/volk/CMakeLists.txt
index 9519505eb..99f705256 100644
--- a/volk/CMakeLists.txt
+++ b/volk/CMakeLists.txt
@@ -62,6 +62,18 @@ if(NOT CHEETAH_FOUND)
message(FATAL_ERROR "Cheetah templates required to build VOLK")
endif()
+if(MSVC)
+ if (NOT DEFINED BOOST_ALL_DYN_LINK)
+ set(BOOST_ALL_DYN_LINK TRUE)
+ endif()
+ set(BOOST_ALL_DYN_LINK "${BOOST_ALL_DYN_LINK}" CACHE BOOL "boost enable dynamic linking")
+ if(BOOST_ALL_DYN_LINK)
+ add_definitions(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc
+ else(BOOST_ALL_DYN_LINK)
+ unset(BOOST_REQUIRED_COMPONENTS) #empty components list for static link
+ endif(BOOST_ALL_DYN_LINK)
+endif(MSVC)
+
set(Boost_ADDITIONAL_VERSIONS
"1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39"
"1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44"
@@ -71,7 +83,7 @@ set(Boost_ADDITIONAL_VERSIONS
"1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64"
"1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69"
)
-find_package(Boost COMPONENTS unit_test_framework)
+find_package(Boost COMPONENTS unit_test_framework filesystem system)
if(NOT Boost_FOUND)
message(FATAL_ERROR "VOLK Requires boost to build")
diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc
index 648f4d878..e0919a278 100644
--- a/volk/apps/volk_profile.cc
+++ b/volk/apps/volk_profile.cc
@@ -1,15 +1,19 @@
#include "qa_utils.h"
-extern "C" {
+
#include <volk/volk.h>
#include <volk/volk_prefs.h>
-}
+
+#include <ciso646>
#include <vector>
#include <boost/foreach.hpp>
+#include <boost/filesystem.hpp>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
+namespace fs = boost::filesystem;
+
int main(int argc, char *argv[]) {
std::vector<std::string> results;
@@ -123,25 +127,20 @@ int main(int argc, char *argv[]) {
VOLK_PROFILE(volk_32f_s32f_multiply_32f_a, 1e-4, 1.0, 204600, 10000, &results);
VOLK_PROFILE(volk_32f_s32f_multiply_32f_u, 1e-4, 0, 204600, 1000, &results);
-
- char path[256];
+ char path[1024];
get_config_path(path);
- std::string config_path(path);
- std::ofstream config;
- std::cout << "filename: " << config_path << std::endl;
- config.open(config_path.c_str());
+ const fs::path config_path(path);
+
+ if (not fs::exists(config_path.branch_path()))
+ {
+ std::cout << "Creating " << config_path.branch_path() << "..." << std::endl;
+ fs::create_directories(config_path.branch_path());
+ }
+
+ std::cout << "Writing " << config_path << "..." << std::endl;
+ std::ofstream config(config_path.string().c_str());
if(!config.is_open()) { //either we don't have write access or we don't have the dir yet
- std::string dir(getenv("HOME"));
- dir += "/.volk";
- if(mkdir(dir.c_str(), 0777) == -1) {
- std::cout << "Error creating directory " << dir << std::endl;
- return -1;
- }
- config.open(config_path.c_str());
- if(!config.is_open()) {
- std::cout << "Error opening file " << config_path << std::endl;
- return -1;
- }
+ std::cout << "Error opening file " << config_path << std::endl;
}
config << "\